USB: serial: cp210x: fix CP2102N-A01 modem control

CP2102N revision A01 (firmware version <= 1.0.4) has a buggy
flow-control implementation that uses the ulXonLimit instead of
ulFlowReplace field of the flow-control settings structure (erratum
CP2102N_E104).

A recent change that set the input software flow-control limits
incidentally broke RTS control for these devices when CRTSCTS is not set
as the new limits would always enable hardware flow control.

Fix this by explicitly disabling flow control for the buggy firmware
versions and only updating the input software flow-control limits when
IXOFF is requested. This makes sure that the terminal settings matches
the default zero ulXonLimit (ulFlowReplace) for these devices.

Link: https://lore.kernel.org/r/20210609161509.9459-1-johan@kernel.org
Reported-by: David Frey <dpfrey@gmail.com>
Reported-by: Alex Villacís Lasso <a_villacis@palosanto.com>
Tested-by: Alex Villacís Lasso <a_villacis@palosanto.com>
Fixes: f61309d9c96a ("USB: serial: cp210x: set IXOFF thresholds")
Cc: stable@vger.kernel.org # 5.12
Signed-off-by: Johan Hovold <johan@kernel.org>

+59 -5
+59 -5
drivers/usb/serial/cp210x.c
··· 252 u8 gpio_input; 253 #endif 254 u8 partnum; 255 speed_t min_speed; 256 speed_t max_speed; 257 bool use_actual_rate; 258 }; 259 260 enum cp210x_event_state { ··· 400 401 /* CP210X_VENDOR_SPECIFIC values */ 402 #define CP210X_READ_2NCONFIG 0x000E 403 #define CP210X_READ_LATCH 0x00C2 404 #define CP210X_GET_PARTNUM 0x370B 405 #define CP210X_GET_PORTCONFIG 0x370C ··· 1131 static void cp210x_set_flow_control(struct tty_struct *tty, 1132 struct usb_serial_port *port, struct ktermios *old_termios) 1133 { 1134 struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); 1135 struct cp210x_special_chars chars; 1136 struct cp210x_flow_ctl flow_ctl; 1137 u32 flow_repl; 1138 u32 ctl_hs; 1139 int ret; 1140 1141 if (old_termios && 1142 C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS) && ··· 1204 port_priv->crtscts = false; 1205 } 1206 1207 - if (I_IXOFF(tty)) 1208 flow_repl |= CP210X_SERIAL_AUTO_RECEIVE; 1209 - else 1210 flow_repl &= ~CP210X_SERIAL_AUTO_RECEIVE; 1211 1212 if (I_IXON(tty)) 1213 flow_repl |= CP210X_SERIAL_AUTO_TRANSMIT; 1214 else 1215 flow_repl &= ~CP210X_SERIAL_AUTO_TRANSMIT; 1216 - 1217 - flow_ctl.ulXonLimit = cpu_to_le32(128); 1218 - flow_ctl.ulXoffLimit = cpu_to_le32(128); 1219 1220 dev_dbg(&port->dev, "%s - ctrl = 0x%02x, flow = 0x%02x\n", __func__, 1221 ctl_hs, flow_repl); ··· 1940 priv->use_actual_rate = use_actual_rate; 1941 } 1942 1943 static int cp210x_attach(struct usb_serial *serial) 1944 { 1945 int result; ··· 1999 2000 usb_set_serial_data(serial, priv); 2001 2002 cp210x_init_max_speed(serial); 2003 2004 result = cp210x_gpio_init(serial);
··· 252 u8 gpio_input; 253 #endif 254 u8 partnum; 255 + u32 fw_version; 256 speed_t min_speed; 257 speed_t max_speed; 258 bool use_actual_rate; 259 + bool no_flow_control; 260 }; 261 262 enum cp210x_event_state { ··· 398 399 /* CP210X_VENDOR_SPECIFIC values */ 400 #define CP210X_READ_2NCONFIG 0x000E 401 + #define CP210X_GET_FW_VER_2N 0x0010 402 #define CP210X_READ_LATCH 0x00C2 403 #define CP210X_GET_PARTNUM 0x370B 404 #define CP210X_GET_PORTCONFIG 0x370C ··· 1128 static void cp210x_set_flow_control(struct tty_struct *tty, 1129 struct usb_serial_port *port, struct ktermios *old_termios) 1130 { 1131 + struct cp210x_serial_private *priv = usb_get_serial_data(port->serial); 1132 struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); 1133 struct cp210x_special_chars chars; 1134 struct cp210x_flow_ctl flow_ctl; 1135 u32 flow_repl; 1136 u32 ctl_hs; 1137 int ret; 1138 + 1139 + /* 1140 + * Some CP2102N interpret ulXonLimit as ulFlowReplace (erratum 1141 + * CP2102N_E104). Report back that flow control is not supported. 1142 + */ 1143 + if (priv->no_flow_control) { 1144 + tty->termios.c_cflag &= ~CRTSCTS; 1145 + tty->termios.c_iflag &= ~(IXON | IXOFF); 1146 + } 1147 1148 if (old_termios && 1149 C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS) && ··· 1191 port_priv->crtscts = false; 1192 } 1193 1194 + if (I_IXOFF(tty)) { 1195 flow_repl |= CP210X_SERIAL_AUTO_RECEIVE; 1196 + 1197 + flow_ctl.ulXonLimit = cpu_to_le32(128); 1198 + flow_ctl.ulXoffLimit = cpu_to_le32(128); 1199 + } else { 1200 flow_repl &= ~CP210X_SERIAL_AUTO_RECEIVE; 1201 + } 1202 1203 if (I_IXON(tty)) 1204 flow_repl |= CP210X_SERIAL_AUTO_TRANSMIT; 1205 else 1206 flow_repl &= ~CP210X_SERIAL_AUTO_TRANSMIT; 1207 1208 dev_dbg(&port->dev, "%s - ctrl = 0x%02x, flow = 0x%02x\n", __func__, 1209 ctl_hs, flow_repl); ··· 1926 priv->use_actual_rate = use_actual_rate; 1927 } 1928 1929 + static int cp210x_get_fw_version(struct usb_serial *serial, u16 value) 1930 + { 1931 + struct cp210x_serial_private *priv = usb_get_serial_data(serial); 1932 + u8 ver[3]; 1933 + int ret; 1934 + 1935 + ret = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, value, 1936 + ver, sizeof(ver)); 1937 + if (ret) 1938 + return ret; 1939 + 1940 + dev_dbg(&serial->interface->dev, "%s - %d.%d.%d\n", __func__, 1941 + ver[0], ver[1], ver[2]); 1942 + 1943 + priv->fw_version = ver[0] << 16 | ver[1] << 8 | ver[2]; 1944 + 1945 + return 0; 1946 + } 1947 + 1948 + static void cp210x_determine_quirks(struct usb_serial *serial) 1949 + { 1950 + struct cp210x_serial_private *priv = usb_get_serial_data(serial); 1951 + int ret; 1952 + 1953 + switch (priv->partnum) { 1954 + case CP210X_PARTNUM_CP2102N_QFN28: 1955 + case CP210X_PARTNUM_CP2102N_QFN24: 1956 + case CP210X_PARTNUM_CP2102N_QFN20: 1957 + ret = cp210x_get_fw_version(serial, CP210X_GET_FW_VER_2N); 1958 + if (ret) 1959 + break; 1960 + if (priv->fw_version <= 0x10004) 1961 + priv->no_flow_control = true; 1962 + break; 1963 + default: 1964 + break; 1965 + } 1966 + } 1967 + 1968 static int cp210x_attach(struct usb_serial *serial) 1969 { 1970 int result; ··· 1946 1947 usb_set_serial_data(serial, priv); 1948 1949 + cp210x_determine_quirks(serial); 1950 cp210x_init_max_speed(serial); 1951 1952 result = cp210x_gpio_init(serial);