aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/offchannel.c19
-rw-r--r--net/mac80211/util.c5
3 files changed, 24 insertions, 3 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d529bd5eab47..9af50fbcd48b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -477,9 +477,12 @@ enum ieee80211_sub_if_data_flags {
477 * @SDATA_STATE_RUNNING: virtual interface is up & running; this 477 * @SDATA_STATE_RUNNING: virtual interface is up & running; this
478 * mirrors netif_running() but is separate for interface type 478 * mirrors netif_running() but is separate for interface type
479 * change handling while the interface is up 479 * change handling while the interface is up
480 * @SDATA_STATE_OFFCHANNEL: This interface is currently in offchannel
481 * mode, so queues are stopped
480 */ 482 */
481enum ieee80211_sdata_state_bits { 483enum ieee80211_sdata_state_bits {
482 SDATA_STATE_RUNNING, 484 SDATA_STATE_RUNNING,
485 SDATA_STATE_OFFCHANNEL,
483}; 486};
484 487
485struct ieee80211_sub_if_data { 488struct ieee80211_sub_if_data {
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index c36b1911987a..eeacaa59380a 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -112,8 +112,10 @@ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
112 * used from user space controlled off-channel operations. 112 * used from user space controlled off-channel operations.
113 */ 113 */
114 if (sdata->vif.type != NL80211_IFTYPE_STATION && 114 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
115 sdata->vif.type != NL80211_IFTYPE_MONITOR) 115 sdata->vif.type != NL80211_IFTYPE_MONITOR) {
116 set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
116 netif_tx_stop_all_queues(sdata->dev); 117 netif_tx_stop_all_queues(sdata->dev);
118 }
117 } 119 }
118 mutex_unlock(&local->iflist_mtx); 120 mutex_unlock(&local->iflist_mtx);
119} 121}
@@ -131,6 +133,7 @@ void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
131 continue; 133 continue;
132 134
133 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 135 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
136 set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
134 netif_tx_stop_all_queues(sdata->dev); 137 netif_tx_stop_all_queues(sdata->dev);
135 if (sdata->u.mgd.associated) 138 if (sdata->u.mgd.associated)
136 ieee80211_offchannel_ps_enable(sdata); 139 ieee80211_offchannel_ps_enable(sdata);
@@ -155,8 +158,20 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
155 ieee80211_offchannel_ps_disable(sdata); 158 ieee80211_offchannel_ps_disable(sdata);
156 } 159 }
157 160
158 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) 161 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
162 clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
163 /*
164 * This may wake up queues even though the driver
165 * currently has them stopped. This is not very
166 * likely, since the driver won't have gotten any
167 * (or hardly any) new packets while we weren't
168 * on the right channel, and even if it happens
169 * it will at most lead to queueing up one more
170 * packet per queue in mac80211 rather than on
171 * the interface qdisc.
172 */
159 netif_tx_wake_all_queues(sdata->dev); 173 netif_tx_wake_all_queues(sdata->dev);
174 }
160 175
161 /* re-enable beaconing */ 176 /* re-enable beaconing */
162 if (enable_beaconing && 177 if (enable_beaconing &&
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d38b3767e8cc..bd40b11d5ab9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -283,8 +283,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
283 283
284 if (skb_queue_empty(&local->pending[queue])) { 284 if (skb_queue_empty(&local->pending[queue])) {
285 rcu_read_lock(); 285 rcu_read_lock();
286 list_for_each_entry_rcu(sdata, &local->interfaces, list) 286 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
287 if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
288 continue;
287 netif_wake_subqueue(sdata->dev, queue); 289 netif_wake_subqueue(sdata->dev, queue);
290 }
288 rcu_read_unlock(); 291 rcu_read_unlock();
289 } else 292 } else
290 tasklet_schedule(&local->tx_pending_tasklet); 293 tasklet_schedule(&local->tx_pending_tasklet);