Hi, > > I also checked, how the read URB's are resubmitted, the logic in the > > driver is correct. The upper layer (usb-serial.c) calls ftdi_close, only > > when the port->open_count <= 0. The function ftdi_process_read(), that is > > issued by the completion handler (ftdi_read_bulk_callback()), tries to > > resubmit the URB iff the port hasn't been closed yet(see code snippet > > below). I could think of, a race condition on an SMP system, where 1 > > thread has just finished the comparison (port->open_count > 0) and the > > other thread would try killing the URB at the same time - last process > > closed the device. Do we want the error be displayed?? > > That race condition is exactly what I was talking about. Since it's bound > to be pretty rare, there's probably no harm in displaying the error > message. But it also wouldn't hurt to check for result != -EPERM. It's > your choice. > > Alan Stern
I think, it's better to leave the error message in there as it is. The attached patch covers the fixes in ftdi_sio.c and usb-serial.c. Could anyone (Ian/Alan?) put the 'signed-off-by:' stamp on it after looking at it, so that it can be applied by Greg? Thanks in advance, Jan
--- linux-2.6.9-rc1-mm1/drivers/usb/serial/ftdi_sio.c 2004-09-08 04:51:23.000000000 +0200 +++ linux-2.6.9-rc1-mm1-ccs/drivers/usb/serial/ftdi_sio.c 2004-09-08 14:00:53.000000000 +0200 @@ -1487,17 +1487,9 @@ } } /* Note change no line if hupcl is off */ - /* shutdown our bulk read */ - if (port->read_urb) { - if (usb_unlink_urb (port->read_urb) < 0) { - /* Generally, this isn't an error. If the previous - read bulk callback occurred (or is about to occur) - while the port was being closed or was throtted - (and is still throttled), the read urb will not - have been submitted. */ - dbg("%s - failed to unlink read urb (generally not an error)", __FUNCTION__); - } - } + /* shutdown our bulk read - synchronously */ + usb_kill_urb(port->read_urb); + } /* ftdi_close */ --- linux-2.6.9-rc1-mm1/drivers/usb/serial/usb-serial.c 2004-09-08 04:51:23.000000000 +0200 +++ linux-2.6.9-rc1-mm1-ccs/drivers/usb/serial/usb-serial.c 2004-09-08 15:31:11.000000000 +0200 @@ -14,6 +14,14 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (09/08/2004) Jan Capek + * destroy_serial(), port_release() - removed test on URB's being NULL as + * these checks are always performed by underlying usb_kill_urb(), + * usb_unlink_urb, usb_free_urb() resp. Further, port->read_urb is now + * removed synchronously using usb_kill_urb() instead of usb_unlink_urb(). + * This is to ensure consistency with the urb.c, so that usb_unlink_urb() + * is not used for synchronous unlinking anymore. + * * (12/10/2002) gkh * Split the ports off into their own struct device, and added a * usb-serial bus driver. @@ -454,18 +462,15 @@ port = serial->port[i]; if (!port) continue; - if (port->read_urb) { - usb_unlink_urb(port->read_urb); - usb_free_urb(port->read_urb); - } - if (port->write_urb) { - usb_unlink_urb(port->write_urb); - usb_free_urb(port->write_urb); - } - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_free_urb(port->interrupt_in_urb); - } + usb_kill_urb(port->read_urb); + usb_free_urb(port->read_urb); + + usb_unlink_urb(port->write_urb); + usb_free_urb(port->write_urb); + + usb_unlink_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); kfree(port->interrupt_in_buffer); @@ -818,18 +823,16 @@ struct usb_serial_port *port = to_usb_serial_port(dev); dbg ("%s - %s", __FUNCTION__, dev->bus_id); - if (port->read_urb) { - usb_unlink_urb(port->read_urb); - usb_free_urb(port->read_urb); - } - if (port->write_urb) { - usb_unlink_urb(port->write_urb); - usb_free_urb(port->write_urb); - } - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_free_urb(port->interrupt_in_urb); - } + + usb_kill_urb(port->read_urb); + usb_free_urb(port->read_urb); + + usb_unlink_urb(port->write_urb); + usb_free_urb(port->write_urb); + + usb_unlink_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); kfree(port->interrupt_in_buffer);