summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ralink
diff options
context:
space:
mode:
authorShiji Yang <yangshiji66@outlook.com>2023-10-14 14:55:01 +0800
committerKalle Valo <kvalo@kernel.org>2023-10-23 20:25:43 +0300
commit69708fbb2c698f262e03360d064c7066e0679953 (patch)
tree3d91b3f9a8555f921c2c0623ab4b1f149d605750 /drivers/net/wireless/ralink
parent359342795d62548f3ba4831914fccf20a24446b5 (diff)
downloadlinux-stable-69708fbb2c698f262e03360d064c7066e0679953.tar.gz
linux-stable-69708fbb2c698f262e03360d064c7066e0679953.tar.bz2
linux-stable-69708fbb2c698f262e03360d064c7066e0679953.zip
wifi: rt2x00: fix rt2800 watchdog function
The watchdog function is broken on rt2800 series SoCs. This patch fixes the incorrect watchdog logic to make it work again. 1. Update current wdt queue index if it's not equal to the previous index. Watchdog compares the current and previous queue index to judge if the queue hung. 2. Make sure hung_{rx,tx} 'true' status won't be override by the normal queue. Any queue hangs should trigger a reset action. 3. Clear the watchdog counter of all queues before resetting the hardware. This change may help to avoid the reset loop. 4. Change hang check function return type to bool as we only need to return two status, yes or no. Signed-off-by: Shiji Yang <yangshiji66@outlook.com> Acked-by: Stanislaw Gruszka <stf_xl@wp.pl> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/TYAP286MB0315BC1D83D31154924F0D39BCD1A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
Diffstat (limited to 'drivers/net/wireless/ralink')
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 6d6ca0d7bdca..b93cfcb1e257 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1237,13 +1237,14 @@ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
-static int rt2800_check_hung(struct data_queue *queue)
+static bool rt2800_check_hung(struct data_queue *queue)
{
unsigned int cur_idx = rt2800_drv_get_dma_done(queue);
- if (queue->wd_idx != cur_idx)
+ if (queue->wd_idx != cur_idx) {
+ queue->wd_idx = cur_idx;
queue->wd_count = 0;
- else
+ } else
queue->wd_count++;
return queue->wd_count > 16;
@@ -1280,7 +1281,7 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
case QID_MGMT:
if (rt2x00queue_empty(queue))
continue;
- hung_tx = rt2800_check_hung(queue);
+ hung_tx = hung_tx || rt2800_check_hung(queue);
break;
case QID_RX:
/* For station mode we should reactive at least
@@ -1289,7 +1290,7 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
*/
if (rt2x00dev->intf_sta_count == 0)
continue;
- hung_rx = rt2800_check_hung(queue);
+ hung_rx = hung_rx || rt2800_check_hung(queue);
break;
default:
break;
@@ -1302,8 +1303,12 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
if (hung_rx)
rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
- if (hung_tx || hung_rx)
+ if (hung_tx || hung_rx) {
+ queue_for_each(rt2x00dev, queue)
+ queue->wd_count = 0;
+
ieee80211_restart_hw(rt2x00dev->hw);
+ }
}
EXPORT_SYMBOL_GPL(rt2800_watchdog);