Skip to content

Commit

Permalink
USB-BKL: Remove BKL use for usb serial driver probing
Browse files Browse the repository at this point in the history
The usb serial driver initialization tried to use the BKL to stop
driver modules from unloading, but that didn't work anyways.

There was already some code to do proper try_module_get,
but it was conditional on having a new probe interface.
I checked all the low level drivers and they all have proper
.owner = THIS_MODULE, so it's ok to always use.

The other problem was the usb_serial_driver_list needing
protection by a lock. This was broken anyways because unregister
did not necessarily have the BKL.

I extended the extending table_lock mutex to protect this case too.

With these changes the BKL can be removed here.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Andi Kleen authored and Greg Kroah-Hartman committed Aug 10, 2010
1 parent c532b29 commit 0daeed3
Showing 1 changed file with 14 additions and 16 deletions.
30 changes: 14 additions & 16 deletions drivers/usb/serial/usb-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
return id;
}

/* Caller must hold table_lock */
static struct usb_serial_driver *search_serial_device(
struct usb_interface *iface)
{
Expand Down Expand Up @@ -718,17 +719,23 @@ int usb_serial_probe(struct usb_interface *interface,
int num_ports = 0;
int max_endpoints;

lock_kernel(); /* guard against unloading a serial driver module */
mutex_lock(&table_lock);
type = search_serial_device(interface);
if (!type) {
unlock_kernel();
mutex_unlock(&table_lock);
dbg("none matched");
return -ENODEV;
}

if (!try_module_get(type->driver.owner)) {
mutex_unlock(&table_lock);
dev_err(&interface->dev, "module get failed, exiting\n");
return -EIO;
}
mutex_unlock(&table_lock);

serial = create_serial(dev, interface, type);
if (!serial) {
unlock_kernel();
dev_err(&interface->dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
Expand All @@ -737,20 +744,11 @@ int usb_serial_probe(struct usb_interface *interface,
if (type->probe) {
const struct usb_device_id *id;

if (!try_module_get(type->driver.owner)) {
unlock_kernel();
dev_err(&interface->dev,
"module get failed, exiting\n");
kfree(serial);
return -EIO;
}

id = get_iface_id(type, interface);
retval = type->probe(serial, id);
module_put(type->driver.owner);

if (retval) {
unlock_kernel();
dbg("sub driver rejected device");
kfree(serial);
return retval;
Expand Down Expand Up @@ -822,7 +820,6 @@ int usb_serial_probe(struct usb_interface *interface,
* properly during a later invocation of usb_serial_probe
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
unlock_kernel();
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
kfree(serial);
return -ENODEV;
Expand All @@ -835,7 +832,6 @@ int usb_serial_probe(struct usb_interface *interface,
if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out;
if (num_ports == 0) {
unlock_kernel();
dev_err(&interface->dev,
"Generic device with no bulk out, not allowed.\n");
kfree(serial);
Expand All @@ -847,7 +843,6 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) {
if (!try_module_get(type->driver.owner)) {
unlock_kernel();
dev_err(&interface->dev,
"module get failed, exiting\n");
kfree(serial);
Expand Down Expand Up @@ -878,7 +873,6 @@ int usb_serial_probe(struct usb_interface *interface,
max_endpoints = max(max_endpoints, num_interrupt_out);
max_endpoints = max(max_endpoints, (int)serial->num_ports);
serial->num_port_pointers = max_endpoints;
unlock_kernel();

dbg("%s - setting up %d port structures for this device",
__func__, max_endpoints);
Expand Down Expand Up @@ -1349,6 +1343,7 @@ int usb_serial_register(struct usb_serial_driver *driver)
driver->description = driver->driver.name;

/* Add this device to our list of devices */
mutex_lock(&table_lock);
list_add(&driver->driver_list, &usb_serial_driver_list);

retval = usb_serial_bus_register(driver);
Expand All @@ -1360,6 +1355,7 @@ int usb_serial_register(struct usb_serial_driver *driver)
printk(KERN_INFO "USB Serial support registered for %s\n",
driver->description);

mutex_unlock(&table_lock);
return retval;
}
EXPORT_SYMBOL_GPL(usb_serial_register);
Expand All @@ -1370,8 +1366,10 @@ void usb_serial_deregister(struct usb_serial_driver *device)
/* must be called with BKL held */
printk(KERN_INFO "USB Serial deregistering driver %s\n",
device->description);
mutex_lock(&table_lock);
list_del(&device->driver_list);
usb_serial_bus_deregister(device);
mutex_unlock(&table_lock);
}
EXPORT_SYMBOL_GPL(usb_serial_deregister);

Expand Down

0 comments on commit 0daeed3

Please sign in to comment.