diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 941c2d409f85..443468e9d66e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -653,6 +653,7 @@ exit: | |||
653 | return id; | 653 | return id; |
654 | } | 654 | } |
655 | 655 | ||
656 | /* Caller must hold table_lock */ | ||
656 | static struct usb_serial_driver *search_serial_device( | 657 | static struct usb_serial_driver *search_serial_device( |
657 | struct usb_interface *iface) | 658 | struct usb_interface *iface) |
658 | { | 659 | { |
@@ -718,17 +719,23 @@ int usb_serial_probe(struct usb_interface *interface, | |||
718 | int num_ports = 0; | 719 | int num_ports = 0; |
719 | int max_endpoints; | 720 | int max_endpoints; |
720 | 721 | ||
721 | lock_kernel(); /* guard against unloading a serial driver module */ | 722 | mutex_lock(&table_lock); |
722 | type = search_serial_device(interface); | 723 | type = search_serial_device(interface); |
723 | if (!type) { | 724 | if (!type) { |
724 | unlock_kernel(); | 725 | mutex_unlock(&table_lock); |
725 | dbg("none matched"); | 726 | dbg("none matched"); |
726 | return -ENODEV; | 727 | return -ENODEV; |
727 | } | 728 | } |
728 | 729 | ||
730 | if (!try_module_get(type->driver.owner)) { | ||
731 | mutex_unlock(&table_lock); | ||
732 | dev_err(&interface->dev, "module get failed, exiting\n"); | ||
733 | return -EIO; | ||
734 | } | ||
735 | mutex_unlock(&table_lock); | ||
736 | |||
729 | serial = create_serial(dev, interface, type); | 737 | serial = create_serial(dev, interface, type); |
730 | if (!serial) { | 738 | if (!serial) { |
731 | unlock_kernel(); | ||
732 | dev_err(&interface->dev, "%s - out of memory\n", __func__); | 739 | dev_err(&interface->dev, "%s - out of memory\n", __func__); |
733 | return -ENOMEM; | 740 | return -ENOMEM; |
734 | } | 741 | } |
@@ -737,20 +744,11 @@ int usb_serial_probe(struct usb_interface *interface, | |||
737 | if (type->probe) { | 744 | if (type->probe) { |
738 | const struct usb_device_id *id; | 745 | const struct usb_device_id *id; |
739 | 746 | ||
740 | if (!try_module_get(type->driver.owner)) { | ||
741 | unlock_kernel(); | ||
742 | dev_err(&interface->dev, | ||
743 | "module get failed, exiting\n"); | ||
744 | kfree(serial); | ||
745 | return -EIO; | ||
746 | } | ||
747 | |||
748 | id = get_iface_id(type, interface); | 747 | id = get_iface_id(type, interface); |
749 | retval = type->probe(serial, id); | 748 | retval = type->probe(serial, id); |
750 | module_put(type->driver.owner); | 749 | module_put(type->driver.owner); |
751 | 750 | ||
752 | if (retval) { | 751 | if (retval) { |
753 | unlock_kernel(); | ||
754 | dbg("sub driver rejected device"); | 752 | dbg("sub driver rejected device"); |
755 | kfree(serial); | 753 | kfree(serial); |
756 | return retval; | 754 | return retval; |
@@ -822,7 +820,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
822 | * properly during a later invocation of usb_serial_probe | 820 | * properly during a later invocation of usb_serial_probe |
823 | */ | 821 | */ |
824 | if (num_bulk_in == 0 || num_bulk_out == 0) { | 822 | if (num_bulk_in == 0 || num_bulk_out == 0) { |
825 | unlock_kernel(); | ||
826 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); | 823 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); |
827 | kfree(serial); | 824 | kfree(serial); |
828 | return -ENODEV; | 825 | return -ENODEV; |
@@ -835,7 +832,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
835 | if (type == &usb_serial_generic_device) { | 832 | if (type == &usb_serial_generic_device) { |
836 | num_ports = num_bulk_out; | 833 | num_ports = num_bulk_out; |
837 | if (num_ports == 0) { | 834 | if (num_ports == 0) { |
838 | unlock_kernel(); | ||
839 | dev_err(&interface->dev, | 835 | dev_err(&interface->dev, |
840 | "Generic device with no bulk out, not allowed.\n"); | 836 | "Generic device with no bulk out, not allowed.\n"); |
841 | kfree(serial); | 837 | kfree(serial); |
@@ -847,7 +843,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
847 | /* if this device type has a calc_num_ports function, call it */ | 843 | /* if this device type has a calc_num_ports function, call it */ |
848 | if (type->calc_num_ports) { | 844 | if (type->calc_num_ports) { |
849 | if (!try_module_get(type->driver.owner)) { | 845 | if (!try_module_get(type->driver.owner)) { |
850 | unlock_kernel(); | ||
851 | dev_err(&interface->dev, | 846 | dev_err(&interface->dev, |
852 | "module get failed, exiting\n"); | 847 | "module get failed, exiting\n"); |
853 | kfree(serial); | 848 | kfree(serial); |
@@ -878,7 +873,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
878 | max_endpoints = max(max_endpoints, num_interrupt_out); | 873 | max_endpoints = max(max_endpoints, num_interrupt_out); |
879 | max_endpoints = max(max_endpoints, (int)serial->num_ports); | 874 | max_endpoints = max(max_endpoints, (int)serial->num_ports); |
880 | serial->num_port_pointers = max_endpoints; | 875 | serial->num_port_pointers = max_endpoints; |
881 | unlock_kernel(); | ||
882 | 876 | ||
883 | dbg("%s - setting up %d port structures for this device", | 877 | dbg("%s - setting up %d port structures for this device", |
884 | __func__, max_endpoints); | 878 | __func__, max_endpoints); |
@@ -1349,6 +1343,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1349 | driver->description = driver->driver.name; | 1343 | driver->description = driver->driver.name; |
1350 | 1344 | ||
1351 | /* Add this device to our list of devices */ | 1345 | /* Add this device to our list of devices */ |
1346 | mutex_lock(&table_lock); | ||
1352 | list_add(&driver->driver_list, &usb_serial_driver_list); | 1347 | list_add(&driver->driver_list, &usb_serial_driver_list); |
1353 | 1348 | ||
1354 | retval = usb_serial_bus_register(driver); | 1349 | retval = usb_serial_bus_register(driver); |
@@ -1360,6 +1355,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1360 | printk(KERN_INFO "USB Serial support registered for %s\n", | 1355 | printk(KERN_INFO "USB Serial support registered for %s\n", |
1361 | driver->description); | 1356 | driver->description); |
1362 | 1357 | ||
1358 | mutex_unlock(&table_lock); | ||
1363 | return retval; | 1359 | return retval; |
1364 | } | 1360 | } |
1365 | EXPORT_SYMBOL_GPL(usb_serial_register); | 1361 | EXPORT_SYMBOL_GPL(usb_serial_register); |
@@ -1370,8 +1366,10 @@ void usb_serial_deregister(struct usb_serial_driver *device) | |||
1370 | /* must be called with BKL held */ | 1366 | /* must be called with BKL held */ |
1371 | printk(KERN_INFO "USB Serial deregistering driver %s\n", | 1367 | printk(KERN_INFO "USB Serial deregistering driver %s\n", |
1372 | device->description); | 1368 | device->description); |
1369 | mutex_lock(&table_lock); | ||
1373 | list_del(&device->driver_list); | 1370 | list_del(&device->driver_list); |
1374 | usb_serial_bus_deregister(device); | 1371 | usb_serial_bus_deregister(device); |
1372 | mutex_unlock(&table_lock); | ||
1375 | } | 1373 | } |
1376 | EXPORT_SYMBOL_GPL(usb_serial_deregister); | 1374 | EXPORT_SYMBOL_GPL(usb_serial_deregister); |
1377 | 1375 | ||