Alan Stern wrote:

On Sun, 13 Mar 2005, Brian Murphy wrote:



Hi,
This line in the acm_probe routine

tty_register_device(acm_tty_driver, minor, &intf->dev);

causes the path to the tty created for each acm to be linked to
the usb interface. As long as the device is closed when it is
disconnected this is no problem but if the tty is open then the
tty deregistering is deferred. When the terminal is closed
the interface parent to the tty no longer exists and the kernel
crashes in kobject_get_path.

The solution is to not link the two things together and replace
&intf->dev above with NULL, see the attached patch.

I believe that someone else had the same problem a few days
ago.



Would another possibility be to call usb_get_intf() before calling tty_register_device() and usb_put_intf() when the link is no longer needed? That way the interface parent to the tty would exist for as long as needed.


Alan Stern




This also works fine and allows me to clean up the tty_disconnect code so there is
only one copy. This patch is now dependant on my interface removal patch as there is
a slight overlap. See patch attached.


BTW The usb_get_intf and usb_put_intf functions needed to be exported before I
could use them here (included in patch).


/Brian
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.

This patch depends on cdc2.patch posted earlier to this list under the title
"cdc acm error removing interface(s)" as there is an overlap.

Signed-off-by: [EMAIL PROTECTED]

diff -r -u linux-2.6.11-bk7.clean/drivers/usb/class/cdc-acm.c 
linux-2.6.11-bk7/drivers/usb/class/cdc-acm.c
--- linux-2.6.11-bk7.clean/drivers/usb/class/cdc-acm.c  2005-03-13 
10:20:11.000000000 +0100
+++ linux-2.6.11-bk7/drivers/usb/class/cdc-acm.c        2005-03-13 
08:09:14.000000000 +0100
@@ -321,6 +321,17 @@
        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;
@@ -335,14 +346,8 @@
                        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);
 }
@@ -764,7 +769,8 @@
 
        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);
@@ -821,12 +827,7 @@
        usb_driver_release_interface(&acm_driver, other_interface);
 
        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;
        }
diff -r -u linux-2.6.11-bk7.clean/drivers/usb/core/usb.c 
linux-2.6.11-bk7/drivers/usb/core/usb.c
--- linux-2.6.11-bk7.clean/drivers/usb/core/usb.c       2005-03-12 
22:43:31.000000000 +0100
+++ linux-2.6.11-bk7/drivers/usb/core/usb.c     2005-03-13 08:10:35.000000000 
+0100
@@ -1499,6 +1499,9 @@
 EXPORT_SYMBOL(usb_deregister);
 EXPORT_SYMBOL(usb_disabled);
 
+EXPORT_SYMBOL(usb_get_intf);
+EXPORT_SYMBOL(usb_put_intf);
+
 EXPORT_SYMBOL(usb_alloc_dev);
 EXPORT_SYMBOL(usb_put_dev);
 EXPORT_SYMBOL(usb_get_dev);

Reply via email to