aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-01-22 06:15:15 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-12 03:57:44 -0400
commitc22b0ff572e4b3723a3c552e74a4ba2497606040 (patch)
tree67b00aae103114becb3ec24770466ba6f8f34898 /drivers/net/wireless/iwlwifi
parente0b8d405132db38fafc9da86ef4de0ebe2be468e (diff)
iwlwifi: mvm: freeze the non-shared queues when a station goes to sleep
When a station goes to sleep, we can't transmit any frame to it. This means that until that station will wake up, a queue that is dedicated to this station won't progress at all. Take this into account when monitoring stuck queues and don't account for the time the station was asleep. This allows to mask false positives where the queues are stuck not because of a bug, but because of the station being asleep. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 7eab892de29b..6b3f4d0284a7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -2427,25 +2427,35 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
2427{ 2427{
2428 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2428 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2429 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 2429 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
2430 unsigned long txqs = 0, tids = 0;
2430 int tid; 2431 int tid;
2431 2432
2433 spin_lock_bh(&mvmsta->lock);
2434 for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
2435 struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
2436
2437 if (tid_data->state != IWL_AGG_ON &&
2438 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
2439 continue;
2440
2441 __set_bit(tid_data->txq_id, &txqs);
2442
2443 if (iwl_mvm_tid_queued(tid_data) == 0)
2444 continue;
2445
2446 __set_bit(tid, &tids);
2447 }
2448
2432 switch (cmd) { 2449 switch (cmd) {
2433 case STA_NOTIFY_SLEEP: 2450 case STA_NOTIFY_SLEEP:
2434 if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) 2451 if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0)
2435 ieee80211_sta_block_awake(hw, sta, true); 2452 ieee80211_sta_block_awake(hw, sta, true);
2436 spin_lock_bh(&mvmsta->lock);
2437 for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
2438 struct iwl_mvm_tid_data *tid_data;
2439 2453
2440 tid_data = &mvmsta->tid_data[tid]; 2454 for_each_set_bit(tid, &tids, IWL_MAX_TID_COUNT)
2441 if (tid_data->state != IWL_AGG_ON &&
2442 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
2443 continue;
2444 if (iwl_mvm_tid_queued(tid_data) == 0)
2445 continue;
2446 ieee80211_sta_set_buffered(sta, tid, true); 2455 ieee80211_sta_set_buffered(sta, tid, true);
2447 } 2456
2448 spin_unlock_bh(&mvmsta->lock); 2457 if (txqs)
2458 iwl_trans_freeze_txq_timer(mvm->trans, txqs, true);
2449 /* 2459 /*
2450 * The fw updates the STA to be asleep. Tx packets on the Tx 2460 * The fw updates the STA to be asleep. Tx packets on the Tx
2451 * queues to this station will not be transmitted. The fw will 2461 * queues to this station will not be transmitted. The fw will
@@ -2455,11 +2465,15 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
2455 case STA_NOTIFY_AWAKE: 2465 case STA_NOTIFY_AWAKE:
2456 if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) 2466 if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
2457 break; 2467 break;
2468
2469 if (txqs)
2470 iwl_trans_freeze_txq_timer(mvm->trans, txqs, false);
2458 iwl_mvm_sta_modify_ps_wake(mvm, sta); 2471 iwl_mvm_sta_modify_ps_wake(mvm, sta);
2459 break; 2472 break;
2460 default: 2473 default:
2461 break; 2474 break;
2462 } 2475 }
2476 spin_unlock_bh(&mvmsta->lock);
2463} 2477}
2464 2478
2465static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, 2479static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,