aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/serial/ftdi_sio.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c02e4602d90a..02e7f2d32d52 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -76,6 +76,7 @@ struct ftdi_private {
76 struct async_icount icount; 76 struct async_icount icount;
77 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ 77 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
78 char prev_status; /* Used for TIOCMIWAIT */ 78 char prev_status; /* Used for TIOCMIWAIT */
79 bool dev_gone; /* Used to abort TIOCMIWAIT */
79 char transmit_empty; /* If transmitter is empty or not */ 80 char transmit_empty; /* If transmitter is empty or not */
80 struct usb_serial_port *port; 81 struct usb_serial_port *port;
81 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface 82 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface
@@ -1681,6 +1682,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
1681 init_waitqueue_head(&priv->delta_msr_wait); 1682 init_waitqueue_head(&priv->delta_msr_wait);
1682 1683
1683 priv->flags = ASYNC_LOW_LATENCY; 1684 priv->flags = ASYNC_LOW_LATENCY;
1685 priv->dev_gone = false;
1684 1686
1685 if (quirk && quirk->port_probe) 1687 if (quirk && quirk->port_probe)
1686 quirk->port_probe(priv); 1688 quirk->port_probe(priv);
@@ -1839,6 +1841,9 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
1839 1841
1840 dbg("%s", __func__); 1842 dbg("%s", __func__);
1841 1843
1844 priv->dev_gone = true;
1845 wake_up_interruptible_all(&priv->delta_msr_wait);
1846
1842 remove_sysfs_attrs(port); 1847 remove_sysfs_attrs(port);
1843 1848
1844 kref_put(&priv->kref, ftdi_sio_priv_release); 1849 kref_put(&priv->kref, ftdi_sio_priv_release);
@@ -2397,15 +2402,12 @@ static int ftdi_ioctl(struct tty_struct *tty,
2397 */ 2402 */
2398 case TIOCMIWAIT: 2403 case TIOCMIWAIT:
2399 cprev = priv->icount; 2404 cprev = priv->icount;
2400 while (1) { 2405 while (!priv->dev_gone) {
2401 interruptible_sleep_on(&priv->delta_msr_wait); 2406 interruptible_sleep_on(&priv->delta_msr_wait);
2402 /* see if a signal did it */ 2407 /* see if a signal did it */
2403 if (signal_pending(current)) 2408 if (signal_pending(current))
2404 return -ERESTARTSYS; 2409 return -ERESTARTSYS;
2405 cnow = priv->icount; 2410 cnow = priv->icount;
2406 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2407 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
2408 return -EIO; /* no change => error */
2409 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || 2411 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2410 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || 2412 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2411 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || 2413 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
@@ -2414,7 +2416,7 @@ static int ftdi_ioctl(struct tty_struct *tty,
2414 } 2416 }
2415 cprev = cnow; 2417 cprev = cnow;
2416 } 2418 }
2417 /* not reached */ 2419 return -EIO;
2418 break; 2420 break;
2419 case TIOCSERGETLSR: 2421 case TIOCSERGETLSR:
2420 return get_lsr_info(port, (struct serial_struct __user *)arg); 2422 return get_lsr_info(port, (struct serial_struct __user *)arg);