On Tue, 8 May 2007, Oliver Neukum wrote: > Hi, > > this shows how the anchors can be used for doing reset support. > Hibernate, when we get it should be similar.
I'll have more comments on this later. But first, I think we should be able to get rid of the skel_open_lock mutex plus similar mutexes in other USB drivers. The problem they address is the race between open() and disconnect() -- or more accurately, open() and unregister_dev(). It should be fixed once and for all in usbcore. And without relying on the BKL. How do you like this approach? Alan Stern Index: usb-2.6/drivers/usb/core/file.c =================================================================== --- usb-2.6.orig/drivers/usb/core/file.c +++ usb-2.6/drivers/usb/core/file.c @@ -16,15 +16,15 @@ */ #include <linux/module.h> -#include <linux/spinlock.h> #include <linux/errno.h> +#include <linux/rwsem.h> #include <linux/usb.h> #include "usb.h" #define MAX_USB_MINORS 256 static const struct file_operations *usb_minors[MAX_USB_MINORS]; -static DEFINE_SPINLOCK(minor_lock); +static DECLARE_RWSEM(minor_rwsem); static int usb_open(struct inode * inode, struct file * file) { @@ -33,14 +33,11 @@ static int usb_open(struct inode * inode int err = -ENODEV; const struct file_operations *old_fops, *new_fops = NULL; - spin_lock (&minor_lock); + down_read(&minor_rwsem); c = usb_minors[minor]; - if (!c || !(new_fops = fops_get(c))) { - spin_unlock(&minor_lock); - return err; - } - spin_unlock(&minor_lock); + if (!c || !(new_fops = fops_get(c))) + goto done; old_fops = file->f_op; file->f_op = new_fops; @@ -52,6 +49,8 @@ static int usb_open(struct inode * inode file->f_op = fops_get(old_fops); } fops_put(old_fops); + done: + up_read(&minor_rwsem); return err; } @@ -124,7 +123,7 @@ int usb_register_dev(struct usb_interfac if (class_driver->fops == NULL) goto exit; - spin_lock (&minor_lock); + down_write(&minor_rwsem); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { if (usb_minors[minor]) continue; @@ -134,7 +133,7 @@ int usb_register_dev(struct usb_interfac retval = 0; break; } - spin_unlock (&minor_lock); + up_write(&minor_rwsem); if (retval) goto exit; @@ -150,9 +149,9 @@ int usb_register_dev(struct usb_interfac intf->usb_dev = device_create(&usb_class, &intf->dev, MKDEV(USB_MAJOR, minor), "%s", temp); if (IS_ERR(intf->usb_dev)) { - spin_lock (&minor_lock); + down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; - spin_unlock (&minor_lock); + up_write(&minor_rwsem); retval = PTR_ERR(intf->usb_dev); } exit: @@ -189,9 +188,9 @@ void usb_deregister_dev(struct usb_inter dbg ("removing %d minor", intf->minor); - spin_lock (&minor_lock); + down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; - spin_unlock (&minor_lock); + up_write(&minor_rwsem); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); device_destroy(&usb_class, MKDEV(USB_MAJOR, intf->minor)); ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel