Commit bbc53b7d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

USB: fix bug where removing usb-serial modules or usb serial devices could oops

This fixes the issue where the Generic driver would bind to all usb-serial
devices, so the disconnect would not properly go to the real driver that
controlled the device.  This was very bad when unloading the module with
the device still connected.
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent e86c8cdf
......@@ -53,6 +53,32 @@ struct usb_serial_device_type usb_serial_generic_device = {
.num_ports = 1,
.shutdown = usb_serial_generic_shutdown,
};
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
static struct usb_device_id generic_serial_ids[] = {
{.driver_info = 42},
{}
};
static int generic_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
const struct usb_device_id *id_pattern;
id_pattern = usb_match_id(interface, generic_device_ids);
if (id_pattern != NULL)
return usb_serial_probe(interface, id);
return -ENODEV;
}
static struct usb_driver generic_driver = {
.owner = THIS_MODULE,
.name = "usbserial_generic",
.probe = generic_probe,
.disconnect = usb_serial_disconnect,
.id_table = generic_serial_ids,
};
#endif
int usb_serial_generic_register (int _debug)
......@@ -67,6 +93,12 @@ int usb_serial_generic_register (int _debug)
/* register our generic driver with ourselves */
retval = usb_serial_register (&usb_serial_generic_device);
if (retval)
goto exit;
retval = usb_register(&generic_driver);
if (retval)
usb_serial_deregister(&usb_serial_generic_device);
exit:
#endif
return retval;
}
......@@ -75,6 +107,7 @@ void usb_serial_generic_deregister (void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_deregister(&generic_driver);
usb_serial_deregister (&usb_serial_generic_device);
#endif
}
......
......@@ -355,25 +355,12 @@
#define DRIVER_DESC "USB Serial Driver core"
#ifdef CONFIG_USB_SERIAL_GENERIC
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
static struct usb_device_id generic_serial_ids[] = {
{.driver_info = 42},
{}
};
#endif /* CONFIG_USB_SERIAL_GENERIC */
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
.owner = THIS_MODULE,
.name = "usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
#ifdef CONFIG_USB_SERIAL_GENERIC
.id_table = generic_serial_ids,
#endif
};
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
......@@ -1383,22 +1370,9 @@ int usb_serial_register(struct usb_serial_device_type *new_device)
void usb_serial_deregister(struct usb_serial_device_type *device)
{
struct usb_serial *serial;
int i;
info("USB Serial deregistering driver %s", device->name);
/* clear out the serial_table if the device is attached to a port */
for(i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial = serial_table[i];
if ((serial != NULL) && (serial->type == device)) {
usb_driver_release_interface (&usb_serial_driver, serial->interface);
usb_serial_disconnect (serial->interface);
}
}
list_del(&device->driver_list);
usb_serial_bus_deregister (device);
usb_serial_bus_deregister(device);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment