Hi,

here is the new one which includes suggestions made,
at least so I hope.

        Regards
                Oliver

You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[EMAIL PROTECTED], 2002-07-02 23:14:07+02:00, [EMAIL PROTECTED]
  - BKL against module unload only where needed




diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c        Tue Jul  2 23:15:46 2002
+++ b/drivers/usb/core/devices.c        Tue Jul  2 23:15:46 2002
@@ -239,6 +239,7 @@
 
        if (start > end)
                return start;
+       lock_kernel(); /* driver might be unloaded */
        start += sprintf(start, format_iface,
                         desc->bInterfaceNumber,
                         desc->bAlternateSetting,
@@ -248,6 +249,7 @@
                         desc->bInterfaceSubClass,
                         desc->bInterfaceProtocol,
                         iface->driver ? iface->driver->name : "(none)");
+       unlock_kernel();
        return start;
 }
 
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c  Tue Jul  2 23:15:46 2002
+++ b/drivers/usb/core/devio.c  Tue Jul  2 23:15:46 2002
@@ -722,14 +722,11 @@
                if (test_bit(i, &ps->ifclaimed))
                        continue;
 
-               if (intf->driver) {
-                       const struct usb_device_id *id;
-                       down(&intf->driver->serialize);
-                       intf->driver->disconnect(ps->dev, intf->private_data);
-                       id = usb_match_id(ps->dev,intf,intf->driver->id_table);
-                       intf->driver->probe(ps->dev, i, id);
-                       up(&intf->driver->serialize);
+               lock_kernel();
+               if (intf->driver && ps->dev) {
+                       usb_bind_driver(intf->driver,ps->dev, i);
                }
+               unlock_kernel();
        }
 
        return 0;
@@ -1092,16 +1089,17 @@
 
        /* disconnect kernel driver from interface, leaving it unbound.  */
        case USBDEVFS_DISCONNECT:
+               /* this function is voodoo. without locking it is a maybe thing */
+               lock_kernel();
                driver = ifp->driver;
                if (driver) {
-                       down (&driver->serialize);
                        dbg ("disconnect '%s' from dev %d interface %d",
                                driver->name, ps->dev->devnum, ctrl.ifno);
-                       driver->disconnect (ps->dev, ifp->private_data);
+                      usb_unbind_driver(ps->dev, ifp);
                        usb_driver_release_interface (driver, ifp);
-                       up (&driver->serialize);
                } else
                        retval = -EINVAL;
+               unlock_kernel();
                break;
 
        /* let kernel drivers try to (re)bind to the interface */
@@ -1111,18 +1109,28 @@
 
        /* talk directly to the interface's driver */
        default:
+               lock_kernel(); /* against module unload */
                driver = ifp->driver;
-               if (driver == 0 || driver->ioctl == 0)
-                       retval = -ENOSYS;
-               else {
-                       if (ifp->driver->owner)
+               if (driver == 0 || driver->ioctl == 0) {
+                       unlock_kernel();
+                       retval = -ENOSYS;
+               } else {
+                       if (ifp->driver->owner) {
                                __MOD_INC_USE_COUNT(ifp->driver->owner);
+                               unlock_kernel();
+                       }
                        /* ifno might usefully be passed ... */
                        retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
                        /* size = min_t(int, size, retval)? */
-                       if (ifp->driver->owner)
+                       if (ifp->driver->owner) {
                                __MOD_DEC_USE_COUNT(ifp->driver->owner);
+                       } else {
+                               unlock_kernel();
+                       }
                }
+               
+               if (retval == -ENOIOCTLCMD)
+                       retval = -ENOTTY;
        }
 
        /* cleanup and return */
@@ -1139,7 +1147,7 @@
 static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
unsigned long arg)
 {
        struct dev_state *ps = (struct dev_state *)file->private_data;
-       int ret = -ENOIOCTLCMD;
+       int ret = -ENOTTY;
 
        if (!(file->f_mode & FMODE_WRITE))
                return -EPERM;
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c    Tue Jul  2 23:15:46 2002
+++ b/drivers/usb/core/hub.c    Tue Jul  2 23:15:46 2002
@@ -1050,8 +1050,6 @@
 
 static int usb_hub_thread(void *__hub)
 {
-       lock_kernel();
-
        /*
         * This thread doesn't need any user-level access,
         * so get rid of all our resources
@@ -1071,8 +1069,6 @@
        } while (!signal_pending(current));
 
        dbg("usb_hub_thread exiting");
-
-       unlock_kernel();
        complete_and_exit(&khubd_exited, 0);
 }
 
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c    Tue Jul  2 23:15:46 2002
+++ b/drivers/usb/core/usb.c    Tue Jul  2 23:15:46 2002
@@ -33,6 +33,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/smp_lock.h>
 
 #ifdef CONFIG_USB_DEBUG
        #define DEBUG
@@ -254,6 +255,96 @@
        up (&usb_bus_list_lock);
 }
 
+/**
+ *     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_device *device, struct usb_interface *intf)
+{
+       struct usb_driver *driver;
+       void *priv;
+       
+
+       driver = intf->driver;
+       priv = intf->private_data;
+       
+       if (!driver)
+               return;
+
+       /* 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 function is part of a depth-first search down the device tree,
  * removing any instances of a device driver.
@@ -278,13 +369,7 @@
                struct usb_interface *interface = &dev->actconfig->interface[i];
                
                if (interface->driver == driver) {
-                       if (driver->owner)
-                               __MOD_INC_USE_COUNT(driver->owner);
-                       down(&driver->serialize);
-                       driver->disconnect(dev, interface->private_data);
-                       up(&driver->serialize);
-                       if (driver->owner)
-                               __MOD_DEC_USE_COUNT(driver->owner);
+                       usb_unbind_driver(dev, interface);
                        /* if driver->disconnect didn't release the interface */
                        if (interface->driver)
                                usb_driver_release_interface(driver, interface);
@@ -300,7 +385,7 @@
 /**
  *     usb_deregister - unregister a USB driver
  *     @driver: USB operations of the driver to unregister
- *     Context: !in_interrupt ()
+ *     Context: !in_interrupt (), must be called with BKL held
  *
  *     Unlinks the specified driver from the internal USB driver list.
  */
@@ -666,9 +751,7 @@
        struct list_head *tmp;
        struct usb_interface *interface;
        void *private;
-       const struct usb_device_id *id;
        struct usb_driver *driver;
-       int i;
        
        if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
                err("bad find_interface_driver params");
@@ -683,37 +766,12 @@
                goto out_err;
 
        private = NULL;
+       lock_kernel();
        for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {
                driver = list_entry(tmp, struct usb_driver, driver_list);
                tmp = tmp->next;
 
-               if (driver->owner)
-                       __MOD_INC_USE_COUNT(driver->owner);
-               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)
-                       __MOD_DEC_USE_COUNT(driver->owner);
+               private = usb_bind_driver(driver, dev, ifnum);
 
                /* probe() may have changed the config on us */
                interface = dev->actconfig->interface + ifnum;
@@ -721,9 +779,11 @@
                if (private) {
                        usb_driver_claim_interface(driver, interface, private);
                        up(&dev->serialize);
+                       unlock_kernel();
                        return 0;
                }
        }
+       unlock_kernel();
 
 out_err:
        up(&dev->serialize);
@@ -1135,27 +1195,22 @@
 
        info("USB disconnect on device %d", dev->devnum);
 
+       lock_kernel();
        if (dev->actconfig) {
                for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
                        struct usb_interface *interface = 
&dev->actconfig->interface[i];
                        struct usb_driver *driver = interface->driver;
                        if (driver) {
-                               if (driver->owner)
-                                       __MOD_INC_USE_COUNT(driver->owner);
-                               down(&driver->serialize);
-                               driver->disconnect(dev, interface->private_data);
-                               up(&driver->serialize);
+                               usb_unbind_driver(dev, interface);
                                /* if driver->disconnect didn't release the interface 
*/
                                if (interface->driver)
                                        usb_driver_release_interface(driver, 
interface);
-                               /* we don't need the driver any longer */
-                               if (driver->owner)
-                                       __MOD_DEC_USE_COUNT(driver->owner);
                        }
                        /* remove our device node for this interface */
                        put_device(&interface->dev);
                }
        }
+       unlock_kernel();
 
        /* Free up all the children.. */
        for (i = 0; i < USB_MAXCHILDREN; i++) {
@@ -1484,6 +1539,8 @@
 EXPORT_SYMBOL(usb_reset_device);
 EXPORT_SYMBOL(usb_connect);
 EXPORT_SYMBOL(usb_disconnect);
+EXPORT_SYMBOL(usb_bind_driver);
+EXPORT_SYMBOL(usb_unbind_driver);
 
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
 
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h       Tue Jul  2 23:15:46 2002
+++ b/include/linux/usb.h       Tue Jul  2 23:15:46 2002
@@ -251,7 +251,7 @@
        int act_altsetting;             /* active alternate setting */
        int num_altsetting;             /* number of alternate settings */
        int max_altsetting;             /* total memory allocated */
- 
+
        struct usb_driver *driver;      /* driver */
        struct device dev;              /* interface specific device info */
        void *private_data;
@@ -429,6 +429,10 @@
 
 /* for when layers above USB add new non-USB drivers */
 extern void usb_scan_devices(void);
+
+/* for probe/disconnect with correct module usage counting */
+void *usb_bind_driver(struct usb_driver *driver, struct usb_device *dev, unsigned int 
+ifnum);
+void usb_unbind_driver(struct usb_device *device, struct usb_interface *intf);
 
 /* mostly for devices emulating SCSI over USB */
 extern int usb_reset_device(struct usb_device *dev);

===================================================================


This BitKeeper patch contains the following changesets:
1.646
## Wrapped with gzip_uu ##


begin 664 bkpatch5604
M'XL(``(8(CT``[59>V_;.!+_V_H4[!;H)6D<DY0HV<XFUVL2W`:;-D73`E?<
M'@P]:%N(+/KT2)H[Y[O?#"G9\BNOS05-9(N<X;SG-^Q;\CV76;^EDOA&9M9;
M\IO*"_@J4Y7*@[&:R"1.RY\'*AO!XE>E8+&#KSN&HA-<MXM,RAP^)-R"/5_\
M(AP36,K[+79@S]\4=U/9;WT]^_OWB[]]M:RC(W(R]M.1O)(%.3JR@NL/42F3
M@^M,^6,\;C9?GG%*&6-<4%NX3,QXU[:=&7-I$,''B'N]8>#VK%$F1Q\,>:@F
MR^2<NMQECNUR,1-<V,(Z)>S`=5Q">8=Z'<H)M_O,Z5/O/>5]2HE1[\,F0Y#W
M@K2I]9'\>9E/K)"TR<??+X@_\N,T+\A$164B29DFRH^(2I,[<CN6F22IE)&,
MK-^)Z-D];GU9F,]J/_/'LJA/K>,-\D<9:IUWRCSHC,O@(%SHX=`><V<V<[@]
M"YGO#H5G.TX4".&)AZRUQ#-4F5PPYM2CG`-W3F>,VPY_5";X79<)*(4S"UTN
MI>ARYH6!;]-GRC1GW)2)]KH]]U&9(GD3JU6IO!GK.EX7@FW(Y-#F+."2!LQ^
MGE0-UDVY((Q[]I/D"F6^P5[<XVSF=\%8GA!=X=.@.^P]7[(Y\Z9LCDO%9IO%
M:9B4D>QHKMK@XZ9DP@&#NX[CS2+.[:@;"3%T(6/9@X)M8;HDD:#4U05GNQ:;
M*]"?L.9J-7K,@"[SJ&`V[<W`$EU/ER>(EJ7JQ/N</J4Z\=>M3L/XYTI5ROQ0
M0B$RKKXD[>Q6_X/"\N4!&[^@3)USAQ%FM1(57@^N99;*9&?WD'3VJF/()!Z-
M"Q+4DLF(['6`2E"DPG=-NNTQH)X:`4_.\R?Y7ZU[W_8P6-'[MGBA]QW29NXK
M^G_B7X-]\V"8PU])1C*561R2::8"4"/.0Y6F,BS(6"934/&!F,G);5R,2:S"
M(B$@2P1BC^;[S6N992HCF2S*+%WP0FI#/!W?Y7'H)Z1Q<MT[03PD_7<I\P)"
M8;$#@M74S*<$JWI1J)YZ7!#/.O=L1FRKM1*R\"(>DITX+8;MXRIVW[TCTQR^
MR9M=\E_8T`(I!D&<[email protected]?K5UG\3`#4[A&.'K(7[.:,\AW"+FIP6I4HSC
MG`S+-"QBE1+X?*-4I-2!MJ<J"X(LP!$D+G#5!X??048!&;R#=%K3Y13.\.#X
M4\8H)MIY]6RUJE-1D3)MJK*0?CC5'!CE%:6S31$&]8^MG8[)OQDK@:C`EPGB
M:.(N$;45ZA]T065\J`24S&95!+2/3?#AV]H9JP+!.XC*&XB\(](^^WQY]>,*
M7]X3F4!6:!KMXN&T]EG[6-U"KB!#%*@';FEMX7R/HG/;F(0;O1]F!VEN:\K&
M^5M8XVZA=U=A6.MA%#F_//EV<?+I='=-Q6_??FA?.96O]+,%88GYV=RSL;!J
MF/=X67T&S'RTJ#:0I>`]UN,]*F9,<-XS)=5[64FEI.V\9D%5-U)C_@@<>NMG
M40[UR>#?Q^J35O`EU8E184/\P=/#\K#181H#/^ZP9V#P1QW6@-TNM1D,9)0#
MA(3L-0@(//,BCV%Y:3OB%9WF1X@NZN:'_6@(8R^92*BA$=17:%JK'1&\J@>(
MQYRJC?`2=`00@5EO*PA,?C48.)],!U@%#L;'B(1<TJ-69V_/(GNMM;H,>BW$
MQ=)?O1YF:H+?-'1#R@]FH4].S89"(>A:T,)@JG=I@CXV@(IXV\XI\.D3_.L7
MDDP5%!5@._7S'*P,-!6U.18I3A3L^%GT=>(`U$`V^/XWA!&`+.I>D/LC24)5
M0I$"XV9P8G)G86_XP[I1<;2A-^5%5H:%7JA.W3//?=)8T@(.$8;L85_>M:#B
M-BF-7?;,$PJO/FP/%80O<'BK;CRDV=9A#;?,WU8&&41^X2.=+M=OS%ZLSP87
M'2(_[(,YR17T='C>2N`09M+/L7/+A3EJ8]RB,=54+X()+>S5@82PQ?V^7I^4
MT%-359`\D7*J6_^B8S:Z3ZLU&'RZ/!V<?SX9?+\Z&YQ<?O_\;67;X::>#KVH
MA35OYUV]&0!;["?Q?R0T=M0(S@-!S/[email protected]\5/P:U3'`_8Z5`"5&:LD
M`KNJH?Z&)Y)1B46UA@GSW6MP8>X5<,<\0'=JYZ,O=K6IR^E&B;>:9ZT)&WN=
MGCUHKWOK'@YKI.IRHL[!;IVDD"5UBOXE)_/XU,%.3+#OK4+*K1&[%.N---@'
M<^7Q*`7;8]^/AVDYT;&OORW%.<0M?`<Q(8K6F`UP5QP=+B7-<DZ9C]K@KQ]V
M6N#JL"/R#H1J'_MA`=(.XQ'`OWKQGUK#?QDI(G*T`(C1H/"#!%6$.$WE+>AX
ME]05ZJ_S;(DC(RLVA)T8&-!#$I-?%_YI'\,!`S\I<ED4`+%A^?U[0P-XO;$-
MQ&MLPQ*A\9R6"JTWP6M5L.N.`=8U(7R,#/)KBM/:GGAZM:[$"X5U-].\M4GV
M:Z[;LZ$ZLF;UYHA\_GYQL6OR+X#:=%T!4OP%^U8)7P4B%IX`2E6T3Q+I`T**
MY-`O07^(P%"W[,A,(\TSCAIG/&0ZBE%0(66<('Z!HF$<^$M]ON;]D)$>,I%)
MC'TCC`[";4:Z?_6J`;%MV@*99R&:]Y1W&0ZDO.N9<6*]\RT'#LYE-M4SB'DT
MN^Z;.#7IFI73@NSL[IMN`:T=9O$$7*.'\WEO/G7='DZ(KH?W-^=N5ZQ?X\!J
MCQ*.,S-SM8@+"Z_6K;I(+6RMI^!Z4EJ?'CWN;KP"@BG&]C;)`M.-#1,C3CF5
MO9YD,)@W<=X',M'=<J#3=0%QG_WCR^77;X.K'Y\^7E[LK.@'^];7EXZN;J\V
M7'=N!NPOO6Q=1>Q;[U<7<!VF*V$N+-WNR]"Z(&WVBE`]DF'B9SY>=QA@/D?K
M&Q"ZN1U>@>@;M'[)T,4%7FZ<F\<?UKEC,^+H'K]Q7C`Y5*'6#8"VNH_Y?W;V
@P]<%R8>+_Q`,QS*\SLO)48\%;K<K`NM_O$5**'L<````
`
end



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

Reply via email to