* packets.
  */
 static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
-                             int scale_index, s32 tpt, u32 status)
+                             int scale_index, s32 tpt, int retries,
+                             int successes)
 {
        struct iwl4965_rate_scale_data *window = NULL;
        u64 mask;
         * subtract "1" from the success counter (this is the main reason
         * we keep these bitmaps!).
         */
-       if (window->counter >= win_size) {
-               window->counter = win_size - 1;
-               mask = 1;
-               mask = (mask << (win_size - 1));
-               if ((window->data & mask)) {
-                       window->data &= ~mask;
-                       window->success_counter = window->success_counter - 1;
+       while (retries > 0) {
+               if (window->counter >= win_size) {
+                       window->counter = win_size - 1;
+                       mask = 1;
+                       mask = (mask << (win_size - 1));
+                       if (window->data & mask) {
+                               window->data &= ~mask;
+                               window->success_counter =
+                                       window->success_counter - 1;
+                       }
                }
-       }
 
-       /* Increment frames-attempted counter */
-       window->counter = window->counter + 1;
+               /* Increment frames-attempted counter */
+               window->counter++;
+
+               /* Shift bitmap by one frame (throw away oldest history),
+                * OR in "1", and increment "success" if this
+                * frame was successful. */
+               mask = window->data;
+               window->data = (mask << 1);
+               if (successes > 0) {
+                       window->success_counter = window->success_counter + 1;
+                       window->data |= 0x1;
+                       successes--;
+               }
 
-       /* Shift bitmap by one frame (throw away oldest history),
-        * OR in "1", and increment "success" if this frame was successful. */
-       mask = window->data;
-       window->data = (mask << 1);
-       if (status != 0) {
-               window->success_counter = window->success_counter + 1;
-               window->data |= 0x1;
+               retries--;
        }
 
        /* Calculate current success ratio, avoid divide-by-0! */
        if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
                return;
 
+       /* This packet was aggregated but doesn't carry rate scale info */
+       if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) &&
+           !(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU))
+               return;
+
        retries = tx_resp->retry_count;
 
        if (retries > 15)
                                tpt = search_tbl->expected_tpt[rs_index];
                        else
                                tpt = 0;
-                       rs_collect_tx_data(search_win, rs_index, tpt, 0);
+                       rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
 
                /* Else if type matches "current/active" table,
                 * add failure to "current/active" history */
                                tpt = curr_tbl->expected_tpt[rs_index];
                        else
                                tpt = 0;
-                       rs_collect_tx_data(window, rs_index, tpt, 0);
+                       rs_collect_tx_data(window, rs_index, tpt, 1, 0);
                }
 
                /* If not searching for a new mode, increment failed counter
                        tpt = search_tbl->expected_tpt[rs_index];
                else
                        tpt = 0;
-               rs_collect_tx_data(search_win,
-                                   rs_index, tpt, status);
-
+               if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
+                       rs_collect_tx_data(search_win, rs_index, tpt,
+                                          tx_resp->ampdu_ack_len,
+                                          tx_resp->ampdu_ack_map);
+               else
+                       rs_collect_tx_data(search_win, rs_index, tpt,
+                                          1, status);
        /* Else if type matches "current/active" table,
         * add final tx status to "current/active" history */
        } else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
                        tpt = curr_tbl->expected_tpt[rs_index];
                else
                        tpt = 0;
-               rs_collect_tx_data(window, rs_index, tpt, status);
+               if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
+                       rs_collect_tx_data(window, rs_index, tpt,
+                                          tx_resp->ampdu_ack_len,
+                                          tx_resp->ampdu_ack_map);
+               else
+                       rs_collect_tx_data(window, rs_index, tpt,
+                                          1, status);
        }
 
        /* If not searching for new mode, increment success/failed counter
         * ... these help determine when to start searching again */
        if (lq_sta->stay_in_tbl) {
-               if (status)
-                       lq_sta->total_success++;
-               else
-                       lq_sta->total_failed++;
+               if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) {
+                       lq_sta->total_success += tx_resp->ampdu_ack_map;
+                       lq_sta->total_failed +=
+                            (tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map);
+               } else {
+                       if (status)
+                               lq_sta->total_success++;
+                       else
+                               lq_sta->total_failed++;
+               }
        }
 
        /* See if there's a better rate or modulation mode to try. */