summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoeren Moch <smoch@web.de>2019-07-01 13:53:13 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-26 10:13:03 +0300
commitbbe756698af485b9bfd84c29e65637bfe4960892 (patch)
tree5f3ab782cf84fb0e216decb49d11ef0633c905aa
parent7f235a535b1752e3472a1c2a5bf055210ab0a4fe (diff)
downloadlinux-bbe756698af485b9bfd84c29e65637bfe4960892.tar.xz
rt2x00usb: fix rx queue hang
commit 41a531ffa4c5aeb062f892227c00fabb3b4a9c91 upstream. Since commit ed194d136769 ("usb: core: remove local_irq_save() around ->complete() handler") the handler rt2x00usb_interrupt_rxdone() is not running with interrupts disabled anymore. So this completion handler is not guaranteed to run completely before workqueue processing starts for the same queue entry. Be sure to set all other flags in the entry correctly before marking this entry ready for workqueue processing. This way we cannot miss error conditions that need to be signalled from the completion handler to the worker thread. Note that rt2x00usb_work_rxdone() processes all available entries, not only such for which queue_work() was called. This patch is similar to what commit df71c9cfceea ("rt2x00: fix order of entry flags modification") did for TX processing. This fixes a regression on a RT5370 based wifi stick in AP mode, which suddenly stopped data transmission after some period of heavy load. Also stopping the hanging hostapd resulted in the error message "ieee80211 phy0: rt2x00queue_flush_queue: Warning - Queue 14 failed to flush". Other operation modes are probably affected as well, this just was the used testcase. Fixes: ed194d136769 ("usb: core: remove local_irq_save() around ->complete() handler") Cc: stable@vger.kernel.org # 4.20+ Signed-off-by: Soeren Moch <smoch@web.de> Acked-by: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00usb.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index 086aad22743d..139bcdb42536 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -367,15 +367,10 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
/*
- * Report the frame as DMA done
- */
- rt2x00lib_dmadone(entry);
-
- /*
* Check if the received data is simply too small
* to be actually valid, or if the urb is signaling
* a problem.
@@ -384,6 +379,11 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
/*
+ * Report the frame as DMA done
+ */
+ rt2x00lib_dmadone(entry);
+
+ /*
* Schedule the delayed work for reading the RX status
* from the device.
*/