]> Pileus Git - ~andy/linux/blobdiff - drivers/net/wireless/iwlwifi/iwl-agn-tx.c
iwlagn: separate and enhance the fixed rate from
[~andy/linux] / drivers / net / wireless / iwlwifi / iwl-agn-tx.c
index 0712b67283a4f7e1b4a4ae702623ba32fd61a933..07c1242599f726cfa203ad9193a54cafefc70499 100644 (file)
@@ -2,7 +2,7 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -98,9 +98,9 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
 /**
  * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
  */
-void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
-                                           struct iwl_tx_queue *txq,
-                                           u16 byte_cnt)
+static void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+                                          struct iwl_tx_queue *txq,
+                                          u16 byte_cnt)
 {
        struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
        int write_ptr = txq->q.write_ptr;
@@ -112,21 +112,19 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
 
        WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
 
-       if (txq_id != priv->cmd_queue) {
-               sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
-               sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
-
-               switch (sec_ctl & TX_CMD_SEC_MSK) {
-               case TX_CMD_SEC_CCM:
-                       len += CCMP_MIC_LEN;
-                       break;
-               case TX_CMD_SEC_TKIP:
-                       len += TKIP_ICV_LEN;
-                       break;
-               case TX_CMD_SEC_WEP:
-                       len += WEP_IV_LEN + WEP_ICV_LEN;
-                       break;
-               }
+       sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
+       sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
+
+       switch (sec_ctl & TX_CMD_SEC_MSK) {
+       case TX_CMD_SEC_CCM:
+               len += CCMP_MIC_LEN;
+               break;
+       case TX_CMD_SEC_TKIP:
+               len += TKIP_ICV_LEN;
+               break;
+       case TX_CMD_SEC_WEP:
+               len += WEP_IV_LEN + WEP_ICV_LEN;
+               break;
        }
 
        bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
@@ -138,8 +136,8 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
                        tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 
-void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
-                                          struct iwl_tx_queue *txq)
+static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
+                                         struct iwl_tx_queue *txq)
 {
        struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
        int txq_id = txq->q.id;
@@ -222,13 +220,8 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
                       scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id);
 }
 
-int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
-                         int tx_fifo, int sta_id, int tid, u16 ssn_idx)
+static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, int tid)
 {
-       unsigned long flags;
-       u16 ra_tid;
-       int ret;
-
        if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWLAGN_FIRST_AMPDU_QUEUE +
                priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
@@ -240,12 +233,33 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
                return -EINVAL;
        }
 
-       ra_tid = BUILD_RAxTID(sta_id, tid);
-
        /* Modify device's station table to Tx this TID */
-       ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
-       if (ret)
-               return ret;
+       return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+}
+
+void iwlagn_txq_agg_queue_setup(struct iwl_priv *priv,
+                               struct ieee80211_sta *sta,
+                               int tid, int frame_limit)
+{
+       int sta_id, tx_fifo, txq_id, ssn_idx;
+       u16 ra_tid;
+       unsigned long flags;
+       struct iwl_tid_data *tid_data;
+
+       sta_id = iwl_sta_id(sta);
+       if (WARN_ON(sta_id == IWL_INVALID_STATION))
+               return;
+       if (WARN_ON(tid >= MAX_TID_COUNT))
+               return;
+
+       spin_lock_irqsave(&priv->sta_lock, flags);
+       tid_data = &priv->stations[sta_id].tid[tid];
+       ssn_idx = SEQ_TO_SN(tid_data->seq_number);
+       txq_id = tid_data->agg.txq_id;
+       tx_fifo = tid_data->agg.tx_fifo;
+       spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+       ra_tid = BUILD_RAxTID(sta_id, tid);
 
        spin_lock_irqsave(&priv->lock, flags);
 
@@ -271,10 +285,10 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
        iwl_write_targ_mem(priv, priv->scd_base_addr +
                        IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
                        sizeof(u32),
-                       ((SCD_WIN_SIZE <<
+                       ((frame_limit <<
                        IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
                        IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
-                       ((SCD_FRAME_LIMIT <<
+                       ((frame_limit <<
                        IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
                        IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
 
@@ -284,12 +298,10 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
        iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
 
        spin_unlock_irqrestore(&priv->lock, flags);
-
-       return 0;
 }
 
-int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
-                          u16 ssn_idx, u8 tx_fifo)
+static int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+                                 u16 ssn_idx, u8 tx_fifo)
 {
        if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
            (IWLAGN_FIRST_AMPDU_QUEUE +
@@ -424,6 +436,16 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
        if (ieee80211_is_data(fc)) {
                tx_cmd->initial_rate_index = 0;
                tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+               if (priv->tm_fixed_rate) {
+                       /*
+                        * rate overwrite by testmode
+                        * we not only send lq command to change rate
+                        * we also re-enforce per data pkt base.
+                        */
+                       tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK;
+                       memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate,
+                              sizeof(tx_cmd->rate_n_flags));
+               }
                return;
        }
 
@@ -485,8 +507,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
 
        case WLAN_CIPHER_SUITE_TKIP:
                tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
-               ieee80211_get_tkip_key(keyconf, skb_frag,
-                       IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+               ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
                IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
                break;
 
@@ -525,7 +546,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        struct iwl_tx_cmd *tx_cmd;
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        int txq_id;
-       dma_addr_t phys_addr;
+       dma_addr_t phys_addr = 0;
        dma_addr_t txcmd_phys;
        dma_addr_t scratch_phys;
        u16 len, firstlen, secondlen;
@@ -552,7 +573,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        spin_lock_irqsave(&priv->lock, flags);
        if (iwl_is_rfkill(priv)) {
                IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
-               goto drop_unlock;
+               goto drop_unlock_priv;
        }
 
        fc = hdr->frame_control;
@@ -577,7 +598,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                if (sta_id == IWL_INVALID_STATION) {
                        IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
                                       hdr->addr1);
-                       goto drop_unlock;
+                       goto drop_unlock_priv;
                }
        }
 
@@ -621,10 +642,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (ieee80211_is_data_qos(fc)) {
                qc = ieee80211_get_qos_ctl(hdr);
                tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-               if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
-                       spin_unlock(&priv->sta_lock);
-                       goto drop_unlock;
-               }
+
+               if (WARN_ON_ONCE(tid >= MAX_TID_COUNT))
+                       goto drop_unlock_sta;
+
                seq_number = priv->stations[sta_id].tid[tid].seq_number;
                seq_number &= IEEE80211_SCTL_SEQ;
                hdr->seq_ctrl = hdr->seq_ctrl &
@@ -642,18 +663,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        txq = &priv->txq[txq_id];
        q = &txq->q;
 
-       if (unlikely(iwl_queue_space(q) < q->high_mark)) {
-               spin_unlock(&priv->sta_lock);
-               goto drop_unlock;
-       }
-
-       if (ieee80211_is_data_qos(fc)) {
-               priv->stations[sta_id].tid[tid].tfds_in_queue++;
-               if (!ieee80211_has_morefrags(fc))
-                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
-       }
-
-       spin_unlock(&priv->sta_lock);
+       if (unlikely(iwl_queue_space(q) < q->high_mark))
+               goto drop_unlock_sta;
 
        /* Set up driver data for this TFD */
        memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
@@ -714,15 +725,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
+       txcmd_phys = dma_map_single(priv->bus.dev,
                                    &out_cmd->hdr, firstlen,
-                                   PCI_DMA_BIDIRECTIONAL);
+                                   DMA_BIDIRECTIONAL);
+       if (unlikely(dma_mapping_error(priv->bus.dev, txcmd_phys)))
+               goto drop_unlock_sta;
        dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
        dma_unmap_len_set(out_meta, len, firstlen);
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  txcmd_phys, firstlen, 1, 0);
 
        if (!ieee80211_has_morefrags(hdr->frame_control)) {
                txq->need_update = 1;
@@ -735,19 +744,37 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
         * if any (802.11 null frames have no payload). */
        secondlen = skb->len - hdr_len;
        if (secondlen > 0) {
-               phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-                                          secondlen, PCI_DMA_TODEVICE);
-               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                          phys_addr, secondlen,
-                                                          0, 0);
+               phys_addr = dma_map_single(priv->bus.dev, skb->data + hdr_len,
+                                          secondlen, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) {
+                       dma_unmap_single(priv->bus.dev,
+                                        dma_unmap_addr(out_meta, mapping),
+                                        dma_unmap_len(out_meta, len),
+                                        DMA_BIDIRECTIONAL);
+                       goto drop_unlock_sta;
+               }
        }
 
+       if (ieee80211_is_data_qos(fc)) {
+               priv->stations[sta_id].tid[tid].tfds_in_queue++;
+               if (!ieee80211_has_morefrags(fc))
+                       priv->stations[sta_id].tid[tid].seq_number = seq_number;
+       }
+
+       spin_unlock(&priv->sta_lock);
+
+       /* Attach buffers to TFD */
+       iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1);
+       if (secondlen > 0)
+               iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
+                                            secondlen, 0);
+
        scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
                                offsetof(struct iwl_tx_cmd, scratch);
 
        /* take back ownership of DMA buffer to enable update */
-       pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
-                                   firstlen, PCI_DMA_BIDIRECTIONAL);
+       dma_sync_single_for_cpu(priv->bus.dev, txcmd_phys, firstlen,
+                       DMA_BIDIRECTIONAL);
        tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
        tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
 
@@ -759,11 +786,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Set up entry for this TFD in Tx byte-count array */
        if (info->flags & IEEE80211_TX_CTL_AMPDU)
-               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
-                                                    le16_to_cpu(tx_cmd->len));
+               iwlagn_txq_update_byte_cnt_tbl(priv, txq,
+                                              le16_to_cpu(tx_cmd->len));
 
-       pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
-                                      firstlen, PCI_DMA_BIDIRECTIONAL);
+       dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen,
+                       DMA_BIDIRECTIONAL);
 
        trace_iwlwifi_dev_tx(priv,
                             &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
@@ -806,183 +833,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        return 0;
 
-drop_unlock:
+drop_unlock_sta:
+       spin_unlock(&priv->sta_lock);
+drop_unlock_priv:
        spin_unlock_irqrestore(&priv->lock, flags);
        return -1;
 }
 
-static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
-                                   struct iwl_dma_ptr *ptr, size_t size)
-{
-       ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
-                                      GFP_KERNEL);
-       if (!ptr->addr)
-               return -ENOMEM;
-       ptr->size = size;
-       return 0;
-}
-
-static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
-                                   struct iwl_dma_ptr *ptr)
-{
-       if (unlikely(!ptr->addr))
-               return;
-
-       dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
-       memset(ptr, 0, sizeof(*ptr));
-}
-
-/**
- * iwlagn_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
-{
-       int txq_id;
-
-       /* Tx queues */
-       if (priv->txq) {
-               for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-                       if (txq_id == priv->cmd_queue)
-                               iwl_cmd_queue_free(priv);
-                       else
-                               iwl_tx_queue_free(priv, txq_id);
-       }
-       iwlagn_free_dma_ptr(priv, &priv->kw);
-
-       iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
-
-       /* free tx queue structure */
-       iwl_free_txq_mem(priv);
-}
-
-/**
- * iwlagn_txq_ctx_alloc - allocate TX queue context
- * Allocate all Tx DMA structures and initialize them
- *
- * @param priv
- * @return error code
- */
-int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
-{
-       int ret;
-       int txq_id, slots_num;
-       unsigned long flags;
-
-       /* Free all tx/cmd queues and keep-warm buffer */
-       iwlagn_hw_txq_ctx_free(priv);
-
-       ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
-                               priv->hw_params.scd_bc_tbls_size);
-       if (ret) {
-               IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
-               goto error_bc_tbls;
-       }
-       /* Alloc keep-warm buffer */
-       ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
-       if (ret) {
-               IWL_ERR(priv, "Keep Warm allocation failed\n");
-               goto error_kw;
-       }
-
-       /* allocate tx queue structure */
-       ret = iwl_alloc_txq_mem(priv);
-       if (ret)
-               goto error;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Turn off all Tx DMA fifos */
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
-
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* Alloc and init all Tx queues, including the command queue (#4/#9) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = (txq_id == priv->cmd_queue) ?
-                                       TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-                                      txq_id);
-               if (ret) {
-                       IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-                       goto error;
-               }
-       }
-
-       return ret;
-
- error:
-       iwlagn_hw_txq_ctx_free(priv);
-       iwlagn_free_dma_ptr(priv, &priv->kw);
- error_kw:
-       iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
- error_bc_tbls:
-       return ret;
-}
-
-void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
-{
-       int txq_id, slots_num;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       /* Turn off all Tx DMA fifos */
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
-
-       /* Tell NIC where to find the "keep warm" buffer */
-       iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* Alloc and init all Tx queues, including the command queue (#4) */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-               slots_num = txq_id == priv->cmd_queue ?
-                           TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-               iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
-       }
-}
-
-/**
- * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
- */
-void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
-{
-       int ch, txq_id;
-       unsigned long flags;
-
-       /* Turn off all Tx DMA fifos */
-       spin_lock_irqsave(&priv->lock, flags);
-
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
-
-       /* Stop each Tx DMA channel, and wait for it to be idle */
-       for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
-               iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
-               if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
-                                   FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
-                                   1000))
-                       IWL_ERR(priv, "Failing on timeout while stopping"
-                           " DMA channel %d [0x%08x]", ch,
-                           iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (!priv->txq)
-               return;
-
-       /* Unmap DMA from host system and free skb's */
-       for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
-               if (txq_id == priv->cmd_queue)
-                       iwl_cmd_queue_unmap(priv);
-               else
-                       iwl_tx_queue_unmap(priv, txq_id);
-}
-
 /*
  * Find first available (lowest unused) Tx Queue, mark it "active".
  * Called only when finding queue for aggregation.
@@ -1013,8 +870,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
        if (unlikely(tx_fifo < 0))
                return tx_fifo;
 
-       IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
-                       __func__, sta->addr, tid);
+       IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n",
+                    sta->addr, tid);
 
        sta_id = iwl_sta_id(sta);
        if (sta_id == IWL_INVALID_STATION) {
@@ -1039,11 +896,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
        tid_data = &priv->stations[sta_id].tid[tid];
        *ssn = SEQ_TO_SN(tid_data->seq_number);
        tid_data->agg.txq_id = txq_id;
+       tid_data->agg.tx_fifo = tx_fifo;
        iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-       ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
-                                                 sta_id, tid, *ssn);
+       ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid);
        if (ret)
                return ret;
 
@@ -1130,8 +987,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
         * to deactivate the uCode queue, just return "success" to allow
         *  mac80211 to clean up it own data.
         */
-       priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
-                                                  tx_fifo_id);
+       iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id);
        spin_unlock_irqrestore(&priv->lock, flags);
 
        ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
@@ -1160,8 +1016,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
                        u16 ssn = SEQ_TO_SN(tid_data->seq_number);
                        int tx_fifo = get_fifo_from_tid(ctx, tid);
                        IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
-                       priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
-                                                            ssn, tx_fifo);
+                       iwlagn_txq_agg_disable(priv, txq_id, ssn, tx_fifo);
                        tid_data->agg.state = IWL_AGG_OFF;
                        ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
                }
@@ -1218,9 +1073,9 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
        struct ieee80211_hdr *hdr;
 
        if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
-               IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
-                         "is out of range [0-%d] %d %d.\n", txq_id,
-                         index, q->n_bd, q->write_ptr, q->read_ptr);
+               IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), "
+                         "index %d is out of range [0-%d] %d %d.\n", __func__,
+                         txq_id, index, q->n_bd, q->write_ptr, q->read_ptr);
                return 0;
        }
 
@@ -1241,10 +1096,9 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
                                 txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
                tx_info->skb = NULL;
 
-               if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
-                       priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq);
+               iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
 
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+               iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);
        }
        return nfreed;
 }
@@ -1260,11 +1114,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
                                 struct iwl_compressed_ba_resp *ba_resp)
 
 {
-       int i, sh, ack;
+       int sh;
        u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
        u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-       int successes = 0;
        struct ieee80211_tx_info *info;
+       u64 bitmap, sent_bitmap;
 
        if (unlikely(!agg->wait_for_ba))  {
                if (unlikely(ba_resp->bitmap))
@@ -1278,70 +1132,42 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
 
        /* Calculate shift to align block-ack bits with our Tx window bits */
        sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
-       if (sh < 0) /* tbw something is wrong with indices */
+       if (sh < 0)
                sh += 0x100;
 
-       if (agg->frame_count > (64 - sh)) {
-               IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
-               return -1;
-       }
-       if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) {
+       /*
+        * Check for success or failure according to the
+        * transmitted bitmap and block-ack bitmap
+        */
+       bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+       sent_bitmap = bitmap & agg->bitmap;
+
+       /* Sanity check values reported by uCode */
+       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);
                /*
-                * sent and ack information provided by uCode
-                * use it instead of figure out ourself
+                * set txed_2_done = txed,
+                * so it won't impact rate scale
                 */
-               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 {
-               u64 bitmap, sent_bitmap;
-
-               /* 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;
-               }
+               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);
 
-               IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
-                                  (unsigned long long)bitmap);
+       /* Find the first ACKed frame to store the TX status */
+       while (sent_bitmap && !(sent_bitmap & 1)) {
+               agg->start_idx = (agg->start_idx + 1) & 0xff;
+               sent_bitmap >>= 1;
        }
 
        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;
-       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;
-       }
+       info->status.ampdu_ack_len = ba_resp->txed_2_done;
+       info->status.ampdu_len = ba_resp->txed;
        iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
 
        return 0;