Hi list,

here is a patch against pre-7 to prevent races with module unload.
It adds a field 'module' to the usb_driver structure. Thus all applicable 
drivers are touched. These are too numerous to contact all maintainers.

It does not work for storage and microtek as it would interfere with scsi 
unregistering. It also does not work with serial, as it and possibly hid and 
videodev, which I still have to look into, use submodules.

I'll make a seperate patch for serial tomorrow.

        Regards
                Oliver


diff -u --recursive --new-file linuxvanilla/drivers/usb/CDCEther.c 
linux/drivers/usb/CDCEther.c
--- linuxvanilla/drivers/usb/CDCEther.c Mon Sep 10 23:39:59 2001
+++ linux/drivers/usb/CDCEther.c        Tue Sep 11 00:01:10 2001
@@ -1245,6 +1245,7 @@
        probe:          CDCEther_probe,
        disconnect:     CDCEther_disconnect,
        id_table:       CDCEther_ids,
+       module :        THIS_MODULE,
 };

 /////////////////////////////////////////////////////////////////////////////
/
diff -u --recursive --new-file linuxvanilla/drivers/usb/acm.c 
linux/drivers/usb/acm.c
--- linuxvanilla/drivers/usb/acm.c      Mon Sep 10 23:39:30 2001
+++ linux/drivers/usb/acm.c     Mon Sep 10 23:59:00 2001
@@ -658,6 +658,7 @@
        probe:          acm_probe,
        disconnect:     acm_disconnect,
        id_table:       acm_ids,
+       module :        THIS_MODULE,
 };

 /*
diff -u --recursive --new-file linuxvanilla/drivers/usb/audio.c 
linux/drivers/usb/audio.c
--- linuxvanilla/drivers/usb/audio.c    Mon Sep 10 23:38:56 2001
+++ linux/drivers/usb/audio.c   Mon Sep 10 23:59:32 2001
@@ -2720,6 +2720,7 @@
        disconnect:     usb_audio_disconnect,
        driver_list:    LIST_HEAD_INIT(usb_audio_driver.driver_list), 
        id_table:       usb_audio_ids,
+       module :        THIS_MODULE,
 };

 static void *find_descriptor(void *descstart, unsigned int desclen, void 
*after, 
diff -u --recursive --new-file linuxvanilla/drivers/usb/bluetooth.c 
linux/drivers/usb/bluetooth.c
--- linuxvanilla/drivers/usb/bluetooth.c        Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/bluetooth.c       Tue Sep 11 00:00:05 2001
@@ -236,6 +236,7 @@
        probe:          usb_bluetooth_probe,
        disconnect:     usb_bluetooth_disconnect,
        id_table:       usb_bluetooth_ids,
+       module :        THIS_MODULE,
 };

 static int                     bluetooth_refcount;
diff -u --recursive --new-file linuxvanilla/drivers/usb/catc.c 
linux/drivers/usb/catc.c
--- linuxvanilla/drivers/usb/catc.c     Mon Sep 10 23:38:56 2001
+++ linux/drivers/usb/catc.c    Tue Sep 11 00:00:37 2001
@@ -740,6 +740,7 @@
        probe:          catc_probe,
        disconnect:     catc_disconnect,
        id_table:       catc_id_table,
+       module :        THIS_MODULE,
 };

 static int __init catc_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/dabusb.c 
linux/drivers/usb/dabusb.c
--- linuxvanilla/drivers/usb/dabusb.c   Mon Sep 10 23:39:59 2001
+++ linux/drivers/usb/dabusb.c  Tue Sep 11 00:01:41 2001
@@ -804,6 +804,7 @@
        fops:           &dabusb_fops,
        minor:          DABUSB_MINOR,
        id_table:       dabusb_ids,
+       module :        THIS_MODULE,
 };

 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file linuxvanilla/drivers/usb/dc2xx.c 
linux/drivers/usb/dc2xx.c
--- linuxvanilla/drivers/usb/dc2xx.c    Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/dc2xx.c   Tue Sep 11 00:02:17 2001
@@ -509,6 +509,7 @@
        disconnect:     camera_disconnect,
 
        fops:           &usb_camera_fops,
+       module :        THIS_MODULE,
        minor:          USB_CAMERA_MINOR_BASE
 };

diff -u --recursive --new-file linuxvanilla/drivers/usb/dsbr100.c 
linux/drivers/usb/dsbr100.c
--- linuxvanilla/drivers/usb/dsbr100.c  Mon Sep 10 23:39:30 2001
+++ linux/drivers/usb/dsbr100.c Tue Sep 11 00:02:48 2001
@@ -124,6 +124,7 @@
        fops:           NULL,
        minor:          0,
        id_table:       usb_dsbr100_table,
+       module :        THIS_MODULE,
 };

 
diff -u --recursive --new-file linuxvanilla/drivers/usb/hid.c 
linux/drivers/usb/hid.c
--- linuxvanilla/drivers/usb/hid.c      Mon Sep 10 23:38:56 2001
+++ linux/drivers/usb/hid.c     Tue Sep 11 00:03:24 2001
@@ -1554,6 +1554,7 @@
        probe:          hid_probe,
        disconnect:     hid_disconnect,
        id_table:       hid_usb_ids,
+       module :        THIS_MODULE,
 };
 
 static int __init hid_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/hub.c 
linux/drivers/usb/hub.c
--- linuxvanilla/drivers/usb/hub.c      Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/hub.c     Tue Sep 11 00:03:59 2001
@@ -855,6 +855,7 @@
        ioctl:          hub_ioctl,
        disconnect:     hub_disconnect,
        id_table:       hub_id_table,
+       module :        THIS_MODULE,
 };

 /*
diff -u --recursive --new-file linuxvanilla/drivers/usb/ibmcam.c 
linux/drivers/usb/ibmcam.c
--- linuxvanilla/drivers/usb/ibmcam.c   Mon Sep 10 23:39:45 2001
+++ linux/drivers/usb/ibmcam.c  Tue Sep 11 00:04:25 2001
@@ -3133,6 +3133,7 @@
        probe:          usb_ibmcam_probe,
        disconnect:     usb_ibmcam_disconnect,
        id_table:       ibmcam_table,
+       module :        THIS_MODULE,
 };
 
 /*
diff -u --recursive --new-file linuxvanilla/drivers/usb/kaweth.c 
linux/drivers/usb/kaweth.c
--- linuxvanilla/drivers/usb/kaweth.c   Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/kaweth.c  Tue Sep 11 00:04:53 2001
@@ -158,6 +158,7 @@
        probe:          kaweth_probe,
        disconnect:     kaweth_disconnect,
        id_table:       usb_klsi_table,
+       module :        THIS_MODULE,
 };

 typedef __u8 eth_addr_t[6];
diff -u --recursive --new-file linuxvanilla/drivers/usb/mdc800.c 
linux/drivers/usb/mdc800.c
--- linuxvanilla/drivers/usb/mdc800.c   Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/mdc800.c  Tue Sep 11 00:05:31 2001
@@ -902,6 +902,7 @@
        disconnect:     mdc800_usb_disconnect,
        fops:           &mdc800_device_ops,
        minor:          MDC800_DEVICE_MINOR_BASE,
+       module :        THIS_MODULE,
        id_table:       mdc800_table
 };

diff -u --recursive --new-file linuxvanilla/drivers/usb/ov511.c 
linux/drivers/usb/ov511.c
--- linuxvanilla/drivers/usb/ov511.c    Mon Sep 10 23:39:45 2001
+++ linux/drivers/usb/ov511.c   Tue Sep 11 00:06:06 2001
@@ -3422,7 +3422,8 @@
        name:           "ov511",
        id_table:       device_table,
        probe:          ov511_probe,
-       disconnect:     ov511_disconnect
+       disconnect:     ov511_disconnect,
+       module :        THIS_MODULE,
 };

 
diff -u --recursive --new-file linuxvanilla/drivers/usb/pegasus.c 
linux/drivers/usb/pegasus.c
--- linuxvanilla/drivers/usb/pegasus.c  Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/pegasus.c Tue Sep 11 00:06:30 2001
@@ -930,6 +930,7 @@
        probe:          pegasus_probe,
        disconnect:     pegasus_disconnect,
        id_table:       pegasus_ids,
+       module :        THIS_MODULE,
 };
 
 int __init pegasus_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/printer.c 
linux/drivers/usb/printer.c
--- linuxvanilla/drivers/usb/printer.c  Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/printer.c Tue Sep 11 00:06:58 2001
@@ -718,6 +718,7 @@
        fops:           &usblp_fops,
        minor:          USBLP_MINOR_BASE,
        id_table:       usblp_ids,
+       module :        THIS_MODULE,
 };

 static int __init usblp_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/rio500.c 
linux/drivers/usb/rio500.c
--- linuxvanilla/drivers/usb/rio500.c   Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/rio500.c  Tue Sep 11 00:07:28 2001
@@ -518,6 +518,7 @@
        fops:           &usb_rio_fops,
        minor:          RIO_MINOR,
        id_table:       rio_table,
+       module :        THIS_MODULE,
 };
 
 int usb_rio_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/scanner.c 
linux/drivers/usb/scanner.c
--- linuxvanilla/drivers/usb/scanner.c  Mon Sep 10 23:39:45 2001
+++ linux/drivers/usb/scanner.c Tue Sep 11 00:08:01 2001
@@ -940,6 +940,7 @@
        id_table:       NULL, /* This would be scanner_device_ids, but we
                                 need to check every USB device, in case
                                 we match a user defined vendor/product ID. */
+       module :        THIS_MODULE,
 };

 void __exit
diff -u --recursive --new-file linuxvanilla/drivers/usb/se401.c 
linux/drivers/usb/se401.c
--- linuxvanilla/drivers/usb/se401.c    Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/se401.c   Tue Sep 11 00:08:28 2001
@@ -1629,7 +1629,8 @@
         id_table:      device_table,
 #endif
        probe:          se401_probe,
-        disconnect:    se401_disconnect
+        disconnect:    se401_disconnect,
+       module :        THIS_MODULE,
 };
 

diff -u --recursive --new-file linuxvanilla/drivers/usb/usb-skeleton.c 
linux/drivers/usb/usb-skeleton.c
--- linuxvanilla/drivers/usb/usb-skeleton.c     Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/usb-skeleton.c    Tue Sep 11 00:08:58 2001
@@ -154,6 +154,7 @@
        fops:           &skel_fops,
        minor:          USB_SKEL_MINOR_BASE,
        id_table:       skel_table,
+       module :        THIS_MODULE,
 };

 
diff -u --recursive --new-file linuxvanilla/drivers/usb/usb.c 
linux/drivers/usb/usb.c
--- linuxvanilla/drivers/usb/usb.c      Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/usb.c     Mon Sep 10 23:55:20 2001
@@ -123,6 +123,20 @@
        read_unlock_irq (&usb_bus_list_lock);
 }

+static void do_driver_disconnect(struct usb_driver *driver,struct usb_device 
*dev, void* priv)
+{
+       /* make sure that the driver is not unloaded */
+       if (driver->module != NULL)
+               __MOD_INC_USE_COUNT(driver->module);
+
+       down(&driver->serialize);
+       driver->disconnect(dev,priv);
+       up(&driver->serialize);
+
+       if (driver->module != NULL)
+               __MOD_DEC_USE_COUNT(driver->module);
+}
+
 /*
  * This function is part of a depth-first search down the device tree,
  * removing any instances of a device driver.
@@ -142,14 +156,12 @@
 
        if (!dev->actconfig)
                return;
-
+
        for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
                struct usb_interface *interface = &dev->actconfig->interface[i];
-
+
                if (interface->driver == driver) {
-                       down(&driver->serialize);
-                       driver->disconnect(dev, interface->private_data);
-                       up(&driver->serialize);
+                       do_driver_disconnect(driver, dev, interface->private_data);
                        /* if driver->disconnect didn't release the interface */
                        if (interface->driver)
                                usb_driver_release_interface(driver, interface);
@@ -668,6 +680,25 @@
        return NULL;
 }
 
+static inline void* do_probe_driver(struct usb_driver* driver,struct 
usb_device *dev,unsigned int ifnum,struct usb_device_id *id)
+{
+
+       void * retval;
+
+       /* make sure that the driver is not unloaded */
+       if (driver->module != NULL)
+               __MOD_INC_USE_COUNT(driver->module);
+
+       down(&driver->serialize);
+       retval = driver->probe(dev,ifnum,id);
+       up(&driver->serialize);
+
+       if (driver->module != NULL)
+               __MOD_DEC_USE_COUNT(driver->module);
+
+       return retval;
+}
+
 /*
  * This entrypoint gets called for each new device.
  *
@@ -717,9 +748,7 @@
                                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);
+                                       do_probe_driver(driver,dev,ifnum,id);
                                        if (private != NULL)
                                                break;
                                }
@@ -729,9 +758,7 @@
                        if (private == NULL)
                                interface->act_altsetting = 0;
                } else { /* "old style" driver */
-                       down(&driver->serialize);
-                       private = driver->probe(dev, ifnum, NULL);
-                       up(&driver->serialize);
+                       do_probe_driver(driver,dev,ifnum,NULL);
                }

                /* probe() may have changed the config on us */
@@ -1013,8 +1040,7 @@
  */
 void usb_free_urb(urb_t* urb)
 {
-       if (urb)
-               kfree(urb);
+       kfree(urb);
 }
 /*-------------------------------------------------------------------*/
 int usb_submit_urb(urb_t *urb)
@@ -1044,8 +1070,7 @@
 {
        api_wrapper_data *awd = (api_wrapper_data *)urb->context;
 
-       if (waitqueue_active(awd->wakeup))
-               wake_up(awd->wakeup);
+       wake_up(awd->wakeup);
 #if 0
        else
                dbg("(blocking_completion): waitqueue empty!"); 
@@ -1702,9 +1727,7 @@
                        struct usb_interface *interface = 
&dev->actconfig->interface[i];
                        struct usb_driver *driver = interface->driver;
                        if (driver) {
-                               down(&driver->serialize);
-                               driver->disconnect(dev, interface->private_data);
-                               up(&driver->serialize);
+                               do_driver_disconnect(driver, dev, 
+interface->private_data);
                                /* if driver->disconnect didn't release the interface 
*/
                                if (interface->driver)
                                        usb_driver_release_interface(driver, 
interface);
diff -u --recursive --new-file linuxvanilla/drivers/usb/usbkbd.c 
linux/drivers/usb/usbkbd.c
--- linuxvanilla/drivers/usb/usbkbd.c   Mon Sep 10 23:39:45 2001
+++ linux/drivers/usb/usbkbd.c  Tue Sep 11 00:09:30 2001
@@ -275,6 +275,7 @@
        probe:          usb_kbd_probe,
        disconnect:     usb_kbd_disconnect,
        id_table:       usb_kbd_id_table,
+       module :        THIS_MODULE,
 };

 static int __init usb_kbd_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/usbmouse.c 
linux/drivers/usb/usbmouse.c
--- linuxvanilla/drivers/usb/usbmouse.c Mon Sep 10 23:38:56 2001
+++ linux/drivers/usb/usbmouse.c        Tue Sep 11 00:09:56 2001
@@ -189,6 +189,7 @@
        probe:          usb_mouse_probe,
        disconnect:     usb_mouse_disconnect,
        id_table:       usb_mouse_id_table,
+       module :        THIS_MODULE,
 };
 
 static int __init usb_mouse_init(void)
diff -u --recursive --new-file linuxvanilla/drivers/usb/usbnet.c 
linux/drivers/usb/usbnet.c
--- linuxvanilla/drivers/usb/usbnet.c   Mon Sep 10 23:40:12 2001
+++ linux/drivers/usb/usbnet.c  Tue Sep 11 00:10:22 2001
@@ -1537,6 +1537,7 @@
        id_table:       products,
        probe:          usbnet_probe,
        disconnect:     usbnet_disconnect,
+       module :        THIS_MODULE,
 };

 /*-------------------------------------------------------------------------*/
diff -u --recursive --new-file linuxvanilla/drivers/usb/uss720.c 
linux/drivers/usb/uss720.c
--- linuxvanilla/drivers/usb/uss720.c   Mon Sep 10 23:38:56 2001
+++ linux/drivers/usb/uss720.c  Tue Sep 11 00:10:48 2001
@@ -647,6 +647,7 @@
        probe:          uss720_probe,
        disconnect:     uss720_disconnect,
        id_table:       uss720_table,
+       module :        THIS_MODULE,
 };
 
 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file linuxvanilla/include/linux/usb.h 
linux/include/linux/usb.h
--- linuxvanilla/include/linux/usb.h    Mon Sep 10 23:40:14 2001
+++ linux/include/linux/usb.h   Mon Sep 10 23:57:31 2001
@@ -399,6 +399,8 @@
 
        struct semaphore serialize;
 
+       struct module * module; /* to manage usage counts while probing and 
disconnecting */
+
        /* ioctl -- userspace apps can talk to drivers through usbdevfs */
        int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to