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.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 73c7d7345abd..92ea1770461b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -344,15 +344,36 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
344{ 344{
345 struct ieee80211_local *local = hw_to_local(hw); 345 struct ieee80211_local *local = hw_to_local(hw);
346 346
347 /* we don't need to track ampdu queues */ 347 if (queue >= hw->queues) {
348 if (queue < ieee80211_num_regular_queues(hw)) { 348 if (local->ampdu_ac_queue[queue - hw->queues] < 0)
349 __clear_bit(reason, &local->queue_stop_reasons[queue]); 349 return;
350
351 /*
352 * for virtual aggregation queues, we need to refcount the
353 * internal mac80211 disable (multiple times!), keep track of
354 * driver disable _and_ make sure the regular queue is
355 * actually enabled.
356 */
357 if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
358 local->amdpu_ac_stop_refcnt[queue - hw->queues]--;
359 else
360 __clear_bit(reason, &local->queue_stop_reasons[queue]);
350 361
351 if (local->queue_stop_reasons[queue] != 0) 362 if (local->queue_stop_reasons[queue] ||
352 /* someone still has this queue stopped */ 363 local->amdpu_ac_stop_refcnt[queue - hw->queues])
353 return; 364 return;
365
366 /* now go on to treat the corresponding regular queue */
367 queue = local->ampdu_ac_queue[queue - hw->queues];
368 reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
354 } 369 }
355 370
371 __clear_bit(reason, &local->queue_stop_reasons[queue]);
372
373 if (local->queue_stop_reasons[queue] != 0)
374 /* someone still has this queue stopped */
375 return;
376
356 if (test_bit(queue, local->queues_pending)) { 377 if (test_bit(queue, local->queues_pending)) {
357 set_bit(queue, local->queues_pending_run); 378 set_bit(queue, local->queues_pending_run);
358 tasklet_schedule(&local->tx_pending_tasklet); 379 tasklet_schedule(&local->tx_pending_tasklet);
@@ -361,8 +382,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
361 } 382 }
362} 383}
363 384
364static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 385void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
365 enum queue_stop_reason reason) 386 enum queue_stop_reason reason)
366{ 387{
367 struct ieee80211_local *local = hw_to_local(hw); 388 struct ieee80211_local *local = hw_to_local(hw);
368 unsigned long flags; 389 unsigned long flags;
@@ -384,15 +405,33 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
384{ 405{
385 struct ieee80211_local *local = hw_to_local(hw); 406 struct ieee80211_local *local = hw_to_local(hw);
386 407
387 /* we don't need to track ampdu queues */ 408 if (queue >= hw->queues) {
388 if (queue < ieee80211_num_regular_queues(hw)) 409 if (local->ampdu_ac_queue[queue - hw->queues] < 0)
389 __set_bit(reason, &local->queue_stop_reasons[queue]); 410 return;
411
412 /*
413 * for virtual aggregation queues, we need to refcount the
414 * internal mac80211 disable (multiple times!), keep track of
415 * driver disable _and_ make sure the regular queue is
416 * actually enabled.
417 */
418 if (reason == IEEE80211_QUEUE_STOP_REASON_AGGREGATION)
419 local->amdpu_ac_stop_refcnt[queue - hw->queues]++;
420 else
421 __set_bit(reason, &local->queue_stop_reasons[queue]);
422
423 /* now go on to treat the corresponding regular queue */
424 queue = local->ampdu_ac_queue[queue - hw->queues];
425 reason = IEEE80211_QUEUE_STOP_REASON_AGGREGATION;
426 }
427
428 __set_bit(reason, &local->queue_stop_reasons[queue]);
390 429
391 netif_stop_subqueue(local->mdev, queue); 430 netif_stop_subqueue(local->mdev, queue);
392} 431}
393 432
394static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 433void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
395 enum queue_stop_reason reason) 434 enum queue_stop_reason reason)
396{ 435{
397 struct ieee80211_local *local = hw_to_local(hw); 436 struct ieee80211_local *local = hw_to_local(hw);
398 unsigned long flags; 437 unsigned long flags;
@@ -418,7 +457,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
418 457
419 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 458 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
420 459
421 for (i = 0; i < ieee80211_num_queues(hw); i++) 460 for (i = 0; i < hw->queues; i++)
422 __ieee80211_stop_queue(hw, i, reason); 461 __ieee80211_stop_queue(hw, i, reason);
423 462
424 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 463 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
@@ -434,6 +473,16 @@ EXPORT_SYMBOL(ieee80211_stop_queues);
434int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) 473int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
435{ 474{
436 struct ieee80211_local *local = hw_to_local(hw); 475 struct ieee80211_local *local = hw_to_local(hw);
476 unsigned long flags;
477
478 if (queue >= hw->queues) {
479 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
480 queue = local->ampdu_ac_queue[queue - hw->queues];
481 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
482 if (queue < 0)
483 return true;
484 }
485
437 return __netif_subqueue_stopped(local->mdev, queue); 486 return __netif_subqueue_stopped(local->mdev, queue);
438} 487}
439EXPORT_SYMBOL(ieee80211_queue_stopped); 488EXPORT_SYMBOL(ieee80211_queue_stopped);