> > The goal is just to minimize the kernel locking time as much as > > possible, with the cost of size, I admit that. > > Why do you think that the BKL or any lock is needed around the test and > set functions? > > I agree module unloading is extreemly racy, but take a look at the > current threads on lkml for some ideas on how to solve this.
TASK A TASK B if (driver->owner) module is unloaded __MOD_INC_USE_COUNT(driver->owner); I've read them. They are, let's say, as yet inconclusive. Anyway, the problem is not limited to 2.5; 2.4 is affected as well. For now all uses of probe/disconnect in usb(dev)fs are full of races, some even exist on UP. I want to reduce there number as far as possible and provide a safe helper for the rest. Unfortunately the BKL issue cannot be hidden. I'll include the current version. It even compiles. Regards Oliver /** * usb_unbind_driver - disconnects a driver from a device * @driver: Driver to be disconnected * @device: usb device to be disconnected * @priv: private pointer passed to device driver * Context: BKL held * * Handles module usage count correctly */ void usb_unbind_driver(struct usb_driver *driver, struct usb_device *device, void *priv) { /* as soon as we increase the module use count we drop the BKL before that we must not sleep */ if (driver->owner) { __MOD_INC_USE_COUNT(driver->owner); unlock_kernel(); } down(&driver->serialize); /* if we sleep here on an umanaged driver the holder of the lock guards against module unload */ driver->disconnect(device, priv); up(&driver->serialize); if (driver->owner) { lock_kernel(); __MOD_DEC_USE_COUNT(driver->owner); } } /** * usb_bind_driver - connect a driver to a device's interface */ void *usb_bind_driver(struct usb_driver *driver, struct usb_device *dev, unsigned int ifnum) { int i; void *private; const struct usb_device_id *id; struct usb_interface *interface; if (driver->owner) { __MOD_INC_USE_COUNT(driver->owner); unlock_kernel(); } interface = &dev->actconfig->interface[ifnum]; id = driver->id_table; /* new style driver? */ if (id) { for (i = 0; i < interface->num_altsetting; i++) { interface->act_altsetting = i; id = usb_match_id(dev, interface, id); if (id) { down(&driver->serialize); private = driver->probe(dev,ifnum,id); up(&driver->serialize); if (private != NULL) break; } } /* if driver not bound, leave defaults unchanged */ if (private == NULL) interface->act_altsetting = 0; } else { /* "old style" driver */ down(&driver->serialize); private = driver->probe(dev, ifnum, NULL); up(&driver->serialize); } if (driver->owner) { lock_kernel(); __MOD_DEC_USE_COUNT(driver->owner); } return private; } ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel