mac80211_hwsim_stop() drops any frames left in data->pending. The loop currently checks skb_queue_empty() and then dequeues separately. That split is racy with TX status handling, which can remove a pending frame under the queue lock. If the last entry is removed after the empty check, skb_dequeue() returns NULL and the stop path passes that NULL skb to ieee80211_free_txskb(). Use skb_dequeue() as the loop condition instead. The dequeue result is the object that stop owns and frees, and a concurrent status completion that empties the queue simply makes the loop terminate. Fixes: bd18de517923 ("mac80211_hwsim: drop pending frames on stop") Assisted-by: Codex:gpt-5.5 Signed-off-by: Cen Zhang --- drivers/net/wireless/virtual/mac80211_hwsim_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c index 0dd8a6c85953..f92d90bc7107 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c @@ -2303,6 +2303,7 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw) static void mac80211_hwsim_stop(struct ieee80211_hw *hw, bool suspend) { struct mac80211_hwsim_data *data = hw->priv; + struct sk_buff *skb; int i; data->started = false; @@ -2310,8 +2311,8 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw, bool suspend) for (i = 0; i < ARRAY_SIZE(data->link_data); i++) hrtimer_cancel(&data->link_data[i].beacon_timer); - while (!skb_queue_empty(&data->pending)) - ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); + while ((skb = skb_dequeue(&data->pending))) + ieee80211_free_txskb(hw, skb); wiphy_dbg(hw->wiphy, "%s\n", __func__); } -- 2.43.0