aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 9e8f4b892555..e67fe5c1def9 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);