mac80211: sync some rt2x00 patches with wireless-next
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / rt2x00 / 005-3-v6.8-wifi-rt2x00-restart-beacon-queue-when-hardware-reset.patch
diff --git a/package/kernel/mac80211/patches/rt2x00/005-3-v6.8-wifi-rt2x00-restart-beacon-queue-when-hardware-reset.patch b/package/kernel/mac80211/patches/rt2x00/005-3-v6.8-wifi-rt2x00-restart-beacon-queue-when-hardware-reset.patch
new file mode 100644 (file)
index 0000000..1fa7b8b
--- /dev/null
@@ -0,0 +1,67 @@
+From a11d965a218f0cd95b13fe44d0bcd8a20ce134a8 Mon Sep 17 00:00:00 2001
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Sat, 4 Nov 2023 16:58:00 +0800
+Subject: wifi: rt2x00: restart beacon queue when hardware reset
+
+When a hardware reset is triggered, all registers are reset, so all
+queues are forced to stop in hardware interface. However, mac80211
+will not automatically stop the queue. If we don't manually stop the
+beacon queue, the queue will be deadlocked and unable to start again.
+This patch fixes the issue where Apple devices cannot connect to the
+AP after calling ieee80211_restart_hw().
+
+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/TYAP286MB031530EB6D98DCE4DF20766CBCA4A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00dev.c |  3 +++
+ drivers/net/wireless/ralink/rt2x00/rt2x00mac.c | 11 +++++++++++
+ 2 files changed, 14 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -101,6 +101,7 @@ void rt2x00lib_disable_radio(struct rt2x
+       rt2x00link_stop_tuner(rt2x00dev);
+       rt2x00queue_stop_queues(rt2x00dev);
+       rt2x00queue_flush_queues(rt2x00dev, true);
++      rt2x00queue_stop_queue(rt2x00dev->bcn);
+       /*
+        * Disable radio.
+@@ -1286,6 +1287,7 @@ int rt2x00lib_start(struct rt2x00_dev *r
+       rt2x00dev->intf_ap_count = 0;
+       rt2x00dev->intf_sta_count = 0;
+       rt2x00dev->intf_associated = 0;
++      rt2x00dev->intf_beaconing = 0;
+       /* Enable the radio */
+       retval = rt2x00lib_enable_radio(rt2x00dev);
+@@ -1312,6 +1314,7 @@ void rt2x00lib_stop(struct rt2x00_dev *r
+       rt2x00dev->intf_ap_count = 0;
+       rt2x00dev->intf_sta_count = 0;
+       rt2x00dev->intf_associated = 0;
++      rt2x00dev->intf_beaconing = 0;
+ }
+ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+@@ -598,6 +598,17 @@ void rt2x00mac_bss_info_changed(struct i
+        */
+       if (changes & BSS_CHANGED_BEACON_ENABLED) {
+               mutex_lock(&intf->beacon_skb_mutex);
++
++              /*
++               * Clear the 'enable_beacon' flag and clear beacon because
++               * the beacon queue has been stopped after hardware reset.
++               */
++              if (test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags) &&
++                  intf->enable_beacon) {
++                      intf->enable_beacon = false;
++                      rt2x00queue_clear_beacon(rt2x00dev, vif);
++              }
++
+               if (!bss_conf->enable_beacon && intf->enable_beacon) {
+                       rt2x00dev->intf_beaconing--;
+                       intf->enable_beacon = false;