| From 93e1c8a638308980309e009cc40b5a57ef87caf1 Mon Sep 17 00:00:00 2001 |
| From: Romain Izard <romain.izard.pro@gmail.com> |
| Date: Fri, 22 Mar 2019 16:53:02 +0100 |
| Subject: usb: cdc-acm: fix race during wakeup blocking TX traffic |
| |
| From: Romain Izard <romain.izard.pro@gmail.com> |
| |
| commit 93e1c8a638308980309e009cc40b5a57ef87caf1 upstream. |
| |
| When the kernel is compiled with preemption enabled, the URB completion |
| handler can run in parallel with the work responsible for waking up the |
| tty layer. If the URB handler sets the EVENT_TTY_WAKEUP bit during the |
| call to tty_port_tty_wakeup() to signal that there is room for additional |
| input, it will be cleared at the end of this call. As a result, TX traffic |
| on the upper layer will be blocked. |
| |
| This can be seen with a kernel configured with CONFIG_PREEMPT, and a fast |
| modem connected with PPP running over a USB CDC-ACM port. |
| |
| Use test_and_clear_bit() instead, which ensures that each wakeup requested |
| by the URB completion code will trigger a call to tty_port_tty_wakeup(). |
| |
| Fixes: 1aba579f3cf5 cdc-acm: handle read pipe errors |
| Signed-off-by: Romain Izard <romain.izard.pro@gmail.com> |
| Cc: stable <stable@vger.kernel.org> |
| Acked-by: Oliver Neukum <oneukum@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/class/cdc-acm.c | 4 +--- |
| 1 file changed, 1 insertion(+), 3 deletions(-) |
| |
| --- a/drivers/usb/class/cdc-acm.c |
| +++ b/drivers/usb/class/cdc-acm.c |
| @@ -570,10 +570,8 @@ static void acm_softint(struct work_stru |
| clear_bit(EVENT_RX_STALL, &acm->flags); |
| } |
| |
| - if (test_bit(EVENT_TTY_WAKEUP, &acm->flags)) { |
| + if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags)) |
| tty_port_tty_wakeup(&acm->port); |
| - clear_bit(EVENT_TTY_WAKEUP, &acm->flags); |
| - } |
| } |
| |
| /* |