From: Yin-Ming Li <redacted>
Driver queue wakeups schedule wake_txqs_tasklet asynchronously. Stopping
the driver work that issued a wakeup does not wait for this tasklet, and
ieee80211_unregister_hw() does not drain it.
Drain the tasklet in ieee80211_free_hw(), before destroying the local
mutex and releasing the hardware allocation. Drivers must stop their
asynchronous producers before calling ieee80211_free_hw(); this drain
waits for a tasklet those producers have already scheduled. Using the
final free boundary also covers deferred wakeups scheduled while the
driver finishes bus teardown after ieee80211_unregister_hw() returns.
Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Yin-Ming Li <redacted>
---
net/mac80211/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f996e15e3d9e35cacddedf482a34c40c587d3e52..086b9ca3485398b4ef2ff60c3f9387dd909a8008 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1755,6 +1755,9 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
struct ieee80211_local *local = hw_to_local(hw);
enum nl80211_band band;
+ /* Driver callbacks have stopped; drain their deferred TXQ wakeups. */
+ tasklet_kill(&local->wake_txqs_tasklet);
+
mutex_destroy(&local->iflist_mtx);
idr_for_each(&local->ack_status_frames,
--
2.43.0