| From 01e01f5c89773c600a9f0b32c888de0146066c3a Mon Sep 17 00:00:00 2001 |
| From: Sergey Ryazanov <ryazanov.s.a@gmail.com> |
| Date: Sun, 1 May 2022 20:58:28 +0300 |
| Subject: usb: cdc-wdm: fix reading stuck on device close |
| |
| From: Sergey Ryazanov <ryazanov.s.a@gmail.com> |
| |
| commit 01e01f5c89773c600a9f0b32c888de0146066c3a upstream. |
| |
| cdc-wdm tracks whether a response reading request is in-progress and |
| blocks the next request from being sent until the previous request is |
| completed. As soon as last user closes the cdc-wdm device file, the |
| driver cancels any ongoing requests, resets the pending response |
| counter, but leaves the response reading in-progress flag |
| (WDM_RESPONDING) untouched. |
| |
| So if the user closes the device file during the response receive |
| request is being performed, no more data will be obtained from the |
| modem. The request will be cancelled, effectively preventing the |
| WDM_RESPONDING flag from being reseted. Keeping the flag set will |
| prevent a new response receive request from being sent, permanently |
| blocking the read path. The read path will staying blocked until the |
| module will be reloaded or till the modem will be re-attached. |
| |
| This stuck has been observed with a Huawei E3372 modem attached to an |
| OpenWrt router and using the comgt utility to set up a network |
| connection. |
| |
| Fix this issue by clearing the WDM_RESPONDING flag on the device file |
| close. |
| |
| Without this fix, the device reading stuck can be easily reproduced in a |
| few connection establishing attempts. With this fix, a load test for |
| modem connection re-establishing worked for several hours without any |
| issues. |
| |
| Fixes: 922a5eadd5a3 ("usb: cdc-wdm: Fix race between autosuspend and reading from the device") |
| Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com> |
| Cc: stable <stable@vger.kernel.org> |
| Acked-by: Oliver Neukum <oneukum@suse.com> |
| Link: https://lore.kernel.org/r/20220501175828.8185-1-ryazanov.s.a@gmail.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/usb/class/cdc-wdm.c | 1 + |
| 1 file changed, 1 insertion(+) |
| |
| --- a/drivers/usb/class/cdc-wdm.c |
| +++ b/drivers/usb/class/cdc-wdm.c |
| @@ -774,6 +774,7 @@ static int wdm_release(struct inode *ino |
| poison_urbs(desc); |
| spin_lock_irq(&desc->iuspin); |
| desc->resp_count = 0; |
| + clear_bit(WDM_RESPONDING, &desc->flags); |
| spin_unlock_irq(&desc->iuspin); |
| desc->manage_power(desc->intf, 0); |
| unpoison_urbs(desc); |