mac80211: clean up remain-on-channel on interface stop
When any interface goes down, it could be the one that we were doing a remain-on-channel with. We therefore need to cancel the remain-on-channel and flush the related work structs so they don't run after the interface has been removed or even destroyed. It's also possible in this case that an off-channel SKB was never transmitted, so free it if this is the case. Note that this can also happen if the driver finishes the off-channel period without ever starting it. Cc: stable@kernel.org Reported-by: Nirav Shah <nirav.j2.shah@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
1ae2fc25a1
commit
71ecfa1893
|
@ -637,6 +637,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||
ieee80211_configure_filter(local);
|
||||
break;
|
||||
default:
|
||||
mutex_lock(&local->mtx);
|
||||
if (local->hw_roc_dev == sdata->dev &&
|
||||
local->hw_roc_channel) {
|
||||
/* ignore return value since this is racy */
|
||||
drv_cancel_remain_on_channel(local);
|
||||
ieee80211_queue_work(&local->hw, &local->hw_roc_done);
|
||||
}
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
flush_work(&local->hw_roc_start);
|
||||
flush_work(&local->hw_roc_done);
|
||||
|
||||
flush_work(&sdata->work);
|
||||
/*
|
||||
* When we get here, the interface is marked down.
|
||||
|
|
|
@ -234,6 +234,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
/* was never transmitted */
|
||||
if (local->hw_roc_skb) {
|
||||
u64 cookie;
|
||||
|
||||
cookie = local->hw_roc_cookie ^ 2;
|
||||
|
||||
cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie,
|
||||
local->hw_roc_skb->data,
|
||||
local->hw_roc_skb->len, false,
|
||||
GFP_KERNEL);
|
||||
|
||||
kfree_skb(local->hw_roc_skb);
|
||||
local->hw_roc_skb = NULL;
|
||||
local->hw_roc_skb_for_status = NULL;
|
||||
}
|
||||
|
||||
if (!local->hw_roc_for_tx)
|
||||
cfg80211_remain_on_channel_expired(local->hw_roc_dev,
|
||||
local->hw_roc_cookie,
|
||||
|
|
Loading…
Reference in New Issue