diff options
author | Oliver Neukum <oliver@neukum.org> | 2008-01-23 06:28:45 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-01 17:35:05 -0500 |
commit | 0915f490d81c1a5098b399ec6c0be45bd421ee1d (patch) | |
tree | 840285ec52dba9ae65757b27c68ee3933c041ff3 /drivers/usb | |
parent | 3edbc986509888fa9977cc180c1fe458d2f89076 (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')
-rw-r--r-- | drivers/usb/serial/digi_acceleport.c | 13 | ||||
-rw-r--r-- | drivers/usb/serial/oti6858.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/ti_usb_3410_5052.c | 17 |
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; |
1484 | exit: | 1484 | exit: |
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 | ||