diff options
-rw-r--r-- | include/net/mac80211.h | 4 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 3 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 30 | ||||
-rw-r--r-- | net/mac80211/scan.c | 9 | ||||
-rw-r--r-- | net/mac80211/tx.c | 15 |
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 | ||
193 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | 183 | void 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 |