> > 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