diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index edd162df49ca..d4809d551473 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -69,9 +69,7 @@ struct ftdi_private { | |||
69 | int flags; /* some ASYNC_xxxx flags are supported */ | 69 | int flags; /* some ASYNC_xxxx flags are supported */ |
70 | unsigned long last_dtr_rts; /* saved modem control outputs */ | 70 | unsigned long last_dtr_rts; /* saved modem control outputs */ |
71 | struct async_icount icount; | 71 | struct async_icount icount; |
72 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
73 | char prev_status; /* Used for TIOCMIWAIT */ | 72 | char prev_status; /* Used for TIOCMIWAIT */ |
74 | bool dev_gone; /* Used to abort TIOCMIWAIT */ | ||
75 | char transmit_empty; /* If transmitter is empty or not */ | 73 | char transmit_empty; /* If transmitter is empty or not */ |
76 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface | 74 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface |
77 | (0 for FT232/245) */ | 75 | (0 for FT232/245) */ |
@@ -1691,10 +1689,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1691 | 1689 | ||
1692 | kref_init(&priv->kref); | 1690 | kref_init(&priv->kref); |
1693 | mutex_init(&priv->cfg_lock); | 1691 | mutex_init(&priv->cfg_lock); |
1694 | init_waitqueue_head(&priv->delta_msr_wait); | ||
1695 | 1692 | ||
1696 | priv->flags = ASYNC_LOW_LATENCY; | 1693 | priv->flags = ASYNC_LOW_LATENCY; |
1697 | priv->dev_gone = false; | ||
1698 | 1694 | ||
1699 | if (quirk && quirk->port_probe) | 1695 | if (quirk && quirk->port_probe) |
1700 | quirk->port_probe(priv); | 1696 | quirk->port_probe(priv); |
@@ -1840,8 +1836,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) | |||
1840 | { | 1836 | { |
1841 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1837 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1842 | 1838 | ||
1843 | priv->dev_gone = true; | 1839 | wake_up_interruptible(&port->delta_msr_wait); |
1844 | wake_up_interruptible_all(&priv->delta_msr_wait); | ||
1845 | 1840 | ||
1846 | remove_sysfs_attrs(port); | 1841 | remove_sysfs_attrs(port); |
1847 | 1842 | ||
@@ -1989,7 +1984,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, | |||
1989 | if (diff_status & FTDI_RS0_RLSD) | 1984 | if (diff_status & FTDI_RS0_RLSD) |
1990 | priv->icount.dcd++; | 1985 | priv->icount.dcd++; |
1991 | 1986 | ||
1992 | wake_up_interruptible_all(&priv->delta_msr_wait); | 1987 | wake_up_interruptible(&port->delta_msr_wait); |
1993 | priv->prev_status = status; | 1988 | priv->prev_status = status; |
1994 | } | 1989 | } |
1995 | 1990 | ||
@@ -2440,11 +2435,15 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2440 | */ | 2435 | */ |
2441 | case TIOCMIWAIT: | 2436 | case TIOCMIWAIT: |
2442 | cprev = priv->icount; | 2437 | cprev = priv->icount; |
2443 | while (!priv->dev_gone) { | 2438 | for (;;) { |
2444 | interruptible_sleep_on(&priv->delta_msr_wait); | 2439 | interruptible_sleep_on(&port->delta_msr_wait); |
2445 | /* see if a signal did it */ | 2440 | /* see if a signal did it */ |
2446 | if (signal_pending(current)) | 2441 | if (signal_pending(current)) |
2447 | return -ERESTARTSYS; | 2442 | return -ERESTARTSYS; |
2443 | |||
2444 | if (port->serial->disconnected) | ||
2445 | return -EIO; | ||
2446 | |||
2448 | cnow = priv->icount; | 2447 | cnow = priv->icount; |
2449 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 2448 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
2450 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 2449 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
@@ -2454,8 +2453,6 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2454 | } | 2453 | } |
2455 | cprev = cnow; | 2454 | cprev = cnow; |
2456 | } | 2455 | } |
2457 | return -EIO; | ||
2458 | break; | ||
2459 | case TIOCSERGETLSR: | 2456 | case TIOCSERGETLSR: |
2460 | return get_lsr_info(port, (struct serial_struct __user *)arg); | 2457 | return get_lsr_info(port, (struct serial_struct __user *)arg); |
2461 | break; | 2458 | break; |