aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-04-03 10:28:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-11 16:23:50 -0400
commit3a25a8c8b75b430c4f4022918e26fa51d557ecde (patch)
treed4863b7f17c2ea44fb523e29951b6bd202ddb1ad /net
parent4b6f1dd6a6faf4ed8d209bbd548e78b15e55aee8 (diff)
mac80211: add improved HW queue control
mac80211 currently only supports one hardware queue per AC. This is already problematic for off-channel uses since if we go off channel while the BE queue is full and then try to send an off-channel frame the frame will never go out. This will become worse when we support multi-channel since then a queue on one channel might be full, but we have to stop the software queue for all channels. That is obviously not desirable. To address this problem allow drivers to register more hardware queues, and allow them to map them to virtual interfaces. When they stop a hardware queue the corresponding AC software queues on the correct interfaces will be stopped as well. Additionally, there's an off-channel queue to solve that problem and a per-interface after-DTIM beacon queue. This allows drivers to manage software queues closer to how the hardware works. Currently, there's a limit of 16 hardware queues. This may or may not be sufficient, we can adjust it as needed. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-tx.c39
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/iface.c62
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/tx.c38
-rw-r--r--net/mac80211/util.c48
7 files changed, 162 insertions, 38 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 9628a189244..5b7053c5873 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -286,25 +286,25 @@ static inline int ieee80211_ac_from_tid(int tid)
286 * a global "agg_queue_stop" refcount. 286 * a global "agg_queue_stop" refcount.
287 */ 287 */
288static void __acquires(agg_queue) 288static void __acquires(agg_queue)
289ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid) 289ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
290{ 290{
291 int queue = ieee80211_ac_from_tid(tid); 291 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
292 292
293 if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1) 293 if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1)
294 ieee80211_stop_queue_by_reason( 294 ieee80211_stop_queue_by_reason(
295 &local->hw, queue, 295 &sdata->local->hw, queue,
296 IEEE80211_QUEUE_STOP_REASON_AGGREGATION); 296 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
297 __acquire(agg_queue); 297 __acquire(agg_queue);
298} 298}
299 299
300static void __releases(agg_queue) 300static void __releases(agg_queue)
301ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) 301ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
302{ 302{
303 int queue = ieee80211_ac_from_tid(tid); 303 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
304 304
305 if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0) 305 if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0)
306 ieee80211_wake_queue_by_reason( 306 ieee80211_wake_queue_by_reason(
307 &local->hw, queue, 307 &sdata->local->hw, queue,
308 IEEE80211_QUEUE_STOP_REASON_AGGREGATION); 308 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
309 __release(agg_queue); 309 __release(agg_queue);
310} 310}
@@ -314,13 +314,14 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)
314 * requires a call to ieee80211_agg_splice_finish later 314 * requires a call to ieee80211_agg_splice_finish later
315 */ 315 */
316static void __acquires(agg_queue) 316static void __acquires(agg_queue)
317ieee80211_agg_splice_packets(struct ieee80211_local *local, 317ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata,
318 struct tid_ampdu_tx *tid_tx, u16 tid) 318 struct tid_ampdu_tx *tid_tx, u16 tid)
319{ 319{
320 int queue = ieee80211_ac_from_tid(tid); 320 struct ieee80211_local *local = sdata->local;
321 int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)];
321 unsigned long flags; 322 unsigned long flags;
322 323
323 ieee80211_stop_queue_agg(local, tid); 324 ieee80211_stop_queue_agg(sdata, tid);
324 325
325 if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" 326 if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
326 " from the pending queue\n", tid)) 327 " from the pending queue\n", tid))
@@ -336,9 +337,9 @@ ieee80211_agg_splice_packets(struct ieee80211_local *local,
336} 337}
337 338
338static void __releases(agg_queue) 339static void __releases(agg_queue)
339ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) 340ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid)
340{ 341{
341 ieee80211_wake_queue_agg(local, tid); 342 ieee80211_wake_queue_agg(sdata, tid);
342} 343}
343 344
344void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) 345void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
@@ -376,9 +377,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
376 " tid %d\n", tid); 377 " tid %d\n", tid);
377#endif 378#endif
378 spin_lock_bh(&sta->lock); 379 spin_lock_bh(&sta->lock);
379 ieee80211_agg_splice_packets(local, tid_tx, tid); 380 ieee80211_agg_splice_packets(sdata, tid_tx, tid);
380 ieee80211_assign_tid_tx(sta, tid, NULL); 381 ieee80211_assign_tid_tx(sta, tid, NULL);
381 ieee80211_agg_splice_finish(local, tid); 382 ieee80211_agg_splice_finish(sdata, tid);
382 spin_unlock_bh(&sta->lock); 383 spin_unlock_bh(&sta->lock);
383 384
384 kfree_rcu(tid_tx, rcu_head); 385 kfree_rcu(tid_tx, rcu_head);
@@ -598,14 +599,14 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
598 */ 599 */
599 spin_lock_bh(&sta->lock); 600 spin_lock_bh(&sta->lock);
600 601
601 ieee80211_agg_splice_packets(local, tid_tx, tid); 602 ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid);
602 /* 603 /*
603 * Now mark as operational. This will be visible 604 * Now mark as operational. This will be visible
604 * in the TX path, and lets it go lock-free in 605 * in the TX path, and lets it go lock-free in
605 * the common case. 606 * the common case.
606 */ 607 */
607 set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); 608 set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
608 ieee80211_agg_splice_finish(local, tid); 609 ieee80211_agg_splice_finish(sta->sdata, tid);
609 610
610 spin_unlock_bh(&sta->lock); 611 spin_unlock_bh(&sta->lock);
611} 612}
@@ -790,12 +791,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
790 * more. 791 * more.
791 */ 792 */
792 793
793 ieee80211_agg_splice_packets(local, tid_tx, tid); 794 ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid);
794 795
795 /* future packets must not find the tid_tx struct any more */ 796 /* future packets must not find the tid_tx struct any more */
796 ieee80211_assign_tid_tx(sta, tid, NULL); 797 ieee80211_assign_tid_tx(sta, tid, NULL);
797 798
798 ieee80211_agg_splice_finish(local, tid); 799 ieee80211_agg_splice_finish(sta->sdata, tid);
799 800
800 kfree_rcu(tid_tx, rcu_head); 801 kfree_rcu(tid_tx, rcu_head);
801 802
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 667d9394339..d6163b98f7b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2106,6 +2106,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2106 2106
2107 IEEE80211_SKB_CB(skb)->flags = flags; 2107 IEEE80211_SKB_CB(skb)->flags = flags;
2108 2108
2109 if (flags & IEEE80211_TX_CTL_TX_OFFCHAN)
2110 IEEE80211_SKB_CB(skb)->hw_queue =
2111 local->hw.offchannel_tx_hw_queue;
2112
2109 skb->dev = sdata->dev; 2113 skb->dev = sdata->dev;
2110 2114
2111 *cookie = (unsigned long) skb; 2115 *cookie = (unsigned long) skb;
@@ -2147,6 +2151,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2147 /* modify cookie to prevent API mismatches */ 2151 /* modify cookie to prevent API mismatches */
2148 *cookie ^= 2; 2152 *cookie ^= 2;
2149 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; 2153 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
2154 IEEE80211_SKB_CB(skb)->hw_queue =
2155 local->hw.offchannel_tx_hw_queue;
2150 local->hw_roc_skb = skb; 2156 local->hw_roc_skb = skb;
2151 local->hw_roc_skb_for_status = skb; 2157 local->hw_roc_skb_for_status = skb;
2152 mutex_unlock(&local->mtx); 2158 mutex_unlock(&local->mtx);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8ed074f7e6c..4be11ea3dfc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1449,6 +1449,7 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
1449 enum queue_stop_reason reason); 1449 enum queue_stop_reason reason);
1450void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 1450void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
1451 enum queue_stop_reason reason); 1451 enum queue_stop_reason reason);
1452void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
1452void ieee80211_add_pending_skb(struct ieee80211_local *local, 1453void ieee80211_add_pending_skb(struct ieee80211_local *local,
1453 struct sk_buff *skb); 1454 struct sk_buff *skb);
1454void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, 1455void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2b88cb278fc..ed297649c57 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -149,6 +149,34 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
149 return 0; 149 return 0;
150} 150}
151 151
152static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata)
153{
154 int n_queues = sdata->local->hw.queues;
155 int i;
156
157 for (i = 0; i < IEEE80211_NUM_ACS; i++) {
158 if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
159 IEEE80211_INVAL_HW_QUEUE))
160 return -EINVAL;
161 if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >=
162 n_queues))
163 return -EINVAL;
164 }
165
166 if (sdata->vif.type != NL80211_IFTYPE_AP) {
167 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
168 return 0;
169 }
170
171 if (WARN_ON_ONCE(sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE))
172 return -EINVAL;
173
174 if (WARN_ON_ONCE(sdata->vif.cab_queue >= n_queues))
175 return -EINVAL;
176
177 return 0;
178}
179
152void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, 180void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
153 const int offset) 181 const int offset)
154{ 182{
@@ -169,6 +197,20 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
169#undef ADJUST 197#undef ADJUST
170} 198}
171 199
200static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
201{
202 struct ieee80211_local *local = sdata->local;
203 int i;
204
205 for (i = 0; i < IEEE80211_NUM_ACS; i++) {
206 if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
207 sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
208 else
209 sdata->vif.hw_queue[i] = i;
210 }
211 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
212}
213
172static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) 214static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
173{ 215{
174 struct ieee80211_sub_if_data *sdata; 216 struct ieee80211_sub_if_data *sdata;
@@ -190,6 +232,8 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
190 snprintf(sdata->name, IFNAMSIZ, "%s-monitor", 232 snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
191 wiphy_name(local->hw.wiphy)); 233 wiphy_name(local->hw.wiphy));
192 234
235 ieee80211_set_default_queues(sdata);
236
193 ret = drv_add_interface(local, sdata); 237 ret = drv_add_interface(local, sdata);
194 if (WARN_ON(ret)) { 238 if (WARN_ON(ret)) {
195 /* ok .. stupid driver, it asked for this! */ 239 /* ok .. stupid driver, it asked for this! */
@@ -197,6 +241,12 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
197 return ret; 241 return ret;
198 } 242 }
199 243
244 ret = ieee80211_check_queues(sdata);
245 if (ret) {
246 kfree(sdata);
247 return ret;
248 }
249
200 rcu_assign_pointer(local->monitor_sdata, sdata); 250 rcu_assign_pointer(local->monitor_sdata, sdata);
201 251
202 return 0; 252 return 0;
@@ -344,6 +394,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
344 res = drv_add_interface(local, sdata); 394 res = drv_add_interface(local, sdata);
345 if (res) 395 if (res)
346 goto err_stop; 396 goto err_stop;
397 res = ieee80211_check_queues(sdata);
398 if (res)
399 goto err_del_interface;
347 } 400 }
348 401
349 if (sdata->vif.type == NL80211_IFTYPE_AP) { 402 if (sdata->vif.type == NL80211_IFTYPE_AP) {
@@ -1040,6 +1093,13 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
1040 if (ret) 1093 if (ret)
1041 type = sdata->vif.type; 1094 type = sdata->vif.type;
1042 1095
1096 /*
1097 * Ignore return value here, there's not much we can do since
1098 * the driver changed the interface type internally already.
1099 * The warnings will hopefully make driver authors fix it :-)
1100 */
1101 ieee80211_check_queues(sdata);
1102
1043 ieee80211_setup_sdata(sdata, type); 1103 ieee80211_setup_sdata(sdata, type);
1044 1104
1045 err = ieee80211_do_open(sdata->dev, false); 1105 err = ieee80211_do_open(sdata->dev, false);
@@ -1266,6 +1326,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1266 sizeof(sdata->rc_rateidx_mcs_mask[i])); 1326 sizeof(sdata->rc_rateidx_mcs_mask[i]));
1267 } 1327 }
1268 1328
1329 ieee80211_set_default_queues(sdata);
1330
1269 /* setup type-dependent data */ 1331 /* setup type-dependent data */
1270 ieee80211_setup_sdata(sdata, type); 1332 ieee80211_setup_sdata(sdata, type);
1271 1333
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d019f0d3a0f..ac79d5e8e0d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -591,6 +591,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
591 local->hw.max_report_rates = 0; 591 local->hw.max_report_rates = 0;
592 local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; 592 local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
593 local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; 593 local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
594 local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE;
594 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; 595 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
595 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; 596 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
596 local->user_power_level = -1; 597 local->user_power_level = -1;
@@ -687,6 +688,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
687 WLAN_CIPHER_SUITE_AES_CMAC 688 WLAN_CIPHER_SUITE_AES_CMAC
688 }; 689 };
689 690
691 if (hw->flags & IEEE80211_HW_QUEUE_CONTROL &&
692 (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
693 local->hw.offchannel_tx_hw_queue >= local->hw.queues))
694 return -EINVAL;
695
690 if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) 696 if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns)
691#ifdef CONFIG_PM 697#ifdef CONFIG_PM
692 && (!local->ops->suspend || !local->ops->resume) 698 && (!local->ops->suspend || !local->ops->resume)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a8d0188ab40..4f6aac16ac3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -400,6 +400,8 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
400 return TX_CONTINUE; 400 return TX_CONTINUE;
401 401
402 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; 402 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
403 if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
404 info->hw_queue = tx->sdata->vif.cab_queue;
403 405
404 /* device releases frame after DTIM beacon */ 406 /* device releases frame after DTIM beacon */
405 if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) 407 if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING))
@@ -1214,11 +1216,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1214 bool txpending) 1216 bool txpending)
1215{ 1217{
1216 struct sk_buff *skb, *tmp; 1218 struct sk_buff *skb, *tmp;
1217 struct ieee80211_tx_info *info;
1218 unsigned long flags; 1219 unsigned long flags;
1219 1220
1220 skb_queue_walk_safe(skbs, skb, tmp) { 1221 skb_queue_walk_safe(skbs, skb, tmp) {
1221 int q = skb_get_queue_mapping(skb); 1222 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1223 int q = info->hw_queue;
1224
1225#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1226 if (WARN_ON_ONCE(q >= local->hw.queues)) {
1227 __skb_unlink(skb, skbs);
1228 dev_kfree_skb(skb);
1229 continue;
1230 }
1231#endif
1222 1232
1223 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 1233 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
1224 if (local->queue_stop_reasons[q] || 1234 if (local->queue_stop_reasons[q] ||
@@ -1240,7 +1250,6 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1240 } 1250 }
1241 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1251 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1242 1252
1243 info = IEEE80211_SKB_CB(skb);
1244 info->control.vif = vif; 1253 info->control.vif = vif;
1245 info->control.sta = sta; 1254 info->control.sta = sta;
1246 1255
@@ -1284,9 +1293,14 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
1284 switch (sdata->vif.type) { 1293 switch (sdata->vif.type) {
1285 case NL80211_IFTYPE_MONITOR: 1294 case NL80211_IFTYPE_MONITOR:
1286 sdata = rcu_dereference(local->monitor_sdata); 1295 sdata = rcu_dereference(local->monitor_sdata);
1287 if (sdata) 1296 if (sdata) {
1288 vif = &sdata->vif; 1297 vif = &sdata->vif;
1289 else 1298 info->hw_queue =
1299 vif->hw_queue[skb_get_queue_mapping(skb)];
1300 } else if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
1301 dev_kfree_skb(skb);
1302 return true;
1303 } else
1290 vif = NULL; 1304 vif = NULL;
1291 break; 1305 break;
1292 case NL80211_IFTYPE_AP_VLAN: 1306 case NL80211_IFTYPE_AP_VLAN:
@@ -1402,6 +1416,12 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1402 tx.channel = local->hw.conf.channel; 1416 tx.channel = local->hw.conf.channel;
1403 info->band = tx.channel->band; 1417 info->band = tx.channel->band;
1404 1418
1419 /* set up hw_queue value early */
1420 if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
1421 !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
1422 info->hw_queue =
1423 sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
1424
1405 if (!invoke_tx_handlers(&tx)) 1425 if (!invoke_tx_handlers(&tx))
1406 result = __ieee80211_tx(local, &tx.skbs, led_len, 1426 result = __ieee80211_tx(local, &tx.skbs, led_len,
1407 tx.sta, txpending); 1427 tx.sta, txpending);
@@ -2172,7 +2192,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
2172void ieee80211_tx_pending(unsigned long data) 2192void ieee80211_tx_pending(unsigned long data)
2173{ 2193{
2174 struct ieee80211_local *local = (struct ieee80211_local *)data; 2194 struct ieee80211_local *local = (struct ieee80211_local *)data;
2175 struct ieee80211_sub_if_data *sdata;
2176 unsigned long flags; 2195 unsigned long flags;
2177 int i; 2196 int i;
2178 bool txok; 2197 bool txok;
@@ -2209,8 +2228,7 @@ void ieee80211_tx_pending(unsigned long data)
2209 } 2228 }
2210 2229
2211 if (skb_queue_empty(&local->pending[i])) 2230 if (skb_queue_empty(&local->pending[i]))
2212 list_for_each_entry_rcu(sdata, &local->interfaces, list) 2231 ieee80211_propagate_queue_wake(local, i);
2213 netif_wake_subqueue(sdata->dev, i);
2214 } 2232 }
2215 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 2233 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
2216 2234
@@ -2717,11 +2735,13 @@ EXPORT_SYMBOL(ieee80211_get_buffered_bc);
2717void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, 2735void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
2718 struct sk_buff *skb, int tid) 2736 struct sk_buff *skb, int tid)
2719{ 2737{
2738 int ac = ieee802_1d_to_ac[tid];
2739
2720 skb_set_mac_header(skb, 0); 2740 skb_set_mac_header(skb, 0);
2721 skb_set_network_header(skb, 0); 2741 skb_set_network_header(skb, 0);
2722 skb_set_transport_header(skb, 0); 2742 skb_set_transport_header(skb, 0);
2723 2743
2724 skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); 2744 skb_set_queue_mapping(skb, ac);
2725 skb->priority = tid; 2745 skb->priority = tid;
2726 2746
2727 /* 2747 /*
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 9e8f4b89255..e67fe5c1def 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -265,11 +265,36 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
265} 265}
266EXPORT_SYMBOL(ieee80211_ctstoself_duration); 266EXPORT_SYMBOL(ieee80211_ctstoself_duration);
267 267
268void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
269{
270 struct ieee80211_sub_if_data *sdata;
271
272 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
273 int ac;
274
275 if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
276 continue;
277
278 if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
279 local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
280 continue;
281
282 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
283 int ac_queue = sdata->vif.hw_queue[ac];
284
285 if (ac_queue == queue ||
286 (sdata->vif.cab_queue == queue &&
287 local->queue_stop_reasons[ac_queue] == 0 &&
288 skb_queue_empty(&local->pending[ac_queue])))
289 netif_wake_subqueue(sdata->dev, ac);
290 }
291 }
292}
293
268static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, 294static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
269 enum queue_stop_reason reason) 295 enum queue_stop_reason reason)
270{ 296{
271 struct ieee80211_local *local = hw_to_local(hw); 297 struct ieee80211_local *local = hw_to_local(hw);
272 struct ieee80211_sub_if_data *sdata;
273 298
274 trace_wake_queue(local, queue, reason); 299 trace_wake_queue(local, queue, reason);
275 300
@@ -287,11 +312,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
287 312
288 if (skb_queue_empty(&local->pending[queue])) { 313 if (skb_queue_empty(&local->pending[queue])) {
289 rcu_read_lock(); 314 rcu_read_lock();
290 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 315 ieee80211_propagate_queue_wake(local, queue);
291 if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
292 continue;
293 netif_wake_subqueue(sdata->dev, queue);
294 }
295 rcu_read_unlock(); 316 rcu_read_unlock();
296 } else 317 } else
297 tasklet_schedule(&local->tx_pending_tasklet); 318 tasklet_schedule(&local->tx_pending_tasklet);
@@ -332,8 +353,15 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
332 __set_bit(reason, &local->queue_stop_reasons[queue]); 353 __set_bit(reason, &local->queue_stop_reasons[queue]);
333 354
334 rcu_read_lock(); 355 rcu_read_lock();
335 list_for_each_entry_rcu(sdata, &local->interfaces, list) 356 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
336 netif_stop_subqueue(sdata->dev, queue); 357 int ac;
358
359 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
360 if (sdata->vif.hw_queue[ac] == queue ||
361 sdata->vif.cab_queue == queue)
362 netif_stop_subqueue(sdata->dev, ac);
363 }
364 }
337 rcu_read_unlock(); 365 rcu_read_unlock();
338} 366}
339 367
@@ -360,8 +388,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
360{ 388{
361 struct ieee80211_hw *hw = &local->hw; 389 struct ieee80211_hw *hw = &local->hw;
362 unsigned long flags; 390 unsigned long flags;
363 int queue = skb_get_queue_mapping(skb);
364 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 391 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
392 int queue = info->hw_queue;
365 393
366 if (WARN_ON(!info->control.vif)) { 394 if (WARN_ON(!info->control.vif)) {
367 kfree_skb(skb); 395 kfree_skb(skb);
@@ -393,7 +421,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
393 continue; 421 continue;
394 } 422 }
395 423
396 queue = skb_get_queue_mapping(skb); 424 queue = info->hw_queue;
397 425
398 __ieee80211_stop_queue(hw, queue, 426 __ieee80211_stop_queue(hw, queue,
399 IEEE80211_QUEUE_STOP_REASON_SKB_ADD); 427 IEEE80211_QUEUE_STOP_REASON_SKB_ADD);