aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/cfg.c3
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c3
-rw-r--r--net/mac80211/offchannel.c30
-rw-r--r--net/mac80211/scan.c9
-rw-r--r--net/mac80211/tx.c15
7 files changed, 40 insertions, 25 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 86ad2c341525..0eaa9092364b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -399,6 +399,9 @@ struct ieee80211_bss_conf {
399 * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be 399 * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be
400 * set by rate control algorithms to indicate probe rate, will 400 * set by rate control algorithms to indicate probe rate, will
401 * be cleared for fragmented frames (except on the last fragment) 401 * be cleared for fragmented frames (except on the last fragment)
402 * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate
403 * that a frame can be transmitted while the queues are stopped for
404 * off-channel operation.
402 * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, 405 * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211,
403 * used to indicate that a pending frame requires TX processing before 406 * used to indicate that a pending frame requires TX processing before
404 * it can be sent out. 407 * it can be sent out.
@@ -464,6 +467,7 @@ enum mac80211_tx_control_flags {
464 IEEE80211_TX_STAT_AMPDU = BIT(10), 467 IEEE80211_TX_STAT_AMPDU = BIT(10),
465 IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), 468 IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11),
466 IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), 469 IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
470 IEEE80211_TX_INTFL_OFFCHAN_TX_OK = BIT(13),
467 IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), 471 IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
468 IEEE80211_TX_INTFL_RETRIED = BIT(15), 472 IEEE80211_TX_INTFL_RETRIED = BIT(15),
469 IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), 473 IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8f6b593a921f..e3dec80cf617 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2749,7 +2749,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2749 goto out_unlock; 2749 goto out_unlock;
2750 } 2750 }
2751 2751
2752 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; 2752 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN |
2753 IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
2753 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) 2754 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
2754 IEEE80211_SKB_CB(skb)->hw_queue = 2755 IEEE80211_SKB_CB(skb)->hw_queue =
2755 local->hw.offchannel_tx_hw_queue; 2756 local->hw.offchannel_tx_hw_queue;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5635dfc7da34..76cdcfcd614c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -809,6 +809,7 @@ enum queue_stop_reason {
809 IEEE80211_QUEUE_STOP_REASON_AGGREGATION, 809 IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
810 IEEE80211_QUEUE_STOP_REASON_SUSPEND, 810 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
811 IEEE80211_QUEUE_STOP_REASON_SKB_ADD, 811 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
812 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
812}; 813};
813 814
814#ifdef CONFIG_MAC80211_LEDS 815#ifdef CONFIG_MAC80211_LEDS
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 76cacdb062c8..efb22763d56d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -685,7 +685,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
685 if (powersave) 685 if (powersave)
686 nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); 686 nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
687 687
688 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 688 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
689 IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
689 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 690 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
690 IEEE80211_STA_CONNECTION_POLL)) 691 IEEE80211_STA_CONNECTION_POLL))
691 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; 692 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;
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)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index edd47d9acb99..d9e2df96f676 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -382,6 +382,11 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
382 int i; 382 int i;
383 struct ieee80211_sub_if_data *sdata; 383 struct ieee80211_sub_if_data *sdata;
384 enum ieee80211_band band = local->hw.conf.channel->band; 384 enum ieee80211_band band = local->hw.conf.channel->band;
385 u32 tx_flags;
386
387 tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
388 if (local->scan_req->no_cck)
389 tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
385 390
386 sdata = rcu_dereference_protected(local->scan_sdata, 391 sdata = rcu_dereference_protected(local->scan_sdata,
387 lockdep_is_held(&local->mtx)); 392 lockdep_is_held(&local->mtx));
@@ -393,9 +398,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
393 local->scan_req->ssids[i].ssid_len, 398 local->scan_req->ssids[i].ssid_len,
394 local->scan_req->ie, local->scan_req->ie_len, 399 local->scan_req->ie, local->scan_req->ie_len,
395 local->scan_req->rates[band], false, 400 local->scan_req->rates[band], false,
396 local->scan_req->no_cck ? 401 tx_flags, local->hw.conf.channel, true);
397 IEEE80211_TX_CTL_NO_CCK_RATE : 0,
398 local->hw.conf.channel, true);
399 402
400 /* 403 /*
401 * After sending probe requests, wait for probe responses 404 * After sending probe requests, wait for probe responses
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 2ef0e19b06bb..f476aa6a771d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1230,6 +1230,21 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1230 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 1230 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
1231 if (local->queue_stop_reasons[q] || 1231 if (local->queue_stop_reasons[q] ||
1232 (!txpending && !skb_queue_empty(&local->pending[q]))) { 1232 (!txpending && !skb_queue_empty(&local->pending[q]))) {
1233 if (unlikely(info->flags &
1234 IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
1235 local->queue_stop_reasons[q] &
1236 ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
1237 /*
1238 * Drop off-channel frames if queues are stopped
1239 * for any reason other than off-channel
1240 * operation. Never queue them.
1241 */
1242 spin_unlock_irqrestore(
1243 &local->queue_stop_reason_lock, flags);
1244 ieee80211_purge_tx_queue(&local->hw, skbs);
1245 return true;
1246 }
1247
1233 /* 1248 /*
1234 * Since queue is stopped, queue up frames for later 1249 * Since queue is stopped, queue up frames for later
1235 * transmission from the tx-pending tasklet when the 1250 * transmission from the tx-pending tasklet when the