aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrian@murphy.dk <brian@murphy.dk>2005-06-29 19:53:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-07-12 14:52:57 -0400
commit83ef344a7539aa55a787790bc036f0bf3466e191 (patch)
tree3a49e9eb5e690a3b0f6609ef0f24f403b3828a39
parenta3fdf4ebe016ba756de3ca29a2a6117e9acd721c (diff)
[PATCH] USB: fix usb reference count bug in cdc-acm driver
This increases the reference count on the usb cdc acm control interface which is referred to by the tty interface provided by the driver. This allows the deferred removal of the tty after the physical device is disconnected if the tty is held open at the time of disconnection. Signed-off-by: brian@murphy.dk Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/class/cdc-acm.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 69e859e0f51d..adff5a77e31f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -422,6 +422,17 @@ bail_out:
422 return -EIO; 422 return -EIO;
423} 423}
424 424
425static void acm_tty_unregister(struct acm *acm)
426{
427 tty_unregister_device(acm_tty_driver, acm->minor);
428 usb_put_intf(acm->control);
429 acm_table[acm->minor] = NULL;
430 usb_free_urb(acm->ctrlurb);
431 usb_free_urb(acm->readurb);
432 usb_free_urb(acm->writeurb);
433 kfree(acm);
434}
435
425static void acm_tty_close(struct tty_struct *tty, struct file *filp) 436static void acm_tty_close(struct tty_struct *tty, struct file *filp)
426{ 437{
427 struct acm *acm = tty->driver_data; 438 struct acm *acm = tty->driver_data;
@@ -436,14 +447,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
436 usb_kill_urb(acm->ctrlurb); 447 usb_kill_urb(acm->ctrlurb);
437 usb_kill_urb(acm->writeurb); 448 usb_kill_urb(acm->writeurb);
438 usb_kill_urb(acm->readurb); 449 usb_kill_urb(acm->readurb);
439 } else { 450 } else
440 tty_unregister_device(acm_tty_driver, acm->minor); 451 acm_tty_unregister(acm);
441 acm_table[acm->minor] = NULL;
442 usb_free_urb(acm->ctrlurb);
443 usb_free_urb(acm->readurb);
444 usb_free_urb(acm->writeurb);
445 kfree(acm);
446 }
447 } 452 }
448 up(&open_sem); 453 up(&open_sem);
449} 454}
@@ -905,7 +910,8 @@ skip_normal_probe:
905 910
906 usb_driver_claim_interface(&acm_driver, data_interface, acm); 911 usb_driver_claim_interface(&acm_driver, data_interface, acm);
907 912
908 tty_register_device(acm_tty_driver, minor, &intf->dev); 913 usb_get_intf(control_interface);
914 tty_register_device(acm_tty_driver, minor, &control_interface->dev);
909 915
910 acm_table[minor] = acm; 916 acm_table[minor] = acm;
911 usb_set_intfdata (intf, acm); 917 usb_set_intfdata (intf, acm);
@@ -954,12 +960,7 @@ static void acm_disconnect(struct usb_interface *intf)
954 usb_driver_release_interface(&acm_driver, acm->data); 960 usb_driver_release_interface(&acm_driver, acm->data);
955 961
956 if (!acm->used) { 962 if (!acm->used) {
957 tty_unregister_device(acm_tty_driver, acm->minor); 963 acm_tty_unregister(acm);
958 acm_table[acm->minor] = NULL;
959 usb_free_urb(acm->ctrlurb);
960 usb_free_urb(acm->readurb);
961 usb_free_urb(acm->writeurb);
962 kfree(acm);
963 up(&open_sem); 964 up(&open_sem);
964 return; 965 return;
965 } 966 }