aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2008-01-21 11:44:10 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:35:04 -0500
commite33fe4d86f91127f6f7d931ff59ed6cbda06e72b (patch)
tree7af352e8fc696220a06c6e2a9b9006a0ea5ee075 /drivers/usb
parent004b4f2d4448cff7f13871c05d744b00a7c74d4a (diff)
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>
Diffstat (limited to 'drivers/usb')
-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:
487static void mct_u232_close (struct usb_serial_port *port, struct file *filp) 487static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
488{ 488{
489 unsigned int c_cflag; 489 unsigned int c_cflag;
490 unsigned long flags;
491 unsigned int control_state; 490 unsigned int control_state;
492 struct mct_u232_private *priv = usb_get_serial_port_data(port); 491 struct mct_u232_private *priv = usb_get_serial_port_data(port);
493 dbg("%s port %d", __FUNCTION__, port->number); 492 dbg("%s port %d", __FUNCTION__, port->number);
494 493
495 if (port->tty) { 494 if (port->tty) {
496 c_cflag = port->tty->termios->c_cflag; 495 c_cflag = port->tty->termios->c_cflag;
497 if (c_cflag & HUPCL) { 496 mutex_lock(&port->serial->disc_mutex);
498 /* drop DTR and RTS */ 497 if (c_cflag & HUPCL && !port->serial->disconnected) {
499 spin_lock_irqsave(&priv->lock, flags); 498 /* drop DTR and RTS */
500 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); 499 spin_lock_irq(&priv->lock);
501 control_state = priv->control_state; 500 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
502 spin_unlock_irqrestore(&priv->lock, flags); 501 control_state = priv->control_state;
503 mct_u232_set_modem_ctrl(port->serial, control_state); 502 spin_unlock_irq(&priv->lock);
503 mct_u232_set_modem_ctrl(port->serial, control_state);
504 } 504 }
505 mutex_unlock(&port->serial->disc_mutex);
505 } 506 }
506 507
507 508
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)
641 portdata->dtr_state = 0; 641 portdata->dtr_state = 0;
642 642
643 if (serial->dev) { 643 if (serial->dev) {
644 option_send_setup(port); 644 mutex_lock(&serial->disc_mutex);
645 if (!serial->disconnected)
646 option_send_setup(port);
647 mutex_unlock(&serial->disc_mutex);
645 648
646 /* Stop reading/writing urbs */ 649 /* Stop reading/writing urbs */
647 for (i = 0; i < N_IN_URB; i++) 650 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)
597 portdata->dtr_state = 0; 597 portdata->dtr_state = 0;
598 598
599 if (serial->dev) { 599 if (serial->dev) {
600 sierra_send_setup(port); 600 mutex_lock(&serial->disc_mutex);
601 if (!serial->disconnected)
602 sierra_send_setup(port);
603 mutex_unlock(&serial->disc_mutex);
601 604
602 /* Stop reading/writing urbs */ 605 /* Stop reading/writing urbs */
603 for (i = 0; i < N_IN_URB; i++) 606 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)
349 usb_kill_urb(port->read_urb); 349 usb_kill_urb(port->read_urb);
350 usb_kill_urb(port->interrupt_in_urb); 350 usb_kill_urb(port->interrupt_in_urb);
351 351
352 /* Try to send shutdown message, if the device is gone, this will just fail. */ 352 mutex_lock(&port->serial->disc_mutex);
353 transfer_buffer = kmalloc (0x12, GFP_KERNEL); 353 if (!port->serial->disconnected) {
354 if (transfer_buffer) { 354 /* Try to send shutdown message, unless the device is gone */
355 usb_control_msg (port->serial->dev, 355 transfer_buffer = kmalloc (0x12, GFP_KERNEL);
356 usb_rcvctrlpipe(port->serial->dev, 0), 356 if (transfer_buffer) {
357 VISOR_CLOSE_NOTIFICATION, 0xc2, 357 usb_control_msg (port->serial->dev,
358 0x0000, 0x0000, 358 usb_rcvctrlpipe(port->serial->dev, 0),
359 transfer_buffer, 0x12, 300); 359 VISOR_CLOSE_NOTIFICATION, 0xc2,
360 kfree (transfer_buffer); 360 0x0000, 0x0000,
361 transfer_buffer, 0x12, 300);
362 kfree (transfer_buffer);
363 }
361 } 364 }
365 mutex_lock(&port->serial->disc_mutex);
362 366
363 if (stats) 367 if (stats)
364 dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", 368 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)
658 struct list_head *tmp2; 658 struct list_head *tmp2;
659 659
660 dbg("%s - port %d", __FUNCTION__, port->number); 660 dbg("%s - port %d", __FUNCTION__, port->number);
661 661
662 mutex_lock(&port->serial->disc_mutex);
662 /* filp is NULL when called from usb_serial_disconnect */ 663 /* filp is NULL when called from usb_serial_disconnect */
663 if (filp && (tty_hung_up_p(filp))) { 664 if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
665 mutex_unlock(&port->serial->disc_mutex);
664 return; 666 return;
665 } 667 }
668 mutex_unlock(&port->serial->disc_mutex);
666 669
667 port->tty->closing = 1; 670 port->tty->closing = 1;
668 671