aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2008-01-23 06:28:45 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:35:05 -0500
commit0915f490d81c1a5098b399ec6c0be45bd421ee1d (patch)
tree840285ec52dba9ae65757b27c68ee3933c041ff3 /drivers/usb/serial
parent3edbc986509888fa9977cc180c1fe458d2f89076 (diff)
USB: last abuses of intfdata in close for usb-serial drivers
these drivers abused intfdata in close() as flags for binding. That races with reprobing of those devices. This patch fixes that by using the flag and the locks introduced with the patch against mos7720. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/digi_acceleport.c13
-rw-r--r--drivers/usb/serial/oti6858.c2
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c17
4 files changed, 19 insertions, 15 deletions
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index ae410c4678ea..5f9c6e46bee5 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1405,19 +1405,19 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
1405 unsigned char buf[32]; 1405 unsigned char buf[32];
1406 struct tty_struct *tty = port->tty; 1406 struct tty_struct *tty = port->tty;
1407 struct digi_port *priv = usb_get_serial_port_data(port); 1407 struct digi_port *priv = usb_get_serial_port_data(port);
1408 unsigned long flags = 0;
1409 1408
1410 dbg("digi_close: TOP: port=%d, open_count=%d", 1409 dbg("digi_close: TOP: port=%d, open_count=%d",
1411 priv->dp_port_num, port->open_count); 1410 priv->dp_port_num, port->open_count);
1412 1411
1412 mutex_lock(&port->serial->disc_mutex);
1413 /* if disconnected, just clear flags */ 1413 /* if disconnected, just clear flags */
1414 if (!usb_get_intfdata(port->serial->interface)) 1414 if (port->serial->disconnected)
1415 goto exit; 1415 goto exit;
1416 1416
1417 /* do cleanup only after final close on this port */ 1417 /* do cleanup only after final close on this port */
1418 spin_lock_irqsave(&priv->dp_port_lock, flags); 1418 spin_lock_irq(&priv->dp_port_lock);
1419 priv->dp_in_close = 1; 1419 priv->dp_in_close = 1;
1420 spin_unlock_irqrestore(&priv->dp_port_lock, flags); 1420 spin_unlock_irq(&priv->dp_port_lock);
1421 1421
1422 /* tell line discipline to process only XON/XOFF */ 1422 /* tell line discipline to process only XON/XOFF */
1423 tty->closing = 1; 1423 tty->closing = 1;
@@ -1482,11 +1482,12 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
1482 } 1482 }
1483 tty->closing = 0; 1483 tty->closing = 0;
1484exit: 1484exit:
1485 spin_lock_irqsave(&priv->dp_port_lock, flags); 1485 spin_lock_irq(&priv->dp_port_lock);
1486 priv->dp_write_urb_in_use = 0; 1486 priv->dp_write_urb_in_use = 0;
1487 priv->dp_in_close = 0; 1487 priv->dp_in_close = 0;
1488 wake_up_interruptible(&priv->dp_close_wait); 1488 wake_up_interruptible(&priv->dp_close_wait);
1489 spin_unlock_irqrestore(&priv->dp_port_lock, flags); 1489 spin_unlock_irq(&priv->dp_port_lock);
1490 mutex_unlock(&port->serial->disc_mutex);
1490 dbg("digi_close: done"); 1491 dbg("digi_close: done");
1491} 1492}
1492 1493
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index db725aaf7d19..a3847d6c946e 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -649,7 +649,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
649 set_current_state(TASK_INTERRUPTIBLE); 649 set_current_state(TASK_INTERRUPTIBLE);
650 if (oti6858_buf_data_avail(priv->buf) == 0 650 if (oti6858_buf_data_avail(priv->buf) == 0
651 || timeout == 0 || signal_pending(current) 651 || timeout == 0 || signal_pending(current)
652 || !usb_get_intfdata(port->serial->interface)) /* disconnect */ 652 || port->serial->disconnected)
653 break; 653 break;
654 spin_unlock_irqrestore(&priv->lock, flags); 654 spin_unlock_irqrestore(&priv->lock, flags);
655 timeout = schedule_timeout(timeout); 655 timeout = schedule_timeout(timeout);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index ac3d8765f482..ae3ec1a64008 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -667,7 +667,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
667 set_current_state(TASK_INTERRUPTIBLE); 667 set_current_state(TASK_INTERRUPTIBLE);
668 if (pl2303_buf_data_avail(priv->buf) == 0 || 668 if (pl2303_buf_data_avail(priv->buf) == 0 ||
669 timeout == 0 || signal_pending(current) || 669 timeout == 0 || signal_pending(current) ||
670 !usb_get_intfdata(port->serial->interface)) /* disconnect */ 670 port->serial->disconnected)
671 break; 671 break;
672 spin_unlock_irqrestore(&priv->lock, flags); 672 spin_unlock_irqrestore(&priv->lock, flags);
673 timeout = schedule_timeout(timeout); 673 timeout = schedule_timeout(timeout);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 70f56c8aef99..b517f93352ec 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1493,11 +1493,10 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
1493 struct ti_device *tdev = tport->tp_tdev; 1493 struct ti_device *tdev = tport->tp_tdev;
1494 struct usb_serial_port *port = tport->tp_port; 1494 struct usb_serial_port *port = tport->tp_port;
1495 wait_queue_t wait; 1495 wait_queue_t wait;
1496 unsigned long flags;
1497 1496
1498 dbg("%s - port %d", __FUNCTION__, port->number); 1497 dbg("%s - port %d", __FUNCTION__, port->number);
1499 1498
1500 spin_lock_irqsave(&tport->tp_lock, flags); 1499 spin_lock_irq(&tport->tp_lock);
1501 1500
1502 /* wait for data to drain from the buffer */ 1501 /* wait for data to drain from the buffer */
1503 tdev->td_urb_error = 0; 1502 tdev->td_urb_error = 0;
@@ -1508,11 +1507,11 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
1508 if (ti_buf_data_avail(tport->tp_write_buf) == 0 1507 if (ti_buf_data_avail(tport->tp_write_buf) == 0
1509 || timeout == 0 || signal_pending(current) 1508 || timeout == 0 || signal_pending(current)
1510 || tdev->td_urb_error 1509 || tdev->td_urb_error
1511 || !usb_get_intfdata(port->serial->interface)) /* disconnect */ 1510 || port->serial->disconnected) /* disconnect */
1512 break; 1511 break;
1513 spin_unlock_irqrestore(&tport->tp_lock, flags); 1512 spin_unlock_irq(&tport->tp_lock);
1514 timeout = schedule_timeout(timeout); 1513 timeout = schedule_timeout(timeout);
1515 spin_lock_irqsave(&tport->tp_lock, flags); 1514 spin_lock_irq(&tport->tp_lock);
1516 } 1515 }
1517 set_current_state(TASK_RUNNING); 1516 set_current_state(TASK_RUNNING);
1518 remove_wait_queue(&tport->tp_write_wait, &wait); 1517 remove_wait_queue(&tport->tp_write_wait, &wait);
@@ -1521,19 +1520,23 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
1521 if (flush) 1520 if (flush)
1522 ti_buf_clear(tport->tp_write_buf); 1521 ti_buf_clear(tport->tp_write_buf);
1523 1522
1524 spin_unlock_irqrestore(&tport->tp_lock, flags); 1523 spin_unlock_irq(&tport->tp_lock);
1525 1524
1525 mutex_lock(&port->serial->disc_mutex);
1526 /* wait for data to drain from the device */ 1526 /* wait for data to drain from the device */
1527 /* wait for empty tx register, plus 20 ms */ 1527 /* wait for empty tx register, plus 20 ms */
1528 timeout += jiffies; 1528 timeout += jiffies;
1529 tport->tp_lsr &= ~TI_LSR_TX_EMPTY; 1529 tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
1530 while ((long)(jiffies - timeout) < 0 && !signal_pending(current) 1530 while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
1531 && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error 1531 && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
1532 && usb_get_intfdata(port->serial->interface)) { /* not disconnected */ 1532 && !port->serial->disconnected) {
1533 if (ti_get_lsr(tport)) 1533 if (ti_get_lsr(tport))
1534 break; 1534 break;
1535 mutex_unlock(&port->serial->disc_mutex);
1535 msleep_interruptible(20); 1536 msleep_interruptible(20);
1537 mutex_lock(&port->serial->disc_mutex);
1536 } 1538 }
1539 mutex_unlock(&port->serial->disc_mutex);
1537} 1540}
1538 1541
1539 1542