diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 48 |
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 | } |
266 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); | 266 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); |
267 | 267 | ||
268 | void 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 | |||
268 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | 294 | static 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); |