Messages in this thread Patch in this message | | | Date | Mon, 24 Mar 2003 17:09:21 +0100 (CET) | From | Roman Zippel <> | Subject | Re: [PATCH 1/3] revert register_chrdev_region change |
| |
Hi,
On Mon, 24 Mar 2003, Christoph Hellwig wrote:
> If you look at Roman's patches they don't even hinder your dev_t enlargement > but they provide a singificant benefit. Now I'm personally not yet > completly happy with his interface either because he still uses the > major/minor split, but I'm working on fixing this properly.
BTW I have an updated patch, which stores the major char_device at (0,major), so the remaining space is free for whatever you need. Below is a patch which shows how drivers/usb/core/file.c could look after this. There are of course further cleanups possible. :)
bye, Roman
diff -Nurp -X /home/roman/nodiff linux-2.5.65-bk4-cdev3/drivers/usb/core/file.c linux-2.5.65-bk4-cdev4/drivers/usb/core/file.c --- linux-2.5.65-bk4-cdev3/drivers/usb/core/file.c 2003-03-24 10:26:47.000000000 +0100 +++ linux-2.5.65-bk4-cdev4/drivers/usb/core/file.c 2003-03-24 14:13:37.000000000 +0100 @@ -32,41 +32,9 @@ devfs_handle_t usb_devfs_handle; /* /dev EXPORT_SYMBOL(usb_devfs_handle); #define MAX_USB_MINORS 256 -static struct file_operations *usb_minors[MAX_USB_MINORS]; -static spinlock_t minor_lock = SPIN_LOCK_UNLOCKED; - -static int usb_open(struct inode * inode, struct file * file) -{ - int minor = minor(inode->i_rdev); - struct file_operations *c; - int err = -ENODEV; - struct file_operations *old_fops, *new_fops = NULL; - - spin_lock (&minor_lock); - c = usb_minors[minor]; - - if (!c || !(new_fops = fops_get(c))) { - spin_unlock(&minor_lock); - return err; - } - spin_unlock(&minor_lock); - - old_fops = file->f_op; - file->f_op = new_fops; - /* Curiouser and curiouser... NULL ->open() as "no device" ? */ - if (file->f_op->open) - err = file->f_op->open(inode,file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - fops_put(old_fops); - return err; -} static struct file_operations usb_fops = { .owner = THIS_MODULE, - .open = usb_open, }; int usb_major_init(void) @@ -107,12 +75,9 @@ void usb_major_cleanup(void) * device, and 0 on success, alone with a value that the driver should * use in start_minor. */ -int usb_register_dev (struct file_operations *fops, int minor, int num_minors, int *start_minor) +int usb_register_dev (struct file_operations *fops, int minor, int *start_minor) { int i; - int j; - int good_spot; - int retval = -EINVAL; #ifdef CONFIG_USB_DYNAMIC_MINORS /* @@ -123,37 +88,29 @@ int usb_register_dev (struct file_operat minor = 0; #endif - dbg ("asking for %d minors, starting at %d", num_minors, minor); + dbg ("asking for 1 minors, starting at %d", minor); if (fops == NULL) - goto exit; + return -EINVAL; *start_minor = 0; - spin_lock (&minor_lock); for (i = minor; i < MAX_USB_MINORS; ++i) { - if (usb_minors[i]) - continue; - - good_spot = 1; - for (j = 1; j <= num_minors-1; ++j) - if (usb_minors[i+j]) { - good_spot = 0; - break; + cdev = cdget(MKDEV(USB_MAJOR, i)); + if (!cdev->cd_fops) { + down(&cdev->cd_sem); + if (!cdev->cd_fops) { + dbg("found a minor chunk free, starting at %d", i); + cdev->cd_fops = fops; + up(&cdev->cd_sem); + start_minor = i; + return 0; } - if (good_spot == 0) - continue; - - *start_minor = i; - dbg("found a minor chunk free, starting at %d", i); - for (i = *start_minor; i < (*start_minor + num_minors); ++i) - usb_minors[i] = fops; - - retval = 0; - goto exit; + up(&cdev->cd_sem); + } + cdput(cdev); } -exit: - spin_unlock (&minor_lock); - return retval; + + return -EBUSY; } EXPORT_SYMBOL(usb_register_dev); @@ -169,16 +126,21 @@ EXPORT_SYMBOL(usb_register_dev); * * This should be called by all drivers that use the USB major number. */ -void usb_deregister_dev (int num_minors, int start_minor) +void usb_deregister_dev (int minor) { int i; dbg ("removing %d minors starting at %d", num_minors, start_minor); - spin_lock (&minor_lock); - for (i = start_minor; i < (start_minor + num_minors); ++i) - usb_minors[i] = NULL; - spin_unlock (&minor_lock); + cdev = cdget(MKDEV(USB_MAJOR, minor)); + down(&cdev->cd_sem); + if (cdev->cd_fops) { + cdev->cd_fops = NULL; + cdput(cdev); + } else + printk("usb_deregister_dev: releasing invalid dev %d\n", minor); + up(&cdev->cd_sem); + cdput(cdev); } EXPORT_SYMBOL(usb_deregister_dev); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |