diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 88b2074867c..fc1cea4aba1 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -487,21 +487,22 @@ error: static void mct_u232_close (struct usb_serial_port *port, struct file *filp) { unsigned int c_cflag; - unsigned long flags; unsigned int control_state; struct mct_u232_private *priv = usb_get_serial_port_data(port); dbg("%s port %d", __FUNCTION__, port->number); if (port->tty) { c_cflag = port->tty->termios->c_cflag; - if (c_cflag & HUPCL) { - /* drop DTR and RTS */ - spin_lock_irqsave(&priv->lock, flags); - priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); - control_state = priv->control_state; - spin_unlock_irqrestore(&priv->lock, flags); - mct_u232_set_modem_ctrl(port->serial, control_state); + mutex_lock(&port->serial->disc_mutex); + if (c_cflag & HUPCL && !port->serial->disconnected) { + /* drop DTR and RTS */ + spin_lock_irq(&priv->lock); + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + control_state = priv->control_state; + spin_unlock_irq(&priv->lock); + mct_u232_set_modem_ctrl(port->serial, control_state); } + mutex_unlock(&port->serial->disc_mutex); } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index bbbe1b96200..5e8bf1bc1e5 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -641,7 +641,10 @@ static void option_close(struct usb_serial_port *port, struct file *filp) portdata->dtr_state = 0; if (serial->dev) { - option_send_setup(port); + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) + option_send_setup(port); + mutex_unlock(&serial->disc_mutex); /* Stop reading/writing urbs */ for (i = 0; i < N_IN_URB; i++) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 953bdf8827d..4c925e3e8a6 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -597,7 +597,10 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) portdata->dtr_state = 0; if (serial->dev) { - sierra_send_setup(port); + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) + sierra_send_setup(port); + mutex_unlock(&serial->disc_mutex); /* Stop reading/writing urbs */ for (i = 0; i < N_IN_URB; i++) diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 7ee087fed91..c2347995c78 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -349,16 +349,20 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); - /* Try to send shutdown message, if the device is gone, this will just fail. */ - transfer_buffer = kmalloc (0x12, GFP_KERNEL); - if (transfer_buffer) { - usb_control_msg (port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - VISOR_CLOSE_NOTIFICATION, 0xc2, - 0x0000, 0x0000, - transfer_buffer, 0x12, 300); - kfree (transfer_buffer); + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) { + /* Try to send shutdown message, unless the device is gone */ + transfer_buffer = kmalloc (0x12, GFP_KERNEL); + if (transfer_buffer) { + usb_control_msg (port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + VISOR_CLOSE_NOTIFICATION, 0xc2, + 0x0000, 0x0000, + transfer_buffer, 0x12, 300); + kfree (transfer_buffer); + } } + mutex_lock(&port->serial->disc_mutex); if (stats) dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index f5033d482ee..38726ef3132 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -658,11 +658,14 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) struct list_head *tmp2; dbg("%s - port %d", __FUNCTION__, port->number); - + + mutex_lock(&port->serial->disc_mutex); /* filp is NULL when called from usb_serial_disconnect */ - if (filp && (tty_hung_up_p(filp))) { + if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) { + mutex_unlock(&port->serial->disc_mutex); return; } + mutex_unlock(&port->serial->disc_mutex); port->tty->closing = 1;