diff options
author | Greg Kroah-Hartman | 2020-05-29 09:40:58 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2020-05-29 09:40:58 +0200 |
commit | 4b9d03131de3196fab550029836b0e2ff4419bf3 (patch) | |
tree | 35336741c71b060b478e08c8ca07dbd23d0084d4 /drivers/usb/serial | |
parent | 97fe809934dd2b0b37dfef3a2fc70417f485d7af (diff) | |
parent | c432df155919582a3cefa35a8f86256c830fa9a4 (diff) |
Merge tag 'usb-serial-5.8-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next
Johan writes:
USB-serial updates for 5.8-rc1
Here are the USB-serial updates for 5.8-rc1, including:
- a SPDX comment-style clean up
- a fix usb_wwan modem drivers which could end up resubmitting the
their read URBs in a tight loop on disconnect
- a regression fix for a subset of quirky ch341 devices which would
lock up on certain low line speeds when using the new divisor
algorithm
All have been in linux-next with no reported issues.
* tag 'usb-serial-5.8-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial:
USB: serial: ch341: fix lockup of devices with limited prescaler
USB: serial: ch341: add basis for quirk detection
USB: serial: usb_wwan: do not resubmit rx urb on fatal errors
USB: serial: Use the correct style for SPDX License Identifier
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/belkin_sa.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/ch341.c | 68 | ||||
-rw-r--r-- | drivers/usb/serial/io_16654.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/io_edgeport.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/io_ionsp.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/io_ti.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/io_usbvend.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/mct_u232.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/oti6858.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/usb_wwan.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/visor.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/whiteheat.h | 2 |
14 files changed, 81 insertions, 15 deletions
diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h index a13a98d284f2..89ec30c63cc6 100644 --- a/drivers/usb/serial/belkin_sa.h +++ b/drivers/usb/serial/belkin_sa.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Definitions for Belkin USB Serial Adapter Driver * diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index c5ecdcd51ffc..89675ee29645 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -73,6 +73,8 @@ #define CH341_LCR_CS6 0x01 #define CH341_LCR_CS5 0x00 +#define CH341_QUIRK_LIMITED_PRESCALER BIT(0) + static const struct usb_device_id id_table[] = { { USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x1a86, 0x7523) }, @@ -87,6 +89,7 @@ struct ch341_private { u8 mcr; u8 msr; u8 lcr; + unsigned long quirks; }; static void ch341_set_termios(struct tty_struct *tty, @@ -159,9 +162,11 @@ static const speed_t ch341_min_rates[] = { * 2 <= div <= 256 if fact = 0, or * 9 <= div <= 256 if fact = 1 */ -static int ch341_get_divisor(speed_t speed) +static int ch341_get_divisor(struct ch341_private *priv) { unsigned int fact, div, clk_div; + speed_t speed = priv->baud_rate; + bool force_fact0 = false; int ps; /* @@ -187,8 +192,12 @@ static int ch341_get_divisor(speed_t speed) clk_div = CH341_CLK_DIV(ps, fact); div = CH341_CLKRATE / (clk_div * speed); + /* Some devices require a lower base clock if ps < 3. */ + if (ps < 3 && (priv->quirks & CH341_QUIRK_LIMITED_PRESCALER)) + force_fact0 = true; + /* Halve base clock (fact = 0) if required. */ - if (div < 9 || div > 255) { + if (div < 9 || div > 255 || force_fact0) { div /= 2; clk_div *= 2; fact = 0; @@ -227,7 +236,7 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev, if (!priv->baud_rate) return -EINVAL; - val = ch341_get_divisor(priv->baud_rate); + val = ch341_get_divisor(priv); if (val < 0) return -EINVAL; @@ -308,6 +317,54 @@ out: kfree(buffer); return r; } +static int ch341_detect_quirks(struct usb_serial_port *port) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + struct usb_device *udev = port->serial->dev; + const unsigned int size = 2; + unsigned long quirks = 0; + char *buffer; + int r; + + buffer = kmalloc(size, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + /* + * A subset of CH34x devices does not support all features. The + * prescaler is limited and there is no support for sending a RS232 + * break condition. A read failure when trying to set up the latter is + * used to detect these devices. + */ + r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), CH341_REQ_READ_REG, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + CH341_REG_BREAK, 0, buffer, size, DEFAULT_TIMEOUT); + if (r == -EPIPE) { + dev_dbg(&port->dev, "break control not supported\n"); + quirks = CH341_QUIRK_LIMITED_PRESCALER; + r = 0; + goto out; + } + + if (r != size) { + if (r >= 0) + r = -EIO; + dev_err(&port->dev, "failed to read break control: %d\n", r); + goto out; + } + + r = 0; +out: + kfree(buffer); + + if (quirks) { + dev_dbg(&port->dev, "enabling quirk flags: 0x%02lx\n", quirks); + priv->quirks |= quirks; + } + + return r; +} + static int ch341_port_probe(struct usb_serial_port *port) { struct ch341_private *priv; @@ -330,6 +387,11 @@ static int ch341_port_probe(struct usb_serial_port *port) goto error; usb_set_serial_port_data(port, priv); + + r = ch341_detect_quirks(port); + if (r < 0) + goto error; + return 0; error: kfree(priv); diff --git a/drivers/usb/serial/io_16654.h b/drivers/usb/serial/io_16654.h index 4980f72dc56f..f18501f056cf 100644 --- a/drivers/usb/serial/io_16654.h +++ b/drivers/usb/serial/io_16654.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /************************************************************************ * * 16654.H Definitions for 16C654 UART used on EdgePorts diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h index 2e7fedbaf2ff..43ba53a3a6fa 100644 --- a/drivers/usb/serial/io_edgeport.h +++ b/drivers/usb/serial/io_edgeport.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /************************************************************************ * * io_edgeport.h Edgeport Linux Interface definitions diff --git a/drivers/usb/serial/io_ionsp.h b/drivers/usb/serial/io_ionsp.h index 4b8e4823bd45..db4fce815c97 100644 --- a/drivers/usb/serial/io_ionsp.h +++ b/drivers/usb/serial/io_ionsp.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /************************************************************************ * * IONSP.H Definitions for I/O Networks Serial Protocol diff --git a/drivers/usb/serial/io_ti.h b/drivers/usb/serial/io_ti.h index 9bbcee37524e..50b899d55ed0 100644 --- a/drivers/usb/serial/io_ti.h +++ b/drivers/usb/serial/io_ti.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /***************************************************************************** * * Copyright (C) 1997-2002 Inside Out Networks, Inc. diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h index 0d1a5bb4636e..52cbc353051f 100644 --- a/drivers/usb/serial/io_usbvend.h +++ b/drivers/usb/serial/io_usbvend.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /************************************************************************ * * USBVEND.H Vendor-specific USB definitions diff --git a/drivers/usb/serial/iuu_phoenix.h b/drivers/usb/serial/iuu_phoenix.h index b400b262f72e..87992b24d904 100644 --- a/drivers/usb/serial/iuu_phoenix.h +++ b/drivers/usb/serial/iuu_phoenix.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Infinity Unlimited USB Phoenix driver * diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h index 0084edf518e8..e3d09a83cab1 100644 --- a/drivers/usb/serial/mct_u232.h +++ b/drivers/usb/serial/mct_u232.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Definitions for MCT (Magic Control Technology) USB-RS232 Converter Driver * diff --git a/drivers/usb/serial/oti6858.h b/drivers/usb/serial/oti6858.h index 1226bf2347eb..5c25836fdcd9 100644 --- a/drivers/usb/serial/oti6858.h +++ b/drivers/usb/serial/oti6858.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Ours Technology Inc. OTi-6858 USB to serial adapter driver. */ diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 52db5519aaf0..7d3090ee7e0c 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Prolific PL2303 USB to serial adaptor driver header file */ diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 13be21aad2f4..4b9845807bee 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -270,6 +270,10 @@ static void usb_wwan_indat_callback(struct urb *urb) if (status) { dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n", __func__, status, endpoint); + + /* don't resubmit on fatal errors */ + if (status == -ESHUTDOWN || status == -ENOENT) + return; } else { if (urb->actual_length) { tty_insert_flip_string(&port->port, data, diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h index 4bd69d047036..622d639ce74e 100644 --- a/drivers/usb/serial/visor.h +++ b/drivers/usb/serial/visor.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * USB HandSpring Visor driver * diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h index 269e727a92f9..7e63074c9128 100644 --- a/drivers/usb/serial/whiteheat.h +++ b/drivers/usb/serial/whiteheat.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * USB ConnectTech WhiteHEAT driver * |