diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index edd162df49ca..9886180e45f1 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) */ |
@@ -642,6 +640,7 @@ static struct usb_device_id id_table_combined [] = { | |||
642 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, | 640 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, |
643 | { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, | 641 | { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, |
644 | { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, | 642 | { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, |
643 | { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) }, | ||
645 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, | 644 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, |
646 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, | 645 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, |
647 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, | 646 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, |
@@ -1691,10 +1690,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1691 | 1690 | ||
1692 | kref_init(&priv->kref); | 1691 | kref_init(&priv->kref); |
1693 | mutex_init(&priv->cfg_lock); | 1692 | mutex_init(&priv->cfg_lock); |
1694 | init_waitqueue_head(&priv->delta_msr_wait); | ||
1695 | 1693 | ||
1696 | priv->flags = ASYNC_LOW_LATENCY; | 1694 | priv->flags = ASYNC_LOW_LATENCY; |
1697 | priv->dev_gone = false; | ||
1698 | 1695 | ||
1699 | if (quirk && quirk->port_probe) | 1696 | if (quirk && quirk->port_probe) |
1700 | quirk->port_probe(priv); | 1697 | quirk->port_probe(priv); |
@@ -1840,8 +1837,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) | |||
1840 | { | 1837 | { |
1841 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1838 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1842 | 1839 | ||
1843 | priv->dev_gone = true; | 1840 | wake_up_interruptible(&port->delta_msr_wait); |
1844 | wake_up_interruptible_all(&priv->delta_msr_wait); | ||
1845 | 1841 | ||
1846 | remove_sysfs_attrs(port); | 1842 | remove_sysfs_attrs(port); |
1847 | 1843 | ||
@@ -1989,7 +1985,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, | |||
1989 | if (diff_status & FTDI_RS0_RLSD) | 1985 | if (diff_status & FTDI_RS0_RLSD) |
1990 | priv->icount.dcd++; | 1986 | priv->icount.dcd++; |
1991 | 1987 | ||
1992 | wake_up_interruptible_all(&priv->delta_msr_wait); | 1988 | wake_up_interruptible(&port->delta_msr_wait); |
1993 | priv->prev_status = status; | 1989 | priv->prev_status = status; |
1994 | } | 1990 | } |
1995 | 1991 | ||
@@ -2440,11 +2436,15 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2440 | */ | 2436 | */ |
2441 | case TIOCMIWAIT: | 2437 | case TIOCMIWAIT: |
2442 | cprev = priv->icount; | 2438 | cprev = priv->icount; |
2443 | while (!priv->dev_gone) { | 2439 | for (;;) { |
2444 | interruptible_sleep_on(&priv->delta_msr_wait); | 2440 | interruptible_sleep_on(&port->delta_msr_wait); |
2445 | /* see if a signal did it */ | 2441 | /* see if a signal did it */ |
2446 | if (signal_pending(current)) | 2442 | if (signal_pending(current)) |
2447 | return -ERESTARTSYS; | 2443 | return -ERESTARTSYS; |
2444 | |||
2445 | if (port->serial->disconnected) | ||
2446 | return -EIO; | ||
2447 | |||
2448 | cnow = priv->icount; | 2448 | cnow = priv->icount; |
2449 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 2449 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
2450 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 2450 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
@@ -2454,8 +2454,6 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2454 | } | 2454 | } |
2455 | cprev = cnow; | 2455 | cprev = cnow; |
2456 | } | 2456 | } |
2457 | return -EIO; | ||
2458 | break; | ||
2459 | case TIOCSERGETLSR: | 2457 | case TIOCSERGETLSR: |
2460 | return get_lsr_info(port, (struct serial_struct __user *)arg); | 2458 | return get_lsr_info(port, (struct serial_struct __user *)arg); |
2461 | break; | 2459 | break; |