* patch "USB: serial: ch341: fix lockup of devices with limited prescaler" added to usb-testing
@ 2020-05-29 7:41 gregkh
0 siblings, 0 replies; only message in thread
From: gregkh @ 2020-05-29 7:41 UTC (permalink / raw)
To: johan, public, stable
This is a note to let you know that I've just added the patch titled
USB: serial: ch341: fix lockup of devices with limited prescaler
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-testing branch.
The patch will show up in the next release of the linux-next tree
(usually sometime within the next 24 hours during the week.)
The patch will be merged to the usb-next branch sometime soon,
after it passes testing, and the merge window is open.
If you have any questions about this process, please let me know.
From c432df155919582a3cefa35a8f86256c830fa9a4 Mon Sep 17 00:00:00 2001
From: Johan Hovold <johan@kernel.org>
Date: Thu, 14 May 2020 11:36:45 +0200
Subject: USB: serial: ch341: fix lockup of devices with limited prescaler
Michael Hanselmann reports that
[a] subset of all CH341 devices stop responding to bulk
transfers, usually after the third byte, when the highest
prescaler bit (0b100) is set. There is one exception, namely a
prescaler of exactly 0b111 (fact=1, ps=3).
Fix this by forcing a lower base clock (fact = 0) whenever needed.
This specifically makes the standard rates 110, 134 and 200 bps work
again with these devices.
Fixes: 35714565089e ("USB: serial: ch341: reimplement line-speed handling")
Cc: stable <stable@vger.kernel.org> # 5.5
Reported-by: Michael Hanselmann <public@hansmi.ch>
Link: https://lore.kernel.org/r/20200514141743.GE25962@localhost
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/ch341.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index f2b93f4554a7..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) },
@@ -160,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;
/*
@@ -188,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;
@@ -228,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;
@@ -333,6 +341,7 @@ static int ch341_detect_quirks(struct usb_serial_port *port)
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;
}
--
2.26.2
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2020-05-29 7:41 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-29 7:41 patch "USB: serial: ch341: fix lockup of devices with limited prescaler" added to usb-testing gregkh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).