From: Yin-Ming Li 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 Signed-off-by: Sean Wang Signed-off-by: Yin-Ming Li --- 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