[PATCH] USB: fix usb reference count bug in cdc-acm driver
authorbrian@murphy.dk <brian@murphy.dk>
Wed, 29 Jun 2005 23:53:29 +0000 (16:53 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 12 Jul 2005 18:52:57 +0000 (11:52 -0700)
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>
drivers/usb/class/cdc-acm.c

index 69e859e0f51d42d479436516d675b5182da0e3a7..adff5a77e31f4f731c5f337e2f5bb391d7aea6f7 100644 (file)
@@ -422,6 +422,17 @@ bail_out:
        return -EIO;
 }
 
+static void acm_tty_unregister(struct acm *acm)
+{
+       tty_unregister_device(acm_tty_driver, acm->minor);
+       usb_put_intf(acm->control);
+       acm_table[acm->minor] = NULL;
+       usb_free_urb(acm->ctrlurb);
+       usb_free_urb(acm->readurb);
+       usb_free_urb(acm->writeurb);
+       kfree(acm);
+}
+
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
        struct acm *acm = tty->driver_data;
@@ -436,14 +447,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
                        usb_kill_urb(acm->ctrlurb);
                        usb_kill_urb(acm->writeurb);
                        usb_kill_urb(acm->readurb);
-               } else {
-                       tty_unregister_device(acm_tty_driver, acm->minor);
-                       acm_table[acm->minor] = NULL;
-                       usb_free_urb(acm->ctrlurb);
-                       usb_free_urb(acm->readurb);
-                       usb_free_urb(acm->writeurb);
-                       kfree(acm);
-               }
+               } else
+                       acm_tty_unregister(acm);
        }
        up(&open_sem);
 }
@@ -905,7 +910,8 @@ skip_normal_probe:
 
        usb_driver_claim_interface(&acm_driver, data_interface, acm);
 
-       tty_register_device(acm_tty_driver, minor, &intf->dev);
+       usb_get_intf(control_interface);
+       tty_register_device(acm_tty_driver, minor, &control_interface->dev);
 
        acm_table[minor] = acm;
        usb_set_intfdata (intf, acm);
@@ -954,12 +960,7 @@ static void acm_disconnect(struct usb_interface *intf)
        usb_driver_release_interface(&acm_driver, acm->data);
 
        if (!acm->used) {
-               tty_unregister_device(acm_tty_driver, acm->minor);
-               acm_table[acm->minor] = NULL;
-               usb_free_urb(acm->ctrlurb);
-               usb_free_urb(acm->readurb);
-               usb_free_urb(acm->writeurb);
-               kfree(acm);
+               acm_tty_unregister(acm);
                up(&open_sem);
                return;
        }