diff options
Diffstat (limited to 'net/mac80211/offchannel.c')
| -rw-r--r-- | net/mac80211/offchannel.c | 28 | 
1 files changed, 22 insertions, 6 deletions
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index acd1f71adc0..7a17decd27f 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -333,7 +333,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)  		container_of(work, struct ieee80211_roc_work, work.work);  	struct ieee80211_sub_if_data *sdata = roc->sdata;  	struct ieee80211_local *local = sdata->local; -	bool started; +	bool started, on_channel;  	mutex_lock(&local->mtx); @@ -354,13 +354,26 @@ void ieee80211_sw_roc_work(struct work_struct *work)  	if (!roc->started) {  		struct ieee80211_roc_work *dep; -		/* start this ROC */ +		WARN_ON(local->use_chanctx); + +		/* If actually operating on the desired channel (with at least +		 * 20 MHz channel width) don't stop all the operations but still +		 * treat it as though the ROC operation started properly, so +		 * other ROC operations won't interfere with this one. +		 */ +		roc->on_channel = roc->chan == local->_oper_chandef.chan && +				  local->_oper_chandef.width != NL80211_CHAN_WIDTH_5 && +				  local->_oper_chandef.width != NL80211_CHAN_WIDTH_10; -		/* switch channel etc */ +		/* start this ROC */  		ieee80211_recalc_idle(local); -		local->tmp_channel = roc->chan; -		ieee80211_hw_config(local, 0); +		if (!roc->on_channel) { +			ieee80211_offchannel_stop_vifs(local); + +			local->tmp_channel = roc->chan; +			ieee80211_hw_config(local, 0); +		}  		/* tell userspace or send frame */  		ieee80211_handle_roc_started(roc); @@ -379,9 +392,10 @@ void ieee80211_sw_roc_work(struct work_struct *work)   finish:  		list_del(&roc->list);  		started = roc->started; +		on_channel = roc->on_channel;  		ieee80211_roc_notify_destroy(roc, !roc->abort); -		if (started) { +		if (started && !on_channel) {  			ieee80211_flush_queues(local, NULL);  			local->tmp_channel = NULL; @@ -394,6 +408,8 @@ void ieee80211_sw_roc_work(struct work_struct *work)  		if (started)  			ieee80211_start_next_roc(local); +		else if (list_empty(&local->roc_list)) +			ieee80211_run_deferred_scan(local);  	}   out_unlock:  | 
