Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / iwl-agn-tx.c
index b02125a..35a6b71 100644 (file)
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
-#include "iwl-sta.h"
 #include "iwl-io.h"
-#include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
 #include "iwl-trans.h"
 
-static inline int get_ac_from_tid(u16 tid)
-{
-       if (likely(tid < ARRAY_SIZE(tid_to_ac)))
-               return tid_to_ac[tid];
-
-       /* no support for TIDs 8-15 yet */
-       return -EINVAL;
-}
-
-static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id,
-                               int tid)
-{
-       if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
-           (IWLAGN_FIRST_AMPDU_QUEUE +
-               hw_params(priv).num_ampdu_queues <= txq_id)) {
-               IWL_WARN(priv,
-                       "queue number out of range: %d, must be %d to %d\n",
-                       txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
-                       IWLAGN_FIRST_AMPDU_QUEUE +
-                       hw_params(priv).num_ampdu_queues - 1);
-               return -EINVAL;
-       }
-
-       /* Modify device's station table to Tx this TID */
-       return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
-}
-
 static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
                                     struct ieee80211_tx_info *info,
                                     __le16 fc, __le32 *tx_flags)
@@ -140,8 +111,6 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
        tx_cmd->next_frame_len = 0;
 }
 
-#define RTS_DFAULT_RETRY_LIMIT         60
-
 static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
                                     struct iwl_tx_cmd *tx_cmd,
                                     struct ieee80211_tx_info *info,
@@ -153,17 +122,25 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
        u8 data_retry_limit;
        u8 rate_plcp;
 
-       /* Set retry limit on DATA packets and Probe Responses*/
-       if (ieee80211_is_probe_resp(fc))
-               data_retry_limit = 3;
-       else
-               data_retry_limit = IWLAGN_DEFAULT_TX_RETRY;
-       tx_cmd->data_retry_limit = data_retry_limit;
+       if (priv->shrd->wowlan) {
+               rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
+               data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
+       } else {
+               /* Set retry limit on RTS packets */
+               rts_retry_limit = IWLAGN_RTS_DFAULT_RETRY_LIMIT;
+
+               /* Set retry limit on DATA packets and Probe Responses*/
+               if (ieee80211_is_probe_resp(fc)) {
+                       data_retry_limit = IWLAGN_MGMT_DFAULT_RETRY_LIMIT;
+                       rts_retry_limit =
+                               min(data_retry_limit, rts_retry_limit);
+               } else if (ieee80211_is_back_req(fc))
+                       data_retry_limit = IWLAGN_BAR_DFAULT_RETRY_LIMIT;
+               else
+                       data_retry_limit = IWLAGN_DEFAULT_TX_RETRY;
+       }
 
-       /* Set retry limit on RTS packets */
-       rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
-       if (data_retry_limit < rts_retry_limit)
-               rts_retry_limit = data_retry_limit;
+       tx_cmd->data_retry_limit = data_retry_limit;
        tx_cmd->rts_retry_limit = rts_retry_limit;
 
        /* DATA packets will use the uCode station table for rate/antenna
@@ -278,14 +255,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        struct iwl_device_cmd *dev_cmd = NULL;
        struct iwl_tx_cmd *tx_cmd;
-       int txq_id;
 
-       u16 seq_number = 0;
        __le16 fc;
        u8 hdr_len;
        u16 len;
        u8 sta_id;
-       u8 tid = 0;
        unsigned long flags;
        bool is_agg = false;
 
@@ -330,7 +304,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                sta_priv = (void *)info->control.sta->drv_priv;
 
        if (sta_priv && sta_priv->asleep &&
-           (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+           (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
                /*
                 * This sends an asynchronous command to the device,
                 * but we can rely on it being processed before the
@@ -343,60 +317,19 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
        }
 
-       /*
-        * Send this frame after DTIM -- there's a special queue
-        * reserved for this for contexts that support AP mode.
-        */
-       if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
-               txq_id = ctx->mcast_queue;
-               /*
-                * The microcode will clear the more data
-                * bit in the last frame it transmits.
-                */
-               hdr->frame_control |=
-                       cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-       } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
-               txq_id = IWL_AUX_QUEUE;
-       else
-               txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
+       if (info->flags & IEEE80211_TX_CTL_AMPDU)
+               is_agg = true;
 
        /* irqs already disabled/saved above when locking priv->shrd->lock */
        spin_lock(&priv->shrd->sta_lock);
 
-       if (ieee80211_is_data_qos(fc)) {
-               u8 *qc = NULL;
-               struct iwl_tid_data *tid_data;
-               qc = ieee80211_get_qos_ctl(hdr);
-               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               tid_data = &priv->shrd->tid_data[sta_id][tid];
-
-               if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
-                       goto drop_unlock_sta;
-
-               seq_number = tid_data->seq_number;
-               seq_number &= IEEE80211_SCTL_SEQ;
-               hdr->seq_ctrl = hdr->seq_ctrl &
-                               cpu_to_le16(IEEE80211_SCTL_FRAG);
-               hdr->seq_ctrl |= cpu_to_le16(seq_number);
-               seq_number += 0x10;
-               /* aggregation is on for this <sta,tid> */
-               if (info->flags & IEEE80211_TX_CTL_AMPDU &&
-                   tid_data->agg.state == IWL_AGG_ON) {
-                       txq_id = tid_data->agg.txq_id;
-                       is_agg = true;
-               }
-       }
-
        dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);
 
        if (unlikely(!dev_cmd))
                goto drop_unlock_sta;
 
        memset(dev_cmd, 0, sizeof(*dev_cmd));
-       tx_cmd = &dev_cmd->cmd.tx;
-
-       /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdr_len);
+       tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
 
        /* Total # bytes to be transmitted */
        len = (u16)skb->len;
@@ -413,19 +346,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        iwl_update_stats(priv, true, fc, len);
 
+       memset(&info->status, 0, sizeof(info->status));
+
        info->driver_data[0] = ctx;
        info->driver_data[1] = dev_cmd;
 
-       if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id, fc, is_agg))
+       if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id))
                goto drop_unlock_sta;
 
-       if (ieee80211_is_data_qos(fc)) {
-               priv->shrd->tid_data[sta_id][tid].tfds_in_queue++;
-               if (!ieee80211_has_morefrags(fc))
-                       priv->shrd->tid_data[sta_id][tid].seq_number =
-                               seq_number;
-       }
-
        spin_unlock(&priv->shrd->sta_lock);
        spin_unlock_irqrestore(&priv->shrd->lock, flags);
 
@@ -450,30 +378,12 @@ drop_unlock_priv:
        return -1;
 }
 
-/*
- * Find first available (lowest unused) Tx Queue, mark it "active".
- * Called only when finding queue for aggregation.
- * Should never return anything < 7, because they should already
- * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
- */
-static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv)
-{
-       int txq_id;
-
-       for (txq_id = 0; txq_id < hw_params(priv).max_txq_num; txq_id++)
-               if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
-                       return txq_id;
-       return -1;
-}
-
 int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
+       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
        int sta_id;
-       int txq_id;
        int ret;
-       unsigned long flags;
-       struct iwl_tid_data *tid_data;
 
        IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n",
                     sta->addr, tid);
@@ -491,45 +401,21 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                return -ENXIO;
        }
 
-       txq_id = iwlagn_txq_ctx_activate_free(priv);
-       if (txq_id == -1) {
-               IWL_ERR(priv, "No free aggregation queue available\n");
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-       tid_data = &priv->shrd->tid_data[sta_id][tid];
-       *ssn = SEQ_TO_SN(tid_data->seq_number);
-       tid_data->agg.txq_id = txq_id;
-       iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id);
-       spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-
-       ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid);
+       ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
        if (ret)
                return ret;
 
-       spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-       tid_data = &priv->shrd->tid_data[sta_id][tid];
-       if (tid_data->tfds_in_queue == 0) {
-               IWL_DEBUG_HT(priv, "HW queue is empty\n");
-               tid_data->agg.state = IWL_AGG_ON;
-               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-       } else {
-               IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
-                            tid_data->tfds_in_queue);
-               tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
-       }
-       spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id,
+                                    tid, ssn);
+
        return ret;
 }
 
 int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta, u16 tid)
 {
-       int txq_id, sta_id, ssn;
-       struct iwl_tid_data *tid_data;
-       int write_ptr, read_ptr;
-       unsigned long flags;
+       int sta_id;
+       struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 
        sta_id = iwl_sta_id(sta);
 
@@ -538,98 +424,8 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
                return -ENXIO;
        }
 
-       spin_lock_irqsave(&priv->shrd->sta_lock, flags);
-
-       tid_data = &priv->shrd->tid_data[sta_id][tid];
-       ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
-       txq_id = tid_data->agg.txq_id;
-
-       switch (priv->shrd->tid_data[sta_id][tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /*
-                * This can happen if the peer stops aggregation
-                * again before we've had a chance to drain the
-                * queue we selected previously, i.e. before the
-                * session was really started completely.
-                */
-               IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
-               goto turn_off;
-       case IWL_AGG_ON:
-               break;
-       default:
-               IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
-       }
-
-       write_ptr = priv->txq[txq_id].q.write_ptr;
-       read_ptr = priv->txq[txq_id].q.read_ptr;
-
-       /* The queue is not empty */
-       if (write_ptr != read_ptr) {
-               IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
-               priv->shrd->tid_data[sta_id][tid].agg.state =
-                               IWL_EMPTYING_HW_QUEUE_DELBA;
-               spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return 0;
-       }
-
-       IWL_DEBUG_HT(priv, "HW queue is empty\n");
- turn_off:
-       priv->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
-
-       /* do not restore/save irqs */
-       spin_unlock(&priv->shrd->sta_lock);
-       spin_lock(&priv->shrd->lock);
-
-       /*
-        * the only reason this call can fail is queue number out of range,
-        * which can happen if uCode is reloaded and all the station
-        * information are lost. if it is outside the range, there is no need
-        * to deactivate the uCode queue, just return "success" to allow
-        *  mac80211 to clean up it own data.
-        */
-       iwl_trans_txq_agg_disable(trans(priv), txq_id);
-       spin_unlock_irqrestore(&priv->shrd->lock, flags);
-
-       ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-
-       return 0;
-}
-
-static int iwlagn_txq_check_empty(struct iwl_priv *priv,
-                          int sta_id, u8 tid, int txq_id)
-{
-       struct iwl_queue *q = &priv->txq[txq_id].q;
-       u8 *addr = priv->stations[sta_id].sta.sta.addr;
-       struct iwl_tid_data *tid_data = &priv->shrd->tid_data[sta_id][tid];
-       struct iwl_rxon_context *ctx;
-
-       ctx = &priv->contexts[priv->stations[sta_id].ctxid];
-
-       lockdep_assert_held(&priv->shrd->sta_lock);
-
-       switch (priv->shrd->tid_data[sta_id][tid].agg.state) {
-       case IWL_EMPTYING_HW_QUEUE_DELBA:
-               /* We are reclaiming the last packet of the */
-               /* aggregated HW queue */
-               if ((txq_id  == tid_data->agg.txq_id) &&
-                   (q->read_ptr == q->write_ptr)) {
-                       IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
-                       iwl_trans_txq_agg_disable(trans(priv), txq_id);
-                       tid_data->agg.state = IWL_AGG_OFF;
-                       ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
-               }
-               break;
-       case IWL_EMPTYING_HW_QUEUE_ADDBA:
-               /* We are reclaiming the last packet of the queue */
-               if (tid_data->tfds_in_queue == 0) {
-                       IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
-                       tid_data->agg.state = IWL_AGG_ON;
-                       ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
-               }
-               break;
-       }
-
-       return 0;
+       return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid,
+                                       sta_id, tid);
 }
 
 static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
@@ -790,6 +586,9 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
                IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
        }
 
+       if (tx_resp->frame_count == 1)
+               return;
+
        /* Construct bit-map of pending frames within Tx window */
        for (i = 0; i < tx_resp->frame_count; i++) {
                u16 fstatus = le16_to_cpu(frame_status[i].status);
@@ -842,21 +641,6 @@ static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
                            tx_resp->frame_count) & MAX_SN;
 }
 
-static void iwl_free_tfds_in_queue(struct iwl_priv *priv,
-                           int sta_id, int tid, int freed)
-{
-       lockdep_assert_held(&priv->shrd->sta_lock);
-
-       if (priv->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
-               priv->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
-       else {
-               IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
-                       priv->shrd->tid_data[sta_id][tid].tfds_in_queue,
-                       freed);
-               priv->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
-       }
-}
-
 static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
 {
        status &= TX_STATUS_MSK;
@@ -961,13 +745,13 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
        }
 }
 
-void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
        int txq_id = SEQ_TO_QUEUE(sequence);
-       int cmd_index = SEQ_TO_INDEX(sequence);
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
+       int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
        struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
        struct ieee80211_hdr *hdr;
        u32 status = le16_to_cpu(tx_resp->status.status);
@@ -980,17 +764,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
        struct sk_buff_head skbs;
        struct sk_buff *skb;
        struct iwl_rxon_context *ctx;
-
-       if ((cmd_index >= txq->q.n_bd) ||
-           (iwl_queue_used(&txq->q, cmd_index) == 0)) {
-               IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) "
-                         "cmd_index %d is out of range [0-%d] %d %d\n",
-                         __func__, txq_id, cmd_index, txq->q.n_bd,
-                         txq->q.write_ptr, txq->q.read_ptr);
-               return;
-       }
-
-       txq->time_stamp = jiffies;
+       bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
 
        tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
                IWLAGN_TX_RES_TID_POS;
@@ -999,15 +773,14 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 
        spin_lock_irqsave(&priv->shrd->sta_lock, flags);
 
-       if (txq->sched_retry)
+       if (is_agg)
                iwl_rx_reply_tx_agg(priv, tx_resp);
 
        if (tx_resp->frame_count == 1) {
-               bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
-
                __skb_queue_head_init(&skbs);
                /*we can free until ssn % q.n_bd not inclusive */
-               iwl_trans_reclaim(trans(priv), txq_id, ssn, status, &skbs);
+               iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
+                                 ssn, status, &skbs);
                freed = 0;
                while (!skb_queue_empty(&skbs)) {
                        skb = __skb_dequeue(&skbs);
@@ -1027,7 +800,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
                            iwl_is_associated_ctx(ctx) && ctx->vif &&
                            ctx->vif->type == NL80211_IFTYPE_STATION) {
                                ctx->last_tx_rejected = true;
-                               iwl_stop_queue(priv, &priv->txq[txq_id]);
+                               iwl_trans_stop_queue(trans(priv), txq_id);
 
                                IWL_DEBUG_TX_REPLY(priv,
                                           "TXQ %d status %s (0x%08x) "
@@ -1057,13 +830,11 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
                }
 
                WARN_ON(!is_agg && freed != 1);
-
-               iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-               iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
        }
 
        iwl_check_abort_status(priv, tx_resp->frame_count, status);
        spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       return 0;
 }
 
 /**
@@ -1072,19 +843,18 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
  * Handles block-acknowledge notification from device, which reports success
  * of frames sent via aggregation.
  */
-void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
-                                          struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+                                  struct iwl_rx_mem_buffer *rxb,
+                                  struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
-       struct iwl_tx_queue *txq = NULL;
        struct iwl_ht_agg *agg;
        struct sk_buff_head reclaimed_skbs;
        struct ieee80211_tx_info *info;
        struct ieee80211_hdr *hdr;
        struct sk_buff *skb;
        unsigned long flags;
-       int index;
        int sta_id;
        int tid;
        int freed;
@@ -1099,17 +869,13 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        if (scd_flow >= hw_params(priv).max_txq_num) {
                IWL_ERR(priv,
                        "BUG_ON scd_flow is bigger than number of queues\n");
-               return;
+               return 0;
        }
 
-       txq = &priv->txq[scd_flow];
        sta_id = ba_resp->sta_id;
        tid = ba_resp->tid;
        agg = &priv->shrd->tid_data[sta_id][tid].agg;
 
-       /* Find index of block-ack window */
-       index = ba_resp_scd_ssn & (txq->q.n_bd - 1);
-
        spin_lock_irqsave(&priv->shrd->sta_lock, flags);
 
        if (unlikely(agg->txq_id != scd_flow)) {
@@ -1123,14 +889,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                        "BA scd_flow %d does not match txq_id %d\n",
                        scd_flow, agg->txq_id);
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return;
+               return 0;
        }
 
        if (unlikely(!agg->wait_for_ba)) {
                if (unlikely(ba_resp->bitmap))
                        IWL_ERR(priv, "Received BA when not expected\n");
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return;
+               return 0;
        }
 
        IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
@@ -1147,7 +913,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                           ba_resp->scd_ssn);
 
        /* Mark that the expected block-ack response arrived */
-       agg->wait_for_ba = 0;
+       agg->wait_for_ba = false;
 
        /* Sanity check values reported by uCode */
        if (ba_resp->txed_2_done > ba_resp->txed) {
@@ -1168,8 +934,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        /* Release all TFDs before the SSN, i.e. all TFDs in front of
         * block-ack window (we assume that they've been successfully
         * transmitted ... if not, it's too late anyway). */
-       iwl_trans_reclaim(trans(priv), scd_flow, ba_resp_scd_ssn, 0,
-                         &reclaimed_skbs);
+       iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn,
+                         0, &reclaimed_skbs);
        freed = 0;
        while (!skb_queue_empty(&reclaimed_skbs)) {
 
@@ -1181,7 +947,10 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                else
                        WARN_ON_ONCE(1);
 
-               if (freed == 0) {
+               info = IEEE80211_SKB_CB(skb);
+               kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+
+               if (freed == 1) {
                        /* this is the first skb we deliver in this batch */
                        /* put the rate scaling data there */
                        info = IEEE80211_SKB_CB(skb);
@@ -1194,14 +963,9 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                                                    info);
                }
 
-               info = IEEE80211_SKB_CB(skb);
-               kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
-
                ieee80211_tx_status_irqsafe(priv->hw, skb);
        }
 
-       iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-       iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
-
        spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       return 0;
 }