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.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCXtC5GAAKCRALxc3C7H1l
 CA07AP4qlFdTgP0PwxewAKi0v+AGfr52gzpAgG58BsOwaJCB3gEAo18LMu3KEYDU
 w4gZZKtEQcFpKuBYY0Hu7Z4xMRMZBQY=
 =ctSR
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Greg Kroah-Hartman 2020-05-29 09:40:58 +02:00
commit 4b9d03131d
14 changed files with 81 additions and 15 deletions

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Definitions for Belkin USB Serial Adapter Driver * Definitions for Belkin USB Serial Adapter Driver
* *

View File

@ -73,6 +73,8 @@
#define CH341_LCR_CS6 0x01 #define CH341_LCR_CS6 0x01
#define CH341_LCR_CS5 0x00 #define CH341_LCR_CS5 0x00
#define CH341_QUIRK_LIMITED_PRESCALER BIT(0)
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x4348, 0x5523) },
{ USB_DEVICE(0x1a86, 0x7523) }, { USB_DEVICE(0x1a86, 0x7523) },
@ -87,6 +89,7 @@ struct ch341_private {
u8 mcr; u8 mcr;
u8 msr; u8 msr;
u8 lcr; u8 lcr;
unsigned long quirks;
}; };
static void ch341_set_termios(struct tty_struct *tty, 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 * 2 <= div <= 256 if fact = 0, or
* 9 <= div <= 256 if fact = 1 * 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; unsigned int fact, div, clk_div;
speed_t speed = priv->baud_rate;
bool force_fact0 = false;
int ps; int ps;
/* /*
@ -187,8 +192,12 @@ static int ch341_get_divisor(speed_t speed)
clk_div = CH341_CLK_DIV(ps, fact); clk_div = CH341_CLK_DIV(ps, fact);
div = CH341_CLKRATE / (clk_div * speed); 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. */ /* Halve base clock (fact = 0) if required. */
if (div < 9 || div > 255) { if (div < 9 || div > 255 || force_fact0) {
div /= 2; div /= 2;
clk_div *= 2; clk_div *= 2;
fact = 0; fact = 0;
@ -227,7 +236,7 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
if (!priv->baud_rate) if (!priv->baud_rate)
return -EINVAL; return -EINVAL;
val = ch341_get_divisor(priv->baud_rate); val = ch341_get_divisor(priv);
if (val < 0) if (val < 0)
return -EINVAL; return -EINVAL;
@ -308,6 +317,54 @@ out: kfree(buffer);
return r; 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) static int ch341_port_probe(struct usb_serial_port *port)
{ {
struct ch341_private *priv; struct ch341_private *priv;
@ -330,6 +387,11 @@ static int ch341_port_probe(struct usb_serial_port *port)
goto error; goto error;
usb_set_serial_port_data(port, priv); usb_set_serial_port_data(port, priv);
r = ch341_detect_quirks(port);
if (r < 0)
goto error;
return 0; return 0;
error: kfree(priv); error: kfree(priv);

View File

@ -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 * 16654.H Definitions for 16C654 UART used on EdgePorts

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/************************************************************************ /************************************************************************
* *
* io_edgeport.h Edgeport Linux Interface definitions * io_edgeport.h Edgeport Linux Interface definitions

View File

@ -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 * IONSP.H Definitions for I/O Networks Serial Protocol

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/***************************************************************************** /*****************************************************************************
* *
* Copyright (C) 1997-2002 Inside Out Networks, Inc. * Copyright (C) 1997-2002 Inside Out Networks, Inc.

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/************************************************************************ /************************************************************************
* *
* USBVEND.H Vendor-specific USB definitions * USBVEND.H Vendor-specific USB definitions

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Infinity Unlimited USB Phoenix driver * Infinity Unlimited USB Phoenix driver
* *

View File

@ -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 * Definitions for MCT (Magic Control Technology) USB-RS232 Converter Driver
* *

View File

@ -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. * Ours Technology Inc. OTi-6858 USB to serial adapter driver.
*/ */

View File

@ -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 * Prolific PL2303 USB to serial adaptor driver header file
*/ */

View File

@ -270,6 +270,10 @@ static void usb_wwan_indat_callback(struct urb *urb)
if (status) { if (status) {
dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n", dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n",
__func__, status, endpoint); __func__, status, endpoint);
/* don't resubmit on fatal errors */
if (status == -ESHUTDOWN || status == -ENOENT)
return;
} else { } else {
if (urb->actual_length) { if (urb->actual_length) {
tty_insert_flip_string(&port->port, data, tty_insert_flip_string(&port->port, data,

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* USB HandSpring Visor driver * USB HandSpring Visor driver
* *

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+ /* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* USB ConnectTech WhiteHEAT driver * USB ConnectTech WhiteHEAT driver
* *