# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.571 -> 1.572 # drivers/usb/serial/usbserial.c 1.28 -> 1.29 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/03/28 ganesh@veritas.com 1.572 # USB serial core # # Module count of a serial converter driver is currently not # decremented if a disconnect happens while the tty is held open. # The fix is to close the device in usb_serial_disconnect() so that # module refcounts are properly updated. # -------------------------------------------- # diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c --- a/drivers/usb/serial/usbserial.c Wed Apr 3 16:39:19 2002 +++ b/drivers/usb/serial/usbserial.c Wed Apr 3 16:39:19 2002 @@ -576,43 +576,45 @@ return retval; } -static void serial_close(struct tty_struct *tty, struct file * filp) +static void __serial_close(struct usb_serial_port *port, struct file *filp) { - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - return; - - down (&port->sem); - - dbg(__FUNCTION__ " - port %d", port->number); - - if (tty->driver_data == NULL) { - /* disconnect beat us to the punch here, so handle it gracefully */ - goto exit; - } if (!port->open_count) { dbg (__FUNCTION__ " - port not opened"); - goto exit_no_mod_dec; + return; } --port->open_count; if (port->open_count <= 0) { /* only call the device specific close if this * port is being closed by the last owner */ - if (serial->type->close) - serial->type->close(port, filp); + if (port->serial->type->close) + port->serial->type->close(port, filp); else generic_close(port, filp); port->open_count = 0; } -exit: - if (serial->type->owner) - __MOD_DEC_USE_COUNT(serial->type->owner); + if (port->serial->type->owner) + __MOD_DEC_USE_COUNT(port->serial->type->owner); +} + +static void serial_close(struct tty_struct *tty, struct file * filp) +{ + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + + if (!serial) + return; + + down (&port->sem); + + dbg(__FUNCTION__ " - port %d", port->number); + + /* if disconnect beat us to the punch here, there's nothing to do */ + if (tty->driver_data) { + __serial_close(port, filp); + } -exit_no_mod_dec: up (&port->sem); } @@ -1400,10 +1402,15 @@ if (serial) { /* fail all future close/read/write/ioctl/etc calls */ for (i = 0; i < serial->num_ports; ++i) { - down (&serial->port[i].sem); - if (serial->port[i].tty != NULL) - serial->port[i].tty->driver_data = NULL; - up (&serial->port[i].sem); + port = &serial->port[i]; + down (&port->sem); + if (port->tty != NULL) { + while (port->open_count > 0) { + __serial_close(port, NULL); + } + port->tty->driver_data = NULL; + } + up (&port->sem); } serial->dev = NULL;