diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 19 | ||||
-rw-r--r-- | net/mac80211/util.c | 5 |
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 | */ |
481 | enum ieee80211_sdata_state_bits { | 483 | enum ieee80211_sdata_state_bits { |
482 | SDATA_STATE_RUNNING, | 484 | SDATA_STATE_RUNNING, |
485 | SDATA_STATE_OFFCHANNEL, | ||
483 | }; | 486 | }; |
484 | 487 | ||
485 | struct ieee80211_sub_if_data { | 488 | struct 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); |