-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Backport fixes for CDC ACM error recovery path.
- Loading branch information
Showing
3 changed files
with
173 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...rnal/board/raspberrypi/patches/linux/0002-CDC-ACM-heed-quirk-also-in-error-handling.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
From 1eaf50e14dfdda654e6acb2a1ee4c18cff346064 Mon Sep 17 00:00:00 2001 | ||
Message-Id: <1eaf50e14dfdda654e6acb2a1ee4c18cff346064.1604607313.git.stefan@agner.ch> | ||
In-Reply-To: <d6fc5f89ac905cb3efc9c61ce79dbfad5d91883b.1604607313.git.stefan@agner.ch> | ||
References: <d6fc5f89ac905cb3efc9c61ce79dbfad5d91883b.1604607313.git.stefan@agner.ch> | ||
From: Oliver Neukum <oneukum@suse.com> | ||
Date: Tue, 26 May 2020 14:44:20 +0200 | ||
Subject: [PATCH 2/3] CDC-ACM: heed quirk also in error handling | ||
|
||
commit 97fe809934dd2b0b37dfef3a2fc70417f485d7af upstream. | ||
|
||
If buffers are iterated over in the error case, the lower limits | ||
for quirky devices must be heeded. | ||
|
||
Signed-off-by: Oliver Neukum <oneukum@suse.com> | ||
Reported-by: Jean Rene Dawin <jdawin@math.uni-bielefeld.de> | ||
Fixes: a4e7279cd1d19 ("cdc-acm: introduce a cool down") | ||
Cc: stable <stable@vger.kernel.org> | ||
Link: https://lore.kernel.org/r/20200526124420.22160-1-oneukum@suse.com | ||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
--- | ||
drivers/usb/class/cdc-acm.c | 2 +- | ||
1 file changed, 1 insertion(+), 1 deletion(-) | ||
|
||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c | ||
index 10ba1b4f0dbf..e8b9b27937ed 100644 | ||
--- a/drivers/usb/class/cdc-acm.c | ||
+++ b/drivers/usb/class/cdc-acm.c | ||
@@ -590,7 +590,7 @@ static void acm_softint(struct work_struct *work) | ||
} | ||
|
||
if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) { | ||
- for (i = 0; i < ACM_NR; i++) | ||
+ for (i = 0; i < acm->rx_buflimit; i++) | ||
if (test_and_clear_bit(i, &acm->urbs_in_error_delay)) | ||
acm_submit_read_urb(acm, i, GFP_NOIO); | ||
} | ||
-- | ||
2.29.1 | ||
|
130 changes: 130 additions & 0 deletions
130
...ot-external/board/raspberrypi/patches/linux/0003-usb-cdc-acm-fix-cooldown-mechanism.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
From 930c59eeae2bdd02fa1327a69e4df70105f672e4 Mon Sep 17 00:00:00 2001 | ||
Message-Id: <930c59eeae2bdd02fa1327a69e4df70105f672e4.1604607313.git.stefan@agner.ch> | ||
In-Reply-To: <d6fc5f89ac905cb3efc9c61ce79dbfad5d91883b.1604607313.git.stefan@agner.ch> | ||
References: <d6fc5f89ac905cb3efc9c61ce79dbfad5d91883b.1604607313.git.stefan@agner.ch> | ||
From: Jerome Brunet <jbrunet@baylibre.com> | ||
Date: Mon, 19 Oct 2020 19:07:02 +0200 | ||
Subject: [PATCH 3/3] usb: cdc-acm: fix cooldown mechanism | ||
|
||
Commit a4e7279cd1d1 ("cdc-acm: introduce a cool down") is causing | ||
regression if there is some USB error, such as -EPROTO. | ||
|
||
This has been reported on some samples of the Odroid-N2 using the Combee II | ||
Zibgee USB dongle. | ||
|
||
> struct acm *acm = container_of(work, struct acm, work) | ||
|
||
is incorrect in case of a delayed work and causes warnings, usually from | ||
the workqueue: | ||
|
||
> WARNING: CPU: 0 PID: 0 at kernel/workqueue.c:1474 __queue_work+0x480/0x528. | ||
|
||
When this happens, USB eventually stops working completely after a while. | ||
Also the ACM_ERROR_DELAY bit is never set, so the cooldown mechanism | ||
previously introduced cannot be triggered and acm_submit_read_urb() is | ||
never called. | ||
|
||
This changes makes the cdc-acm driver use a single delayed work, fixing the | ||
pointer arithmetic in acm_softint() and set the ACM_ERROR_DELAY when the | ||
cooldown mechanism appear to be needed. | ||
|
||
Fixes: a4e7279cd1d1 ("cdc-acm: introduce a cool down") | ||
Cc: Oliver Neukum <oneukum@suse.com> | ||
Reported-by: Pascal Vizeli <pascal.vizeli@nabucasa.com> | ||
Acked-by: Oliver Neukum <oneukum@suse.com> | ||
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> | ||
Link: https://lore.kernel.org/r/20201019170702.150534-1-jbrunet@baylibre.com | ||
Cc: stable <stable@vger.kernel.org> | ||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
--- | ||
drivers/usb/class/cdc-acm.c | 12 +++++------- | ||
drivers/usb/class/cdc-acm.h | 3 +-- | ||
2 files changed, 6 insertions(+), 9 deletions(-) | ||
|
||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c | ||
index e8b9b27937ed..4b543aa0030d 100644 | ||
--- a/drivers/usb/class/cdc-acm.c | ||
+++ b/drivers/usb/class/cdc-acm.c | ||
@@ -510,6 +510,7 @@ static void acm_read_bulk_callback(struct urb *urb) | ||
"%s - cooling babbling device\n", __func__); | ||
usb_mark_last_busy(acm->dev); | ||
set_bit(rb->index, &acm->urbs_in_error_delay); | ||
+ set_bit(ACM_ERROR_DELAY, &acm->flags); | ||
cooldown = true; | ||
break; | ||
default: | ||
@@ -535,7 +536,7 @@ static void acm_read_bulk_callback(struct urb *urb) | ||
|
||
if (stopped || stalled || cooldown) { | ||
if (stalled) | ||
- schedule_work(&acm->work); | ||
+ schedule_delayed_work(&acm->dwork, 0); | ||
else if (cooldown) | ||
schedule_delayed_work(&acm->dwork, HZ / 2); | ||
return; | ||
@@ -570,13 +571,13 @@ static void acm_write_bulk(struct urb *urb) | ||
acm_write_done(acm, wb); | ||
spin_unlock_irqrestore(&acm->write_lock, flags); | ||
set_bit(EVENT_TTY_WAKEUP, &acm->flags); | ||
- schedule_work(&acm->work); | ||
+ schedule_delayed_work(&acm->dwork, 0); | ||
} | ||
|
||
static void acm_softint(struct work_struct *work) | ||
{ | ||
int i; | ||
- struct acm *acm = container_of(work, struct acm, work); | ||
+ struct acm *acm = container_of(work, struct acm, dwork.work); | ||
|
||
if (test_bit(EVENT_RX_STALL, &acm->flags)) { | ||
smp_mb(); /* against acm_suspend() */ | ||
@@ -592,7 +593,7 @@ static void acm_softint(struct work_struct *work) | ||
if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) { | ||
for (i = 0; i < acm->rx_buflimit; i++) | ||
if (test_and_clear_bit(i, &acm->urbs_in_error_delay)) | ||
- acm_submit_read_urb(acm, i, GFP_NOIO); | ||
+ acm_submit_read_urb(acm, i, GFP_KERNEL); | ||
} | ||
|
||
if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags)) | ||
@@ -1386,7 +1387,6 @@ static int acm_probe(struct usb_interface *intf, | ||
acm->ctrlsize = ctrlsize; | ||
acm->readsize = readsize; | ||
acm->rx_buflimit = num_rx_buf; | ||
- INIT_WORK(&acm->work, acm_softint); | ||
INIT_DELAYED_WORK(&acm->dwork, acm_softint); | ||
init_waitqueue_head(&acm->wioctl); | ||
spin_lock_init(&acm->write_lock); | ||
@@ -1596,7 +1596,6 @@ static void acm_disconnect(struct usb_interface *intf) | ||
} | ||
|
||
acm_kill_urbs(acm); | ||
- cancel_work_sync(&acm->work); | ||
cancel_delayed_work_sync(&acm->dwork); | ||
|
||
tty_unregister_device(acm_tty_driver, acm->minor); | ||
@@ -1639,7 +1638,6 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | ||
return 0; | ||
|
||
acm_kill_urbs(acm); | ||
- cancel_work_sync(&acm->work); | ||
cancel_delayed_work_sync(&acm->dwork); | ||
acm->urbs_in_error_delay = 0; | ||
|
||
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h | ||
index 30380d28a504..d8f8651425c4 100644 | ||
--- a/drivers/usb/class/cdc-acm.h | ||
+++ b/drivers/usb/class/cdc-acm.h | ||
@@ -111,8 +111,7 @@ struct acm { | ||
# define ACM_ERROR_DELAY 3 | ||
unsigned long urbs_in_error_delay; /* these need to be restarted after a delay */ | ||
struct usb_cdc_line_coding line; /* bits, stop, parity */ | ||
- struct work_struct work; /* work queue entry for various purposes*/ | ||
- struct delayed_work dwork; /* for cool downs needed in error recovery */ | ||
+ struct delayed_work dwork; /* work queue entry for various purposes */ | ||
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ | ||
unsigned int ctrlout; /* output control lines (DTR, RTS) */ | ||
struct async_icount iocount; /* counters for control line changes */ | ||
-- | ||
2.29.1 | ||
|