USB: ch341: switch to generic TIOCMIWAIT implementation
authorJohan Hovold <jhovold@gmail.com>
Thu, 2 Jan 2014 21:49:32 +0000 (22:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 3 Jan 2014 20:42:24 +0000 (12:42 -0800)
Switch to the generic TIOCMIWAIT implementation which does not suffer
from the races involved when using the deprecated sleep_on functions.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/serial/ch341.c

index acc88650ac0ac7350d2a8758c9fa0aaf9374fcf8..ac21618ace190e67ce3a9b454120780a51299250 100644 (file)
@@ -463,7 +463,14 @@ static void ch341_update_line_status(struct usb_serial_port *port,
        if (!delta)
                return;
 
+       if (delta & CH341_BIT_CTS)
+               port->icount.cts++;
+       if (delta & CH341_BIT_DSR)
+               port->icount.dsr++;
+       if (delta & CH341_BIT_RI)
+               port->icount.rng++;
        if (delta & CH341_BIT_DCD) {
+               port->icount.dcd++;
                tty = tty_port_tty_get(&port->port);
                if (tty) {
                        usb_serial_handle_dcd_change(port, tty,
@@ -510,46 +517,6 @@ exit:
                        __func__, status);
 }
 
-static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ch341_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       u8 prevstatus;
-       u8 status;
-       u8 changed;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       prevstatus = priv->line_status;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       for (;;) {
-               interruptible_sleep_on(&port->port.delta_msr_wait);
-               /* see if a signal did it */
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-
-               if (port->serial->disconnected)
-                       return -EIO;
-
-               spin_lock_irqsave(&priv->lock, flags);
-               status = priv->line_status;
-               spin_unlock_irqrestore(&priv->lock, flags);
-
-               changed = prevstatus ^ status;
-
-               if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) ||
-                   ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) ||
-                   ((arg & TIOCM_CD)  && (changed & CH341_BIT_DCD)) ||
-                   ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) {
-                       return 0;
-               }
-               prevstatus = status;
-       }
-
-       return 0;
-}
-
 static int ch341_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -603,7 +570,7 @@ static struct usb_serial_driver ch341_device = {
        .break_ctl         = ch341_break_ctl,
        .tiocmget          = ch341_tiocmget,
        .tiocmset          = ch341_tiocmset,
-       .tiocmiwait        = ch341_tiocmiwait,
+       .tiocmiwait        = usb_serial_generic_tiocmiwait,
        .read_int_callback = ch341_read_int_callback,
        .port_probe        = ch341_port_probe,
        .port_remove       = ch341_port_remove,