diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 75 |
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 | ||
364 | static void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 385 | void 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 | ||
394 | static void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 433 | void 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); | |||
434 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | 473 | int 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 | } |
439 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 488 | EXPORT_SYMBOL(ieee80211_queue_stopped); |