Most recent kernel where this bug did not occur: still seen Distribution: KUbuntu 2.6.20.15 and Freescale BSP 2.6.19.2 Hardware Environment: Dell Optiplex x86 and Freescale ARM Development Board Software Environment: Vmware running Kubuntu on Windows XP and Embedded ARM development board Problem Description: If you have a program that opens a port using usb-serial and the USB device is disconnected there is no uevent indicating the ACTION "remove" for the tty device (e.g ttyUSB0). Once the port is closed the uevent is triggered and notifies the system the device has disconnected. When using the port there is no way to get notified that the device has disconnected. If no ports are open the uevent is sent without problems. I admit this could be a design decision but it seems like a limitation. I've seen the same problem in the cdc-acm driver. I've debugged the problem and found a potential solution. When the serial->kref is initialized it starts as one. When the port is opened it obviously gets incremented. The problem is that on the serial_disconnect there should be a kref_put for each port that calls tty_hangup. Also the port->tty->driver_data MUST be reset to NULL otherwise when the program closes its open port it will crash the driver. The proposed change is as follows: if (serial) { for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port && port->tty) { tty_hangup(port->tty); + /* prevents a close from an open device crashing the driver */ + port->tty->driver_data = NULL; + + /* we are also done with the reference used by tty */ + usb_serial_put(serial); } } /* let the last holder of this object * cause it to be cleaned up */ usb_serial_put(serial); } Steps to reproduce: 1. Connect usb-serial device 2. Open the port (e.g. ttyUSB0) using some program (e.g. minicom) 3. Disconnect the usb-serial device 4. problem occurs here, no uevent for the remove of ttyUSB0. /dev/ttyUSB0 is still around. 5. Can now kill/terminate the program that had the port open and the uevent will be sent out.
I don't think the patch is needed to keep the code from oopsing, right? It still works fine to keep a port open and yank out the device. I ran udevmonitor and if I hold the port open with 'cat', yank out the device, the hangup happens and notifies cat, cat lets the port go, and then the uevent remove event happens. So I don't see a bug here, what am I missing? Can you try the 2.6.22 kernel or newer?
Reply-To: akpm@linux-foundation.org On Thu, 20 Sep 2007 14:05:59 -0700 (PDT) bugme-daemon@bugzilla.kernel.org wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=9046 > > Summary: USB Serial not sending uevent on device disconnect if > port open > Product: Drivers > Version: 2.5 > KernelVersion: 2.6.20.15 and 2.6.19.2 > Platform: All > OS/Version: Linux > Tree: Mainline > Status: NEW > Severity: normal > Priority: P1 > Component: USB > AssignedTo: greg@kroah.com > ReportedBy: tsmoore@wideopenwest.com > > > Most recent kernel where this bug did not occur: still seen > Distribution: KUbuntu 2.6.20.15 and Freescale BSP 2.6.19.2 > Hardware Environment: Dell Optiplex x86 and Freescale ARM Development Board > Software Environment: Vmware running Kubuntu on Windows XP and Embedded ARM > development board > Problem Description: > If you have a program that opens a port using usb-serial and the USB device > is > disconnected there is no uevent indicating the ACTION "remove" for the tty > device (e.g ttyUSB0). Once the port is closed the uevent is triggered and > notifies the system the device has disconnected. When using the port there > is > no way to get notified that the device has disconnected. If no ports are > open > the uevent is sent without problems. I admit this could be a design decision > but it seems like a limitation. I've seen the same problem in the cdc-acm > driver. > > I've debugged the problem and found a potential solution. When the > serial->kref is initialized it starts as one. When the port is opened it > obviously gets incremented. The problem is that on the serial_disconnect > there > should be a kref_put for each port that calls tty_hangup. Also the > port->tty->driver_data MUST be reset to NULL otherwise when the program > closes > its open port it will crash the driver. > > The proposed change is as follows: > if (serial) { > for (i = 0; i < serial->num_ports; ++i) { > port = serial->port[i]; > if (port && port->tty) > { > tty_hangup(port->tty); > > + /* prevents a close from an open device crashing the driver > */ > + port->tty->driver_data = NULL; > + > + /* we are also done with the reference used by tty */ > + usb_serial_put(serial); > } > } > /* let the last holder of this object > * cause it to be cleaned up */ > usb_serial_put(serial); > } > Steps to reproduce: > 1. Connect usb-serial device > 2. Open the port (e.g. ttyUSB0) using some program (e.g. minicom) > 3. Disconnect the usb-serial device > 4. problem occurs here, no uevent for the remove of ttyUSB0. /dev/ttyUSB0 is > still around. > 5. Can now kill/terminate the program that had the port open and the uevent > will be sent out. >
> > If you have a program that opens a port using usb-serial and the USB device > is > > disconnected there is no uevent indicating the ACTION "remove" for the tty > > device (e.g ttyUSB0). Once the port is closed the uevent is triggered and You should get a hangup on the port. That notifies the open process. No comment on the other bits although the whole open/close stuff has a couple of other races and is on the hit list for a rewrite so a semi-ugly patch here for now isn't too worrying
What's the verdict on this, Alan? Should it be closed? Tysen, have you found a solution to your problem basing on the comments from developers?
[sorry for the delayed response] Based on the comments I do have a work around. Thanks for the help and sorry for any wasted effort cause.