diff options
author | Trieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com> | 2010-02-10 13:27:34 -0500 |
---|---|---|
committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-02-11 13:27:41 -0500 |
commit | 1db5950f1d0b82e07371b211a48317b8972da063 (patch) | |
tree | 6fc4f38f2c8cfd3a212c5eb18e326dd5d409ca2c /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | a9e10fb9b1c6ad16e73cf2656951fce3a817611e (diff) |
iwlwifi: Monitor and recover the aggregation TX flow failure
This change monitors the tx statistics to detect the drop in throughput.
When the throughput drops, the ratio of the actual_ack_count and the expected_
ack_count also drops. At the same time, the aggregated ba_timeout (the number
of ba timeout retries) also rises. If the actual_ack_count/expected_ack_count
ratio is 0 and the number of ba timeout retries rises to 16, no tx packets
(tcp, udp, or ping - icmp) can be delivered. The driver recovers from this
situation by reseting the uCode firmware. If the actual_ack_count/expected_
ack_count ratio drops below 50% (but not 0) and the aggregated ba_timeout
retries just exceed 5 (but not 16), then the driver can reset the radio to
bring the throughput up.
Signed-off-by: Trieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 31b156d58d7f..4157c6c8645f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2941 | return ret; | 2941 | return ret; |
2942 | case IEEE80211_AMPDU_TX_START: | 2942 | case IEEE80211_AMPDU_TX_START: |
2943 | IWL_DEBUG_HT(priv, "start Tx\n"); | 2943 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2944 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 2944 | ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); |
2945 | if (ret == 0) { | ||
2946 | priv->agg_tids_count++; | ||
2947 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2948 | priv->agg_tids_count); | ||
2949 | } | ||
2950 | return ret; | ||
2945 | case IEEE80211_AMPDU_TX_STOP: | 2951 | case IEEE80211_AMPDU_TX_STOP: |
2946 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 2952 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2947 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); | 2953 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); |
2954 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | ||
2955 | priv->agg_tids_count--; | ||
2956 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2957 | priv->agg_tids_count); | ||
2958 | } | ||
2948 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2959 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2949 | return 0; | 2960 | return 0; |
2950 | else | 2961 | else |
@@ -3364,6 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3364 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3375 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3365 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | 3376 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; |
3366 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3377 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3378 | priv->agg_tids_count = 0; | ||
3367 | 3379 | ||
3368 | /* Choose which receivers/antennas to use */ | 3380 | /* Choose which receivers/antennas to use */ |
3369 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3381 | if (priv->cfg->ops->hcmd->set_rxon_chain) |