aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/offchannel.c
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2013-02-11 12:21:07 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-11 16:52:21 -0500
commit6c17b77b67587b9f9e3070fb89fe98cef3187131 (patch)
tree5e47a8feb14ec822b276c893a9fb3cca93e6bbd0 /net/mac80211/offchannel.c
parentdf15a6c4fa7f77511663d7b5f9134f37ad2e8c92 (diff)
mac80211: Fix tx queue handling during scans
Scans currently work by stopping the netdev tx queues but leaving the mac80211 queues active. This stops the flow of incoming packets while still allowing mac80211 to transmit nullfunc and probe request frames to facilitate scanning. However, the driver may try to wake the mac80211 queues while in this state, which will also wake the netdev queues. To prevent this, add a new queue stop reason, IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, to be used when stopping the tx queues for off-channel operation. This prevents the netdev queues from waking when a driver wakes the mac80211 queues. This also stops all frames from being transmitted, even those meant to be sent off-channel. Add a new tx control flag, IEEE80211_TX_CTL_OFFCHAN_TX_OK, which allows frames to be transmitted when the queues are stopped only for the off-channel stop reason. Update all locations transmitting off-channel frames to use this flag. Signed-off-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/offchannel.c')
-rw-r--r--net/mac80211/offchannel.c30
1 files changed, 10 insertions, 20 deletions
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 82baf5b6ecf4..4c3ee3e8285c 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -113,6 +113,10 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
113 * notify the AP about us leaving the channel and stop all 113 * notify the AP about us leaving the channel and stop all
114 * STA interfaces. 114 * STA interfaces.
115 */ 115 */
116
117 ieee80211_stop_queues_by_reason(&local->hw,
118 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
119
116 mutex_lock(&local->iflist_mtx); 120 mutex_lock(&local->iflist_mtx);
117 list_for_each_entry(sdata, &local->interfaces, list) { 121 list_for_each_entry(sdata, &local->interfaces, list) {
118 if (!ieee80211_sdata_running(sdata)) 122 if (!ieee80211_sdata_running(sdata))
@@ -133,12 +137,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
133 sdata, BSS_CHANGED_BEACON_ENABLED); 137 sdata, BSS_CHANGED_BEACON_ENABLED);
134 } 138 }
135 139
136 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { 140 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
137 netif_tx_stop_all_queues(sdata->dev); 141 sdata->u.mgd.associated)
138 if (sdata->vif.type == NL80211_IFTYPE_STATION && 142 ieee80211_offchannel_ps_enable(sdata);
139 sdata->u.mgd.associated)
140 ieee80211_offchannel_ps_enable(sdata);
141 }
142 } 143 }
143 mutex_unlock(&local->iflist_mtx); 144 mutex_unlock(&local->iflist_mtx);
144} 145}
@@ -166,20 +167,6 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
166 sdata->u.mgd.associated) 167 sdata->u.mgd.associated)
167 ieee80211_offchannel_ps_disable(sdata); 168 ieee80211_offchannel_ps_disable(sdata);
168 169
169 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
170 /*
171 * This may wake up queues even though the driver
172 * currently has them stopped. This is not very
173 * likely, since the driver won't have gotten any
174 * (or hardly any) new packets while we weren't
175 * on the right channel, and even if it happens
176 * it will at most lead to queueing up one more
177 * packet per queue in mac80211 rather than on
178 * the interface qdisc.
179 */
180 netif_tx_wake_all_queues(sdata->dev);
181 }
182
183 if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, 170 if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
184 &sdata->state)) { 171 &sdata->state)) {
185 sdata->vif.bss_conf.enable_beacon = true; 172 sdata->vif.bss_conf.enable_beacon = true;
@@ -188,6 +175,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
188 } 175 }
189 } 176 }
190 mutex_unlock(&local->iflist_mtx); 177 mutex_unlock(&local->iflist_mtx);
178
179 ieee80211_wake_queues_by_reason(&local->hw,
180 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
191} 181}
192 182
193void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) 183void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)