Greg -- Here is a new version of the patch to usb-serial.c to fix the unbalanced kref and module get/put in serial_open and serial_close when there are errors. This version works correctly when try_module_get fails and now "rmmod --wait" works correctly.
This patch applies to 2.6.10-rc1-bk20. Please apply. Thanks, -- Al Change Log * If the low level usb serial open fails, the kref and module use counts are decremented once in open. Before, they were mistakenly decremented again in close. * If try_module_get fails, the module use count is not changed. Before, the module use count was mistakenly decremented. Now "rmmod --wait" works correctly. * The tty->driver_data pointer is never set to NULL once the port is open. Before there was a small window when it was mistakenly set to NULL for an already open port. Signed-off-by: Al Borchers <[EMAIL PROTECTED]> --- linux-2.6.10-rc1-bk20.orig/drivers/usb/serial/usb-serial.c 2004-11-10 09:30:10.000000000 -0600 +++ linux-2.6.10-rc1-bk20.new/drivers/usb/serial/usb-serial.c 2004-11-11 01:33:52.000000000 -0600 @@ -480,45 +480,51 @@ struct usb_serial *serial; struct usb_serial_port *port; unsigned int portNumber; - int retval = -ENODEV; + int retval; dbg("%s", __FUNCTION__); - /* initialize the pointer incase something fails */ - tty->driver_data = NULL; - /* get the serial object associated with this tty pointer */ serial = usb_serial_get_by_index(tty->index); - if (!serial) - goto bailout; + if (!serial) { + tty->driver_data = NULL; + return -ENODEV; + } - /* set up our port structure making the tty driver remember our port object, and us it */ portNumber = tty->index - serial->minor; port = serial->port[portNumber]; - tty->driver_data = port; - - port->tty = tty; - /* lock this module before we call it, - this may, which means we must bail out, safe because we are called with BKL held */ - if (!try_module_get(serial->type->owner)) { - kref_put(&serial->kref, destroy_serial); - goto bailout; - } - - retval = 0; ++port->open_count; + if (port->open_count == 1) { + + /* set up our port structure making the tty driver + * remember our port object, and us it */ + tty->driver_data = port; + port->tty = tty; + + /* lock this module before we call it + * this may fail, which means we must bail out, + * safe because we are called with BKL held */ + if (!try_module_get(serial->type->owner)) { + retval = -ENODEV; + goto bailout_kref_put; + } + /* only call the device specific open if this * is the first time the port is opened */ retval = serial->type->open(port, filp); - if (retval) { - port->open_count = 0; - module_put(serial->type->owner); - kref_put(&serial->kref, destroy_serial); - } + if (retval) + goto bailout_module_put; } -bailout: + + return 0; + +bailout_module_put: + module_put(serial->type->owner); +bailout_kref_put: + kref_put(&serial->kref, destroy_serial); + port->open_count = 0; return retval; } @@ -531,21 +537,24 @@ dbg("%s - port %d", __FUNCTION__, port->number); + if (port->open_count == 0) + return; + --port->open_count; - if (port->open_count <= 0) { + if (port->open_count == 0) { /* only call the device specific close if this * port is being closed by the last owner */ port->serial->type->close(port, filp); - port->open_count = 0; if (port->tty) { if (port->tty->driver_data) port->tty->driver_data = NULL; port->tty = NULL; } + + module_put(port->serial->type->owner); } - module_put(port->serial->type->owner); kref_put(&port->serial->kref, destroy_serial); } ------------------------------------------------------- This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel