summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-03-19 09:21:06 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-28 12:18:02 -0700
commit5557c6706441e7ad797b8b5c95579a9a1146502b (patch)
tree11bb8f3fc42039695d29dcd7177b78a906fb5342 /drivers
parent5a8d2f76c000f12e8985a64d0c8b45f0c746fc43 (diff)
USB: cdc-acm: fix device unregistration
commit cb25505fc604292c70fc02143fc102f54c8595f0 upstream. Unregister tty device in disconnect as is required by the USB stack. By deferring unregistration to when the last tty reference is dropped, the parent interface device can get unregistered before the child resulting in broken hotplug events being generated when the tty is finally closed: KERNEL[2290.798128] remove /devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:3.1 (usb) KERNEL[2290.804589] remove /devices/pci0000:00/0000:00:1d.7/usb2/2-1 (usb) KERNEL[2294.554799] remove /2-1:3.1/tty/ttyACM0 (tty) The driver must deal with tty callbacks after disconnect by checking the disconnected flag. Specifically, further opens must be prevented and this is already implemented. Acked-by: Oliver Neukum <oneukum@suse.de> Cc: Oliver Neukum <oneukum@suse.de> Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/class/cdc-acm.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 2d92cce260d7..35d2cf13efc3 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -600,7 +600,6 @@ static void acm_port_destruct(struct tty_port *port)
dev_dbg(&acm->control->dev, "%s\n", __func__);
- tty_unregister_device(acm_tty_driver, acm->minor);
acm_release_minor(acm);
usb_put_intf(acm->control);
kfree(acm->country_codes);
@@ -1418,6 +1417,8 @@ static void acm_disconnect(struct usb_interface *intf)
stop_data_traffic(acm);
+ tty_unregister_device(acm_tty_driver, acm->minor);
+
usb_free_urb(acm->ctrlurb);
for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb);