aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 12:17:38 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 12:17:38 -0500
commit97f9c5f211d1f063b1745370e6b4fd64d6adaeff (patch)
tree995e93101e168941b6470fb305cb150171b2b812
parentd6169d04097fd9ddf811e63eae4e5cd71e6666e2 (diff)
parent2d5a9c72d0c4ac73cf97f4b7814ed6c44b1e49ae (diff)
Merge tag 'usb-serial-4.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus
Johan writes: USB-serial fixes for v4.10-rc4 These fixes address a number of issues in the ch341 driver and includes a partial revert of a change in how we set the line settings that went into 4.10-rc1 but which turned out to have undesired side effects. This included deasserting the modem-control lines when configuring the device, but also prevented a certain class of CH340 devices from working with the driver. Included are also two fixes for two minor information leaks in kl5kusb105 and ch341 due to failures to detect short control transfers. Signed-off-by: Johan Hovold <johan@kernel.org>
-rw-r--r--drivers/usb/serial/ch341.c108
-rw-r--r--drivers/usb/serial/kl5kusb105.c9
2 files changed, 78 insertions, 39 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 2597b83a8ae2..95aa5233726c 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -95,6 +95,7 @@ struct ch341_private {
95 unsigned baud_rate; /* set baud rate */ 95 unsigned baud_rate; /* set baud rate */
96 u8 line_control; /* set line control value RTS/DTR */ 96 u8 line_control; /* set line control value RTS/DTR */
97 u8 line_status; /* active status of modem control inputs */ 97 u8 line_status; /* active status of modem control inputs */
98 u8 lcr;
98}; 99};
99 100
100static void ch341_set_termios(struct tty_struct *tty, 101static void ch341_set_termios(struct tty_struct *tty,
@@ -112,6 +113,8 @@ static int ch341_control_out(struct usb_device *dev, u8 request,
112 r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, 113 r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
113 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 114 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
114 value, index, NULL, 0, DEFAULT_TIMEOUT); 115 value, index, NULL, 0, DEFAULT_TIMEOUT);
116 if (r < 0)
117 dev_err(&dev->dev, "failed to send control message: %d\n", r);
115 118
116 return r; 119 return r;
117} 120}
@@ -129,11 +132,24 @@ static int ch341_control_in(struct usb_device *dev,
129 r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, 132 r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
130 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 133 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
131 value, index, buf, bufsize, DEFAULT_TIMEOUT); 134 value, index, buf, bufsize, DEFAULT_TIMEOUT);
132 return r; 135 if (r < bufsize) {
136 if (r >= 0) {
137 dev_err(&dev->dev,
138 "short control message received (%d < %u)\n",
139 r, bufsize);
140 r = -EIO;
141 }
142
143 dev_err(&dev->dev, "failed to receive control message: %d\n",
144 r);
145 return r;
146 }
147
148 return 0;
133} 149}
134 150
135static int ch341_init_set_baudrate(struct usb_device *dev, 151static int ch341_set_baudrate_lcr(struct usb_device *dev,
136 struct ch341_private *priv, unsigned ctrl) 152 struct ch341_private *priv, u8 lcr)
137{ 153{
138 short a; 154 short a;
139 int r; 155 int r;
@@ -156,9 +172,19 @@ static int ch341_init_set_baudrate(struct usb_device *dev,
156 factor = 0x10000 - factor; 172 factor = 0x10000 - factor;
157 a = (factor & 0xff00) | divisor; 173 a = (factor & 0xff00) | divisor;
158 174
159 /* 0x9c is "enable SFR_UART Control register and timer" */ 175 /*
160 r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 176 * CH341A buffers data until a full endpoint-size packet (32 bytes)
161 0x9c | (ctrl << 8), a | 0x80); 177 * has been received unless bit 7 is set.
178 */
179 a |= BIT(7);
180
181 r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, a);
182 if (r)
183 return r;
184
185 r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, lcr);
186 if (r)
187 return r;
162 188
163 return r; 189 return r;
164} 190}
@@ -170,9 +196,9 @@ static int ch341_set_handshake(struct usb_device *dev, u8 control)
170 196
171static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) 197static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
172{ 198{
199 const unsigned int size = 2;
173 char *buffer; 200 char *buffer;
174 int r; 201 int r;
175 const unsigned size = 8;
176 unsigned long flags; 202 unsigned long flags;
177 203
178 buffer = kmalloc(size, GFP_KERNEL); 204 buffer = kmalloc(size, GFP_KERNEL);
@@ -183,14 +209,9 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
183 if (r < 0) 209 if (r < 0)
184 goto out; 210 goto out;
185 211
186 /* setup the private status if available */ 212 spin_lock_irqsave(&priv->lock, flags);
187 if (r == 2) { 213 priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
188 r = 0; 214 spin_unlock_irqrestore(&priv->lock, flags);
189 spin_lock_irqsave(&priv->lock, flags);
190 priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
191 spin_unlock_irqrestore(&priv->lock, flags);
192 } else
193 r = -EPROTO;
194 215
195out: kfree(buffer); 216out: kfree(buffer);
196 return r; 217 return r;
@@ -200,9 +221,9 @@ out: kfree(buffer);
200 221
201static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) 222static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
202{ 223{
224 const unsigned int size = 2;
203 char *buffer; 225 char *buffer;
204 int r; 226 int r;
205 const unsigned size = 8;
206 227
207 buffer = kmalloc(size, GFP_KERNEL); 228 buffer = kmalloc(size, GFP_KERNEL);
208 if (!buffer) 229 if (!buffer)
@@ -232,7 +253,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
232 if (r < 0) 253 if (r < 0)
233 goto out; 254 goto out;
234 255
235 r = ch341_init_set_baudrate(dev, priv, 0); 256 r = ch341_set_baudrate_lcr(dev, priv, priv->lcr);
236 if (r < 0) 257 if (r < 0)
237 goto out; 258 goto out;
238 259
@@ -258,7 +279,6 @@ static int ch341_port_probe(struct usb_serial_port *port)
258 279
259 spin_lock_init(&priv->lock); 280 spin_lock_init(&priv->lock);
260 priv->baud_rate = DEFAULT_BAUD_RATE; 281 priv->baud_rate = DEFAULT_BAUD_RATE;
261 priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
262 282
263 r = ch341_configure(port->serial->dev, priv); 283 r = ch341_configure(port->serial->dev, priv);
264 if (r < 0) 284 if (r < 0)
@@ -320,7 +340,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
320 340
321 r = ch341_configure(serial->dev, priv); 341 r = ch341_configure(serial->dev, priv);
322 if (r) 342 if (r)
323 goto out; 343 return r;
324 344
325 if (tty) 345 if (tty)
326 ch341_set_termios(tty, port, NULL); 346 ch341_set_termios(tty, port, NULL);
@@ -330,12 +350,19 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
330 if (r) { 350 if (r) {
331 dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n", 351 dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n",
332 __func__, r); 352 __func__, r);
333 goto out; 353 return r;
334 } 354 }
335 355
336 r = usb_serial_generic_open(tty, port); 356 r = usb_serial_generic_open(tty, port);
357 if (r)
358 goto err_kill_interrupt_urb;
359
360 return 0;
361
362err_kill_interrupt_urb:
363 usb_kill_urb(port->interrupt_in_urb);
337 364
338out: return r; 365 return r;
339} 366}
340 367
341/* Old_termios contains the original termios settings and 368/* Old_termios contains the original termios settings and
@@ -356,7 +383,6 @@ static void ch341_set_termios(struct tty_struct *tty,
356 383
357 baud_rate = tty_get_baud_rate(tty); 384 baud_rate = tty_get_baud_rate(tty);
358 385
359 priv->baud_rate = baud_rate;
360 ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX; 386 ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
361 387
362 switch (C_CSIZE(tty)) { 388 switch (C_CSIZE(tty)) {
@@ -386,22 +412,25 @@ static void ch341_set_termios(struct tty_struct *tty,
386 ctrl |= CH341_LCR_STOP_BITS_2; 412 ctrl |= CH341_LCR_STOP_BITS_2;
387 413
388 if (baud_rate) { 414 if (baud_rate) {
389 spin_lock_irqsave(&priv->lock, flags); 415 priv->baud_rate = baud_rate;
390 priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); 416
391 spin_unlock_irqrestore(&priv->lock, flags); 417 r = ch341_set_baudrate_lcr(port->serial->dev, priv, ctrl);
392 r = ch341_init_set_baudrate(port->serial->dev, priv, ctrl);
393 if (r < 0 && old_termios) { 418 if (r < 0 && old_termios) {
394 priv->baud_rate = tty_termios_baud_rate(old_termios); 419 priv->baud_rate = tty_termios_baud_rate(old_termios);
395 tty_termios_copy_hw(&tty->termios, old_termios); 420 tty_termios_copy_hw(&tty->termios, old_termios);
421 } else if (r == 0) {
422 priv->lcr = ctrl;
396 } 423 }
397 } else {
398 spin_lock_irqsave(&priv->lock, flags);
399 priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
400 spin_unlock_irqrestore(&priv->lock, flags);
401 } 424 }
402 425
403 ch341_set_handshake(port->serial->dev, priv->line_control); 426 spin_lock_irqsave(&priv->lock, flags);
427 if (C_BAUD(tty) == B0)
428 priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
429 else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
430 priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
431 spin_unlock_irqrestore(&priv->lock, flags);
404 432
433 ch341_set_handshake(port->serial->dev, priv->line_control);
405} 434}
406 435
407static void ch341_break_ctl(struct tty_struct *tty, int break_state) 436static void ch341_break_ctl(struct tty_struct *tty, int break_state)
@@ -576,14 +605,23 @@ static int ch341_tiocmget(struct tty_struct *tty)
576 605
577static int ch341_reset_resume(struct usb_serial *serial) 606static int ch341_reset_resume(struct usb_serial *serial)
578{ 607{
579 struct ch341_private *priv; 608 struct usb_serial_port *port = serial->port[0];
580 609 struct ch341_private *priv = usb_get_serial_port_data(port);
581 priv = usb_get_serial_port_data(serial->port[0]); 610 int ret;
582 611
583 /* reconfigure ch341 serial port after bus-reset */ 612 /* reconfigure ch341 serial port after bus-reset */
584 ch341_configure(serial->dev, priv); 613 ch341_configure(serial->dev, priv);
585 614
586 return 0; 615 if (tty_port_initialized(&port->port)) {
616 ret = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
617 if (ret) {
618 dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
619 ret);
620 return ret;
621 }
622 }
623
624 return usb_serial_generic_resume(serial);
587} 625}
588 626
589static struct usb_serial_driver ch341_device = { 627static struct usb_serial_driver ch341_device = {
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 0ee190fc1bf8..6cb45757818f 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -192,10 +192,11 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
192 status_buf, KLSI_STATUSBUF_LEN, 192 status_buf, KLSI_STATUSBUF_LEN,
193 10000 193 10000
194 ); 194 );
195 if (rc < 0) 195 if (rc != KLSI_STATUSBUF_LEN) {
196 dev_err(&port->dev, "Reading line status failed (error = %d)\n", 196 dev_err(&port->dev, "reading line status failed: %d\n", rc);
197 rc); 197 if (rc >= 0)
198 else { 198 rc = -EIO;
199 } else {
199 status = get_unaligned_le16(status_buf); 200 status = get_unaligned_le16(status_buf);
200 201
201 dev_info(&port->serial->dev->dev, "read status %x %x\n", 202 dev_info(&port->serial->dev->dev, "read status %x %x\n",