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

Reply via email to