USB: Push BKL on open down into the drivers

Straightforward push into the drivers to allow
auditing individual drivers separately

Signed-off-by: Oliver Neukum <oliver@neukum.org>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 18aafcb..b75a3d8 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -19,6 +19,7 @@
 #include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/usb/cdc.h>
 #include <asm/byteorder.h>
@@ -516,6 +517,7 @@
 	struct usb_interface *intf;
 	struct wdm_device *desc;
 
+	lock_kernel();
 	mutex_lock(&wdm_mutex);
 	intf = usb_find_interface(&wdm_driver, minor);
 	if (!intf)
@@ -548,6 +550,7 @@
 	usb_autopm_put_interface(desc->intf);
 out:
 	mutex_unlock(&wdm_mutex);
+	unlock_kernel();
 	return rv;
 }
 
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 93b5f85..d53f949 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -56,6 +56,7 @@
 #include <linux/slab.h>
 #include <linux/lp.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #undef DEBUG
 #include <linux/usb.h>
 
@@ -395,6 +396,7 @@
 	if (minor < 0)
 		return -ENODEV;
 
+	lock_kernel();
 	mutex_lock (&usblp_mutex);
 
 	retval = -ENODEV;
@@ -434,6 +436,7 @@
 	}
 out:
 	mutex_unlock (&usblp_mutex);
+	unlock_kernel();
 	return retval;
 }
 
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 8588c09..426bfc7 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -26,6 +26,7 @@
 #include <linux/uaccess.h>
 #include <linux/kref.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/usb/tmc.h>
 
@@ -113,6 +114,7 @@
 	struct usbtmc_device_data *data;
 	int retval = 0;
 
+	lock_kernel();
 	intf = usb_find_interface(&usbtmc_driver, iminor(inode));
 	if (!intf) {
 		printk(KERN_ERR KBUILD_MODNAME
@@ -128,6 +130,7 @@
 	filp->private_data = data;
 
 exit:
+	unlock_kernel();
 	return retval;
 }
 
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index bfc6c2e..c3536f1 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -34,7 +34,6 @@
 	int err = -ENODEV;
 	const struct file_operations *old_fops, *new_fops = NULL;
 
-	lock_kernel();
 	down_read(&minor_rwsem);
 	c = usb_minors[minor];
 
@@ -53,7 +52,6 @@
 	fops_put(old_fops);
  done:
 	up_read(&minor_rwsem);
-	unlock_kernel();
 	return err;
 }
 
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index e192e8f..dce4f7b 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -96,6 +96,7 @@
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 
 #include <linux/usb.h>
 #include <linux/fs.h>
@@ -622,6 +623,7 @@
 	int retval=0;
 	int errn=0;
 
+	lock_kernel();
 	mutex_lock(&mdc800->io_lock);
 	
 	if (mdc800->state == NOT_CONNECTED)
@@ -660,6 +662,7 @@
 
 error_out:
 	mutex_unlock(&mdc800->io_lock);
+	unlock_kernel();
 	return errn;
 }
 
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 306e978..ac8ad91 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_USB_DEBUG
@@ -274,6 +275,7 @@
 
 	dbg(2,"%s : enter", __func__);
 
+	lock_kernel();
 	subminor = iminor(inode);
 
 	if ((retval = mutex_lock_interruptible(&adutux_mutex))) {
@@ -332,6 +334,7 @@
 exit_no_device:
 	mutex_unlock(&adutux_mutex);
 exit_no_lock:
+	unlock_kernel();
 	dbg(2,"%s : leave, return value %d ", __func__, retval);
 	return retval;
 }
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index f21bf51..32c47fb 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -45,6 +45,7 @@
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/workqueue.h>
@@ -623,22 +624,30 @@
 */
 static int ftdi_elan_open(struct inode *inode, struct file *file)
 {
-        int subminor = iminor(inode);
-        struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver,
-                subminor);
+	int subminor;
+	struct usb_interface *interface;
+
+	lock_kernel();
+        subminor = iminor(inode);
+        interface = usb_find_interface(&ftdi_elan_driver, subminor);
+
         if (!interface) {
+		unlock_kernel();
                 printk(KERN_ERR "can't find device for minor %d\n", subminor);
                 return -ENODEV;
         } else {
                 struct usb_ftdi *ftdi = usb_get_intfdata(interface);
                 if (!ftdi) {
+			unlock_kernel();
                         return -ENODEV;
                 } else {
                         if (down_interruptible(&ftdi->sw_lock)) {
+				unlock_kernel();
                                 return -EINTR;
                         } else {
                                 ftdi_elan_get_kref(ftdi);
                                 file->private_data = ftdi;
+				unlock_kernel();
                                 return 0;
                         }
                 }
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index a54c3cb..68df9ac 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
@@ -226,16 +227,20 @@
 	struct usb_interface *interface;
 	int result;
 
+	lock_kernel();
 	/* get the interface from minor number and driver information */
 	interface = usb_find_interface (&idmouse_driver, iminor (inode));
-	if (!interface)
+	if (!interface) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
 	mutex_lock(&open_disc_mutex);
 	/* get the device information block from the interface */
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&open_disc_mutex);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
@@ -272,6 +277,7 @@
 
 	/* unlock this device */
 	mutex_unlock(&dev->lock);
+	unlock_kernel();
 	return result;
 }
 
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 5206423..d3c8523 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -602,10 +602,12 @@
 
 	dbg("%s", __func__);
 
+	lock_kernel();
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&iowarrior_driver, subminor);
 	if (!interface) {
+		unlock_kernel();
 		err("%s - error, can't find device for minor %d", __func__,
 		    subminor);
 		return -ENODEV;
@@ -615,6 +617,7 @@
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&iowarrior_open_disc_lock);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
@@ -641,6 +644,7 @@
 
 out:
 	mutex_unlock(&dev->mutex);
+	unlock_kernel();
 	return retval;
 }
 
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7c0bd13..8de32df 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <linux/input.h>
@@ -296,12 +297,14 @@
 	int retval;
 	struct usb_interface *interface;
 
+	lock_kernel();
 	nonseekable_open(inode, file);
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&ld_usb_driver, subminor);
 
 	if (!interface) {
+		unlock_kernel();
 		err("%s - error, can't find device for minor %d\n",
 		     __func__, subminor);
 		return -ENODEV;
@@ -309,12 +312,16 @@
 
 	dev = usb_get_intfdata(interface);
 
-	if (!dev)
+	if (!dev) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
 	/* lock this device */
-	if (mutex_lock_interruptible(&dev->mutex))
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		unlock_kernel();
 		return -ERESTARTSYS;
+	}
 
 	/* allow opening only once */
 	if (dev->open_count) {
@@ -353,6 +360,7 @@
 
 unlock_exit:
 	mutex_unlock(&dev->mutex);
+	unlock_kernel();
 
 	return retval;
 }
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 3d4378f..94e1b84 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -82,6 +82,7 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/poll.h>
@@ -345,6 +346,7 @@
 
 	dbg(2, "%s: enter", __func__);
 
+	lock_kernel();
 	nonseekable_open(inode, file);
 	subminor = iminor(inode);
 
@@ -430,6 +432,7 @@
 	mutex_unlock(&dev->lock);
 
 exit:
+	unlock_kernel();
 	dbg(2, "%s: leave, return value %d ", __func__, retval);
 
 	return retval;
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 17e4eec..47ce46bb 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -77,7 +77,7 @@
 static int open_rio(struct inode *inode, struct file *file)
 {
 	struct rio_usb_data *rio = &rio_instance;
-
+	lock_kernel();
 	mutex_lock(&(rio->lock));
 
 	if (rio->isopen || !rio->present) {
@@ -91,6 +91,7 @@
 	mutex_unlock(&(rio->lock));
 
 	dev_info(&rio->rio_dev->dev, "Rio opened.\n");
+	unlock_kernel();
 
 	return 0;
 }
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index bb0b315..3991655 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2416,21 +2416,28 @@
 	struct usb_interface *interface;
 	int subminor = iminor(inode);
 
-	if (!(interface = usb_find_interface(&sisusb_driver, subminor)))
+	lock_kernel();
+	if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
-	if (!(sisusb = usb_get_intfdata(interface)))
+	if (!(sisusb = usb_get_intfdata(interface))) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
 	mutex_lock(&sisusb->lock);
 
 	if (!sisusb->present || !sisusb->ready) {
 		mutex_unlock(&sisusb->lock);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
 	if (sisusb->isopen) {
 		mutex_unlock(&sisusb->lock);
+		unlock_kernel();
 		return -EBUSY;
 	}
 
@@ -2439,11 +2446,13 @@
 			if (sisusb_init_gfxdevice(sisusb, 0)) {
 				mutex_unlock(&sisusb->lock);
 				dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
+				unlock_kernel();
 				return -EIO;
 			}
 		} else {
 			mutex_unlock(&sisusb->lock);
 			dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
+			unlock_kernel();
 			return -EIO;
 		}
 	}
@@ -2456,6 +2465,7 @@
 	file->private_data = sisusb;
 
 	mutex_unlock(&sisusb->lock);
+	unlock_kernel();
 
 	return 0;
 }
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 499d750..90aede9 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -74,10 +74,12 @@
 	struct usb_interface *interface;
 	int subminor, r;
 
+	lock_kernel();
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&lcd_driver, subminor);
 	if (!interface) {
+		unlock_kernel();
 		err ("USBLCD: %s - error, can't find device for minor %d",
 		     __func__, subminor);
 		return -ENODEV;
@@ -87,6 +89,7 @@
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&open_disc_mutex);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
@@ -98,11 +101,13 @@
 	r = usb_autopm_get_interface(interface);
 	if (r < 0) {
 		kref_put(&dev->kref, lcd_delete);
+		unlock_kernel();
 		return r;
 	}
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
+	unlock_kernel();
 
 	return 0;
 }
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
index 874c81b..b787b25 100644
--- a/drivers/usb/misc/vstusb.c
+++ b/drivers/usb/misc/vstusb.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 
@@ -103,19 +104,23 @@
 	struct vstusb_device *vstdev;
 	struct usb_interface *interface;
 
+	lock_kernel();
 	interface = usb_find_interface(&vstusb_driver, iminor(inode));
 
 	if (!interface) {
 		printk(KERN_ERR KBUILD_MODNAME
 		       ": %s - error, can't find device for minor %d\n",
 		       __func__, iminor(inode));
+		unlock_kernel();
 		return -ENODEV;
 	}
 
 	vstdev = usb_get_intfdata(interface);
 
-	if (!vstdev)
+	if (!vstdev) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
 	/* lock this device */
 	mutex_lock(&vstdev->lock);
@@ -123,6 +128,7 @@
 	/* can only open one time */
 	if ((!vstdev->present) || (vstdev->isopen)) {
 		mutex_unlock(&vstdev->lock);
+		unlock_kernel();
 		return -EBUSY;
 	}
 
@@ -137,6 +143,7 @@
 	dev_dbg(&vstdev->usb_dev->dev, "%s: opened\n", __func__);
 
 	mutex_unlock(&vstdev->lock);
+	unlock_kernel();
 
 	return 0;
 }
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 6152278..e94176b 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kref.h>
+#include <linux/smp_lock.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
@@ -90,6 +91,7 @@
 	int subminor;
 	int retval = 0;
 
+	lock_kernel();
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&skel_driver, subminor);
@@ -135,6 +137,7 @@
 	mutex_unlock(&dev->io_mutex);
 
 exit:
+	unlock_kernel();
 	return retval;
 }