diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 3780362eb9f0..685fb69bcc32 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -685,14 +685,17 @@ int usb_serial_probe(struct usb_interface *interface, | |||
685 | int num_ports = 0; | 685 | int num_ports = 0; |
686 | int max_endpoints; | 686 | int max_endpoints; |
687 | 687 | ||
688 | lock_kernel(); /* guard against unloading a serial driver module */ | ||
688 | type = search_serial_device(interface); | 689 | type = search_serial_device(interface); |
689 | if (!type) { | 690 | if (!type) { |
691 | unlock_kernel(); | ||
690 | dbg("none matched"); | 692 | dbg("none matched"); |
691 | return -ENODEV; | 693 | return -ENODEV; |
692 | } | 694 | } |
693 | 695 | ||
694 | serial = create_serial (dev, interface, type); | 696 | serial = create_serial (dev, interface, type); |
695 | if (!serial) { | 697 | if (!serial) { |
698 | unlock_kernel(); | ||
696 | dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); | 699 | dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); |
697 | return -ENOMEM; | 700 | return -ENOMEM; |
698 | } | 701 | } |
@@ -702,6 +705,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
702 | const struct usb_device_id *id; | 705 | const struct usb_device_id *id; |
703 | 706 | ||
704 | if (!try_module_get(type->driver.owner)) { | 707 | if (!try_module_get(type->driver.owner)) { |
708 | unlock_kernel(); | ||
705 | dev_err(&interface->dev, "module get failed, exiting\n"); | 709 | dev_err(&interface->dev, "module get failed, exiting\n"); |
706 | kfree (serial); | 710 | kfree (serial); |
707 | return -EIO; | 711 | return -EIO; |
@@ -712,6 +716,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
712 | module_put(type->driver.owner); | 716 | module_put(type->driver.owner); |
713 | 717 | ||
714 | if (retval) { | 718 | if (retval) { |
719 | unlock_kernel(); | ||
715 | dbg ("sub driver rejected device"); | 720 | dbg ("sub driver rejected device"); |
716 | kfree (serial); | 721 | kfree (serial); |
717 | return retval; | 722 | return retval; |
@@ -781,6 +786,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
781 | * properly during a later invocation of usb_serial_probe | 786 | * properly during a later invocation of usb_serial_probe |
782 | */ | 787 | */ |
783 | if (num_bulk_in == 0 || num_bulk_out == 0) { | 788 | if (num_bulk_in == 0 || num_bulk_out == 0) { |
789 | unlock_kernel(); | ||
784 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); | 790 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); |
785 | kfree (serial); | 791 | kfree (serial); |
786 | return -ENODEV; | 792 | return -ENODEV; |
@@ -796,6 +802,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
796 | if (type == &usb_serial_generic_device) { | 802 | if (type == &usb_serial_generic_device) { |
797 | num_ports = num_bulk_out; | 803 | num_ports = num_bulk_out; |
798 | if (num_ports == 0) { | 804 | if (num_ports == 0) { |
805 | unlock_kernel(); | ||
799 | dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); | 806 | dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); |
800 | kfree (serial); | 807 | kfree (serial); |
801 | return -EIO; | 808 | return -EIO; |
@@ -806,6 +813,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
806 | /* if this device type has a calc_num_ports function, call it */ | 813 | /* if this device type has a calc_num_ports function, call it */ |
807 | if (type->calc_num_ports) { | 814 | if (type->calc_num_ports) { |
808 | if (!try_module_get(type->driver.owner)) { | 815 | if (!try_module_get(type->driver.owner)) { |
816 | unlock_kernel(); | ||
809 | dev_err(&interface->dev, "module get failed, exiting\n"); | 817 | dev_err(&interface->dev, "module get failed, exiting\n"); |
810 | kfree (serial); | 818 | kfree (serial); |
811 | return -EIO; | 819 | return -EIO; |
@@ -831,6 +839,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
831 | max_endpoints = max(max_endpoints, num_interrupt_out); | 839 | max_endpoints = max(max_endpoints, num_interrupt_out); |
832 | max_endpoints = max(max_endpoints, (int)serial->num_ports); | 840 | max_endpoints = max(max_endpoints, (int)serial->num_ports); |
833 | serial->num_port_pointers = max_endpoints; | 841 | serial->num_port_pointers = max_endpoints; |
842 | unlock_kernel(); | ||
843 | |||
834 | dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); | 844 | dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); |
835 | for (i = 0; i < max_endpoints; ++i) { | 845 | for (i = 0; i < max_endpoints; ++i) { |
836 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); | 846 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); |
@@ -1187,7 +1197,7 @@ static void fixup_generic(struct usb_serial_driver *device) | |||
1187 | set_to_generic_if_null(device, shutdown); | 1197 | set_to_generic_if_null(device, shutdown); |
1188 | } | 1198 | } |
1189 | 1199 | ||
1190 | int usb_serial_register(struct usb_serial_driver *driver) | 1200 | int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ |
1191 | { | 1201 | { |
1192 | int retval; | 1202 | int retval; |
1193 | 1203 | ||
@@ -1211,7 +1221,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1211 | } | 1221 | } |
1212 | 1222 | ||
1213 | 1223 | ||
1214 | void usb_serial_deregister(struct usb_serial_driver *device) | 1224 | void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */ |
1215 | { | 1225 | { |
1216 | info("USB Serial deregistering driver %s", device->description); | 1226 | info("USB Serial deregistering driver %s", device->description); |
1217 | list_del(&device->driver_list); | 1227 | list_del(&device->driver_list); |