]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
USB: serial: ftdi_sio: clean up flow control management
authorJohan Hovold <johan@kernel.org>
Fri, 18 May 2018 13:25:50 +0000 (15:25 +0200)
committerJohan Hovold <johan@kernel.org>
Mon, 21 May 2018 08:04:30 +0000 (10:04 +0200)
Clean up the somewhat convoluted hardware-assisted flow control
handling.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
drivers/usb/serial/ftdi_sio.c

index 3d7f181e7e2afb7397bcc3a7115222cf80aa85a9..b5cef322826f15a1c3980f7bb8bd99dbd9a08f11 100644 (file)
@@ -2191,12 +2191,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        struct ktermios *termios = &tty->termios;
        unsigned int cflag = termios->c_cflag;
-       u16 value;
-
-       /* Added for xon/xoff support */
-       unsigned int iflag = termios->c_iflag;
-       unsigned char vstop;
-       unsigned char vstart;
+       u16 value, index;
+       int ret;
 
        /* Force baud rate if this device requires it, unless it is set to
           B0. */
@@ -2325,61 +2321,30 @@ static void ftdi_set_termios(struct tty_struct *tty,
                        set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
        }
 
-       /* Set flow control */
-       /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
 no_c_cflag_changes:
-       if (cflag & CRTSCTS) {
-               dev_dbg(ddev, "%s Setting to CRTSCTS flow control\n", __func__);
-               if (usb_control_msg(dev,
-                                   usb_sndctrlpipe(dev, 0),
-                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST,
-                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-                                   0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
-                                   NULL, 0, WDR_TIMEOUT) < 0) {
-                       dev_err(ddev, "urb failed to set to rts/cts flow control\n");
-               }
+       /* Set hardware-assisted flow control */
+       value = 0;
+
+       if (C_CRTSCTS(tty)) {
+               dev_dbg(&port->dev, "enabling rts/cts flow control\n");
+               index = FTDI_SIO_RTS_CTS_HS;
+       } else if (I_IXON(tty)) {
+               dev_dbg(&port->dev, "enabling xon/xoff flow control\n");
+               index = FTDI_SIO_XON_XOFF_HS;
+               value = STOP_CHAR(tty) << 8 | START_CHAR(tty);
        } else {
-               /*
-                * Xon/Xoff code
-                */
-               if (iflag & IXON) {
-                       dev_dbg(ddev, "%s  request to enable xonxoff iflag=%04x\n",
-                               __func__, iflag);
-                       /* Try to enable the XON/XOFF on the ftdi_sio
-                        * Set the vstart and vstop -- could have been done up
-                        * above where a lot of other dereferencing is done but
-                        * that would be very inefficient as vstart and vstop
-                        * are not always needed.
-                        */
-                       vstart = termios->c_cc[VSTART];
-                       vstop = termios->c_cc[VSTOP];
-                       value = (vstop << 8) | (vstart);
-
-                       if (usb_control_msg(dev,
-                                           usb_sndctrlpipe(dev, 0),
-                                           FTDI_SIO_SET_FLOW_CTRL_REQUEST,
-                                           FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-                                           value , (FTDI_SIO_XON_XOFF_HS
-                                                        | priv->interface),
-                                           NULL, 0, WDR_TIMEOUT) < 0) {
-                               dev_err(&port->dev, "urb failed to set to "
-                                       "xon/xoff flow control\n");
-                       }
-               } else {
-                       /* else clause to only run if cflag ! CRTSCTS and iflag
-                        * ! XON. CHECKME Assuming XON/XOFF handled by tty
-                        * stack - not by device */
-                       dev_dbg(ddev, "%s Turning off hardware flow control\n", __func__);
-                       if (usb_control_msg(dev,
-                                           usb_sndctrlpipe(dev, 0),
-                                           FTDI_SIO_SET_FLOW_CTRL_REQUEST,
-                                           FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-                                           0, priv->interface,
-                                           NULL, 0, WDR_TIMEOUT) < 0) {
-                               dev_err(ddev, "urb failed to clear flow control\n");
-                       }
-               }
+               dev_dbg(&port->dev, "disabling flow control\n");
+               index = FTDI_SIO_DISABLE_FLOW_CTRL;
        }
+
+       index |= priv->interface;
+
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+                       FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+                       value, index, NULL, 0, WDR_TIMEOUT);
+       if (ret < 0)
+               dev_err(&port->dev, "failed to set flow control: %d\n", ret);
 }
 
 /*