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>
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 31b156d..4157c6c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2941,10 +2941,21 @@
 			return ret;
 	case IEEE80211_AMPDU_TX_START:
 		IWL_DEBUG_HT(priv, "start Tx\n");
-		return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
+		ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
+		if (ret == 0) {
+			priv->agg_tids_count++;
+			IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+				priv->agg_tids_count);
+		}
+		return ret;
 	case IEEE80211_AMPDU_TX_STOP:
 		IWL_DEBUG_HT(priv, "stop Tx\n");
 		ret = iwl_tx_agg_stop(priv, sta->addr, tid);
+		if ((ret == 0) && (priv->agg_tids_count > 0)) {
+			priv->agg_tids_count--;
+			IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
+				priv->agg_tids_count);
+		}
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 			return 0;
 		else
@@ -3364,6 +3375,7 @@
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+	priv->agg_tids_count = 0;
 
 	/* Choose which receivers/antennas to use */
 	if (priv->cfg->ops->hcmd->set_rxon_chain)