summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2008-01-21 17:44:10 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 14:35:04 -0800
commite33fe4d86f91127f6f7d931ff59ed6cbda06e72b (patch)
tree7af352e8fc696220a06c6e2a9b9006a0ea5ee075
parent004b4f2d4448cff7f13871c05d744b00a7c74d4a (diff)
downloadlinux-e33fe4d86f91127f6f7d931ff59ed6cbda06e72b.tar.gz
linux-e33fe4d86f91127f6f7d931ff59ed6cbda06e72b.tar.bz2
linux-e33fe4d86f91127f6f7d931ff59ed6cbda06e72b.zip
USB: make sure usb serial drivers don't flush to logically disconnected devices
If disconnect() is called for a logical disconnect, no more IO must be done after disconnect() returns, or the old and new drivers may conflict. This patch avoids this by using the flag and lock introduced by the earlier patch for the mos7720 driver. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/serial/mct_u232.c17
-rw-r--r--drivers/usb/serial/option.c5
-rw-r--r--drivers/usb/serial/sierra.c5
-rw-r--r--drivers/usb/serial/visor.c22
-rw-r--r--drivers/usb/serial/whiteheat.c7
5 files changed, 35 insertions, 21 deletions
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 88b2074867c5..fc1cea4aba13 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 bbbe1b962008..5e8bf1bc1e50 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 953bdf8827d2..4c925e3e8a63 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 7ee087fed913..c2347995c786 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 f5033d482eee..38726ef3132b 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;