aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/offchannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/offchannel.c')
-rw-r--r--net/mac80211/offchannel.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index a3ad4c3c80a3..cc79b4a2e821 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -113,6 +113,15 @@ 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 /*
118 * Stop queues and transmit all frames queued by the driver
119 * before sending nullfunc to enable powersave at the AP.
120 */
121 ieee80211_stop_queues_by_reason(&local->hw,
122 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
123 drv_flush(local, false);
124
116 mutex_lock(&local->iflist_mtx); 125 mutex_lock(&local->iflist_mtx);
117 list_for_each_entry(sdata, &local->interfaces, list) { 126 list_for_each_entry(sdata, &local->interfaces, list) {
118 if (!ieee80211_sdata_running(sdata)) 127 if (!ieee80211_sdata_running(sdata))
@@ -125,18 +134,17 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
125 set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); 134 set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
126 135
127 /* Check to see if we should disable beaconing. */ 136 /* Check to see if we should disable beaconing. */
128 if (sdata->vif.type == NL80211_IFTYPE_AP || 137 if (sdata->vif.bss_conf.enable_beacon) {
129 sdata->vif.type == NL80211_IFTYPE_ADHOC || 138 set_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
130 sdata->vif.type == NL80211_IFTYPE_MESH_POINT) 139 &sdata->state);
140 sdata->vif.bss_conf.enable_beacon = false;
131 ieee80211_bss_info_change_notify( 141 ieee80211_bss_info_change_notify(
132 sdata, BSS_CHANGED_BEACON_ENABLED); 142 sdata, BSS_CHANGED_BEACON_ENABLED);
133
134 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
135 netif_tx_stop_all_queues(sdata->dev);
136 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
137 sdata->u.mgd.associated)
138 ieee80211_offchannel_ps_enable(sdata);
139 } 143 }
144
145 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
146 sdata->u.mgd.associated)
147 ieee80211_offchannel_ps_enable(sdata);
140 } 148 }
141 mutex_unlock(&local->iflist_mtx); 149 mutex_unlock(&local->iflist_mtx);
142} 150}
@@ -164,27 +172,17 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
164 sdata->u.mgd.associated) 172 sdata->u.mgd.associated)
165 ieee80211_offchannel_ps_disable(sdata); 173 ieee80211_offchannel_ps_disable(sdata);
166 174
167 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { 175 if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
168 /* 176 &sdata->state)) {
169 * This may wake up queues even though the driver 177 sdata->vif.bss_conf.enable_beacon = true;
170 * currently has them stopped. This is not very
171 * likely, since the driver won't have gotten any
172 * (or hardly any) new packets while we weren't
173 * on the right channel, and even if it happens
174 * it will at most lead to queueing up one more
175 * packet per queue in mac80211 rather than on
176 * the interface qdisc.
177 */
178 netif_tx_wake_all_queues(sdata->dev);
179 }
180
181 if (sdata->vif.type == NL80211_IFTYPE_AP ||
182 sdata->vif.type == NL80211_IFTYPE_ADHOC ||
183 sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
184 ieee80211_bss_info_change_notify( 178 ieee80211_bss_info_change_notify(
185 sdata, BSS_CHANGED_BEACON_ENABLED); 179 sdata, BSS_CHANGED_BEACON_ENABLED);
180 }
186 } 181 }
187 mutex_unlock(&local->iflist_mtx); 182 mutex_unlock(&local->iflist_mtx);
183
184 ieee80211_wake_queues_by_reason(&local->hw,
185 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL);
188} 186}
189 187
190void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) 188void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)