USB: serial: cp210x: refactor flow-control handling
authorJohan Hovold <johan@kernel.org>
Mon, 16 Nov 2020 16:18:25 +0000 (17:18 +0100)
committerJohan Hovold <johan@kernel.org>
Fri, 4 Dec 2020 13:57:27 +0000 (14:57 +0100)
Add a helper function to be used to configure flow control.

The flow-control code was the last caller that relied on the
memset-on-failure behaviour of cp210x_read_reg_block(), which we can now
drop in favour of bailing out on errors when retrieving the flow-control
settings.

This should also simplify adding support for software flow control.

Signed-off-by: Johan Hovold <johan@kernel.org>
drivers/usb/serial/cp210x.c

index 04d2b15ceded6bf7b1c17fa7b48e4a84f671b38a..c77fd09b91ce50ab8fd1c0292e150a8720dbad9d 100644 (file)
@@ -555,14 +555,8 @@ static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req,
        int result;
 
        dmabuf = kmalloc(bufsize, GFP_KERNEL);
-       if (!dmabuf) {
-               /*
-                * FIXME Some callers don't bother to check for error,
-                * at least give them consistent junk until they are fixed
-                */
-               memset(buf, 0, bufsize);
+       if (!dmabuf)
                return -ENOMEM;
-       }
 
        result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                        req, REQTYPE_INTERFACE_TO_HOST, 0,
@@ -576,12 +570,6 @@ static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req,
                                req, bufsize, result);
                if (result >= 0)
                        result = -EIO;
-
-               /*
-                * FIXME Some callers don't bother to check for error,
-                * at least give them consistent junk until they are fixed
-                */
-               memset(buf, 0, bufsize);
        }
 
        kfree(dmabuf);
@@ -1095,11 +1083,55 @@ static bool cp210x_termios_change(const struct ktermios *a, const struct ktermio
        return tty_termios_hw_change(a, b) || iflag_change;
 }
 
+static void cp210x_set_flow_control(struct tty_struct *tty,
+               struct usb_serial_port *port, struct ktermios *old_termios)
+{
+       struct cp210x_flow_ctl flow_ctl;
+       u32 flow_repl;
+       u32 ctl_hs;
+       int ret;
+
+       if (old_termios && C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS))
+               return;
+
+       ret = cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
+                       sizeof(flow_ctl));
+       if (ret)
+               return;
+
+       ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
+       flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
+
+       ctl_hs &= ~CP210X_SERIAL_DSR_HANDSHAKE;
+       ctl_hs &= ~CP210X_SERIAL_DCD_HANDSHAKE;
+       ctl_hs &= ~CP210X_SERIAL_DSR_SENSITIVITY;
+       ctl_hs &= ~CP210X_SERIAL_DTR_MASK;
+       ctl_hs |= CP210X_SERIAL_DTR_SHIFT(CP210X_SERIAL_DTR_ACTIVE);
+
+       if (C_CRTSCTS(tty)) {
+               ctl_hs |= CP210X_SERIAL_CTS_HANDSHAKE;
+               flow_repl &= ~CP210X_SERIAL_RTS_MASK;
+               flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL);
+       } else {
+               ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE;
+               flow_repl &= ~CP210X_SERIAL_RTS_MASK;
+               flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_ACTIVE);
+       }
+
+       dev_dbg(&port->dev, "%s - ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n",
+                       __func__, ctl_hs, flow_repl);
+
+       flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs);
+       flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
+
+       cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl,
+                       sizeof(flow_ctl));
+}
+
 static void cp210x_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct cp210x_serial_private *priv = usb_get_serial_data(port->serial);
-       struct device *dev = &port->dev;
        u16 bits;
        int ret;
 
@@ -1156,42 +1188,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
        if (ret)
                dev_err(&port->dev, "failed to set line control: %d\n", ret);
 
-       if (!old_termios || C_CRTSCTS(tty) != (old_termios->c_cflag & CRTSCTS)) {
-               struct cp210x_flow_ctl flow_ctl;
-               u32 ctl_hs;
-               u32 flow_repl;
-
-               cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
-                               sizeof(flow_ctl));
-               ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
-               flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
-
-               ctl_hs &= ~CP210X_SERIAL_DSR_HANDSHAKE;
-               ctl_hs &= ~CP210X_SERIAL_DCD_HANDSHAKE;
-               ctl_hs &= ~CP210X_SERIAL_DSR_SENSITIVITY;
-               ctl_hs &= ~CP210X_SERIAL_DTR_MASK;
-               ctl_hs |= CP210X_SERIAL_DTR_SHIFT(CP210X_SERIAL_DTR_ACTIVE);
-               if (C_CRTSCTS(tty)) {
-                       ctl_hs |= CP210X_SERIAL_CTS_HANDSHAKE;
-
-                       flow_repl &= ~CP210X_SERIAL_RTS_MASK;
-                       flow_repl |= CP210X_SERIAL_RTS_SHIFT(
-                                       CP210X_SERIAL_RTS_FLOW_CTL);
-               } else {
-                       ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE;
-
-                       flow_repl &= ~CP210X_SERIAL_RTS_MASK;
-                       flow_repl |= CP210X_SERIAL_RTS_SHIFT(
-                                       CP210X_SERIAL_RTS_ACTIVE);
-               }
-
-               dev_dbg(dev, "%s - ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n",
-                               __func__, ctl_hs, flow_repl);
-               flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs);
-               flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
-               cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl,
-                               sizeof(flow_ctl));
-       }
+       cp210x_set_flow_control(tty, port, old_termios);
 
        /*
         * Enable event-insertion mode only if input parity checking is