USB-BKL: Remove BKL use for usb serial driver probing

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>
This commit is contained in:
Andi Kleen 2010-06-01 23:04:42 +02:00 committed by Greg Kroah-Hartman
parent c532b29a6f
commit 0daeed381c

View File

@ -653,6 +653,7 @@ exit:
return id; return id;
} }
/* Caller must hold table_lock */
static struct usb_serial_driver *search_serial_device( static struct usb_serial_driver *search_serial_device(
struct usb_interface *iface) struct usb_interface *iface)
{ {
@ -718,17 +719,23 @@ int usb_serial_probe(struct usb_interface *interface,
int num_ports = 0; int num_ports = 0;
int max_endpoints; int max_endpoints;
lock_kernel(); /* guard against unloading a serial driver module */ mutex_lock(&table_lock);
type = search_serial_device(interface); type = search_serial_device(interface);
if (!type) { if (!type) {
unlock_kernel(); mutex_unlock(&table_lock);
dbg("none matched"); dbg("none matched");
return -ENODEV; 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); serial = create_serial(dev, interface, type);
if (!serial) { if (!serial) {
unlock_kernel();
dev_err(&interface->dev, "%s - out of memory\n", __func__); dev_err(&interface->dev, "%s - out of memory\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
@ -737,20 +744,11 @@ int usb_serial_probe(struct usb_interface *interface,
if (type->probe) { if (type->probe) {
const struct usb_device_id *id; 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); id = get_iface_id(type, interface);
retval = type->probe(serial, id); retval = type->probe(serial, id);
module_put(type->driver.owner); module_put(type->driver.owner);
if (retval) { if (retval) {
unlock_kernel();
dbg("sub driver rejected device"); dbg("sub driver rejected device");
kfree(serial); kfree(serial);
return retval; return retval;
@ -822,7 +820,6 @@ int usb_serial_probe(struct usb_interface *interface,
* properly during a later invocation of usb_serial_probe * properly during a later invocation of usb_serial_probe
*/ */
if (num_bulk_in == 0 || num_bulk_out == 0) { 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"); dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
kfree(serial); kfree(serial);
return -ENODEV; return -ENODEV;
@ -835,7 +832,6 @@ int usb_serial_probe(struct usb_interface *interface,
if (type == &usb_serial_generic_device) { if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out; num_ports = num_bulk_out;
if (num_ports == 0) { if (num_ports == 0) {
unlock_kernel();
dev_err(&interface->dev, dev_err(&interface->dev,
"Generic device with no bulk out, not allowed.\n"); "Generic device with no bulk out, not allowed.\n");
kfree(serial); kfree(serial);
@ -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 this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) { if (type->calc_num_ports) {
if (!try_module_get(type->driver.owner)) { if (!try_module_get(type->driver.owner)) {
unlock_kernel();
dev_err(&interface->dev, dev_err(&interface->dev,
"module get failed, exiting\n"); "module get failed, exiting\n");
kfree(serial); kfree(serial);
@ -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, num_interrupt_out);
max_endpoints = max(max_endpoints, (int)serial->num_ports); max_endpoints = max(max_endpoints, (int)serial->num_ports);
serial->num_port_pointers = max_endpoints; serial->num_port_pointers = max_endpoints;
unlock_kernel();
dbg("%s - setting up %d port structures for this device", dbg("%s - setting up %d port structures for this device",
__func__, max_endpoints); __func__, max_endpoints);
@ -1349,6 +1343,7 @@ int usb_serial_register(struct usb_serial_driver *driver)
driver->description = driver->driver.name; driver->description = driver->driver.name;
/* Add this device to our list of devices */ /* Add this device to our list of devices */
mutex_lock(&table_lock);
list_add(&driver->driver_list, &usb_serial_driver_list); list_add(&driver->driver_list, &usb_serial_driver_list);
retval = usb_serial_bus_register(driver); retval = usb_serial_bus_register(driver);
@ -1360,6 +1355,7 @@ int usb_serial_register(struct usb_serial_driver *driver)
printk(KERN_INFO "USB Serial support registered for %s\n", printk(KERN_INFO "USB Serial support registered for %s\n",
driver->description); driver->description);
mutex_unlock(&table_lock);
return retval; return retval;
} }
EXPORT_SYMBOL_GPL(usb_serial_register); EXPORT_SYMBOL_GPL(usb_serial_register);
@ -1370,8 +1366,10 @@ void usb_serial_deregister(struct usb_serial_driver *device)
/* must be called with BKL held */ /* must be called with BKL held */
printk(KERN_INFO "USB Serial deregistering driver %s\n", printk(KERN_INFO "USB Serial deregistering driver %s\n",
device->description); device->description);
mutex_lock(&table_lock);
list_del(&device->driver_list); list_del(&device->driver_list);
usb_serial_bus_deregister(device); usb_serial_bus_deregister(device);
mutex_unlock(&table_lock);
} }
EXPORT_SYMBOL_GPL(usb_serial_deregister); EXPORT_SYMBOL_GPL(usb_serial_deregister);