mac80211: sync some rt2x00 patches with wireless-next
[openwrt/staging/wigyori.git] / package / kernel / mac80211 / patches / rt2x00 / 003-v6.7-wifi-rt2x00-fix-rt2800-watchdog-function.patch
diff --git a/package/kernel/mac80211/patches/rt2x00/003-v6.7-wifi-rt2x00-fix-rt2800-watchdog-function.patch b/package/kernel/mac80211/patches/rt2x00/003-v6.7-wifi-rt2x00-fix-rt2800-watchdog-function.patch
new file mode 100644 (file)
index 0000000..f253dac
--- /dev/null
@@ -0,0 +1,78 @@
+From 69708fbb2c698f262e03360d064c7066e0679953 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 14 Oct 2023 14:55:01 +0800
+Subject: 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
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+--- 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 rt2x0
+ }
+ 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 *
+               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 *
+                        */
+                       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 *
+       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);