iwlagn: used frame count info in compressed ba packet
authorWey-Yi Guy <wey-yi.w.guy@intel.com>
Wed, 10 Nov 2010 19:05:38 +0000 (11:05 -0800)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Tue, 16 Nov 2010 15:43:42 +0000 (07:43 -0800)
For newer devices, uCode provide both "number of frames sent"
and "number of frames acked" information inside the compressed_ba
packet. So instead of figure the success/failure information through
the bitmap, use those information which is much betrer approach.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.h

index 4748d067eb1dd577759b9061c128d521bfb0b2ce..a172bd171a0c854dceaab6643a41d0d9d0a757b5 100644 (file)
@@ -2620,6 +2620,7 @@ static struct iwl_base_params iwl4965_base_params = {
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
+       .no_agg_framecnt_info = true,
 };
 
 struct iwl_cfg iwl4965_agn_cfg = {
index 2b078a995729a0bbaa2ccc311fea83fa74bb7e19..522c77f23e04dcf3571dcfc7f6014eef18f26752 100644 (file)
@@ -1241,37 +1241,61 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
        if (sh < 0) /* tbw something is wrong with indices */
                sh += 0x100;
 
-       /* don't use 64-bit values for now */
-       bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
-
        if (agg->frame_count > (64 - sh)) {
                IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
                return -1;
        }
-
-       /* check for success or failure according to the
-        * transmitted bitmap and block-ack bitmap */
-       sent_bitmap = bitmap & agg->bitmap;
-
-       /* For each frame attempted in aggregation,
-        * update driver's record of tx frame's status. */
-       i = 0;
-       while (sent_bitmap) {
-               ack = sent_bitmap & 1ULL;
-               successes += ack;
-               IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
-                       ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
-                       agg->start_idx + i);
-               sent_bitmap >>= 1;
-               ++i;
+       if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
+               /*
+                * sent and ack information provided by uCode
+                * use it instead of figure out ourself
+                */
+               if (ba_resp->txed_2_done > ba_resp->txed) {
+                       IWL_DEBUG_TX_REPLY(priv,
+                               "bogus sent(%d) and ack(%d) count\n",
+                               ba_resp->txed, ba_resp->txed_2_done);
+                       /*
+                        * set txed_2_done = txed,
+                        * so it won't impact rate scale
+                        */
+                       ba_resp->txed = ba_resp->txed_2_done;
+               }
+               IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
+                               ba_resp->txed, ba_resp->txed_2_done);
+       } else {
+               /* don't use 64-bit values for now */
+               bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+
+               /* check for success or failure according to the
+                * transmitted bitmap and block-ack bitmap */
+               sent_bitmap = bitmap & agg->bitmap;
+
+               /* For each frame attempted in aggregation,
+                * update driver's record of tx frame's status. */
+               i = 0;
+               while (sent_bitmap) {
+                       ack = sent_bitmap & 1ULL;
+                       successes += ack;
+                       IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
+                               ack ? "ACK" : "NACK", i,
+                               (agg->start_idx + i) & 0xff,
+                               agg->start_idx + i);
+                       sent_bitmap >>= 1;
+                       ++i;
+               }
        }
-
        info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
        memset(&info->status, 0, sizeof(info->status));
        info->flags |= IEEE80211_TX_STAT_ACK;
        info->flags |= IEEE80211_TX_STAT_AMPDU;
-       info->status.ampdu_ack_len = successes;
-       info->status.ampdu_len = agg->frame_count;
+       if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
+               info->status.ampdu_ack_len = ba_resp->txed_2_done;
+               info->status.ampdu_len = ba_resp->txed;
+
+       } else {
+               info->status.ampdu_ack_len = successes;
+               info->status.ampdu_len = agg->frame_count;
+       }
        iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
 
        IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);
index 424801abc80eae92a5d39a777c08a73baf13c7a6..31c29a5fe8b1b1ad01d177c225d4df685c00db6f 100644 (file)
@@ -2022,6 +2022,9 @@ struct iwl_compressed_ba_resp {
        __le64 bitmap;
        __le16 scd_flow;
        __le16 scd_ssn;
+       /* following only for 5000 series and up */
+       u8 txed;        /* number of frames sent */
+       u8 txed_2_done; /* number of frames acked */
 } __packed;
 
 /*
index ee8cf240d65d9a1ff6a90c6a8bc1e744bebf1454..98b79f62772088a478531a5519edd89cebb1a3bf 100644 (file)
@@ -291,7 +291,9 @@ struct iwl_mod_params {
  * @chain_noise_calib_by_driver: driver has the capability to perform
  *     chain noise calibration operation
  * @shadow_reg_enable: HW shadhow register bit
-*/
+ * @no_agg_framecnt_info: uCode do not provide aggregation frame count
+ *     information
+ */
 struct iwl_base_params {
        int eeprom_size;
        int num_of_queues;      /* def: HW dependent */
@@ -322,6 +324,7 @@ struct iwl_base_params {
        const bool sensitivity_calib_by_driver;
        const bool chain_noise_calib_by_driver;
        const bool shadow_reg_enable;
+       const bool no_agg_framecnt_info;
 };
 /*
  * @advanced_bt_coexist: support advanced bt coexist