iwlwifi: pcie: support short Tx queues for A000 device family
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 16 Jul 2017 09:28:05 +0000 (12:28 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 18 Aug 2017 13:04:44 +0000 (16:04 +0300)
This allows to modify TFD_TX_CMD_SLOTS to a power of 2
which is smaller than 256.
Note that we still need to set values to wrap at 256
into the scheduler's write pointer, but all the rest of
the code can use shorter transmit queues.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index eddaca76d51490b102d5c527c886b02e967066de..3fc4343581eee27c2234909a0554aac67a2b3c93 100644 (file)
@@ -244,7 +244,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
        ctxt_info->hcmd_cfg.cmd_queue_addr =
                cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
        ctxt_info->hcmd_cfg.cmd_queue_size =
-               TFD_QUEUE_CB_SIZE(TFD_QUEUE_SIZE_MAX);
+               TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS);
 
        /* allocate ucode sections in dram and set addresses */
        ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
index f46871840fd25207e296ca7d47487fa658cf773c..79020cf8c79cfd7b09a4310dd4f94d31c5254fdc 100644 (file)
@@ -661,10 +661,16 @@ static inline void iwl_pcie_sw_reset(struct iwl_trans *trans)
        usleep_range(5000, 6000);
 }
 
+static inline u8 iwl_pcie_get_cmd_index(struct iwl_txq *q, u32 index)
+{
+       return index & (q->n_window - 1);
+}
+
 static inline void *iwl_pcie_get_tfd(struct iwl_trans_pcie *trans_pcie,
                                     struct iwl_txq *txq, int idx)
 {
-       return txq->tfds + trans_pcie->tfd_size * idx;
+       return txq->tfds + trans_pcie->tfd_size * iwl_pcie_get_cmd_index(txq,
+                                                                        idx);
 }
 
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
@@ -726,11 +732,6 @@ static inline bool iwl_queue_used(const struct iwl_txq *q, int i)
                !(i < q->read_ptr && i >= q->write_ptr);
 }
 
-static inline u8 get_cmd_index(struct iwl_txq *q, u32 index)
-{
-       return index & (q->n_window - 1);
-}
-
 static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
index 351c4423125a219cc88b4dc0846d5b573526afbb..e5d2bf0bde3738b898398a3f4483be95a610ae86 100644 (file)
@@ -1176,7 +1176,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 
                sequence = le16_to_cpu(pkt->hdr.sequence);
                index = SEQ_TO_INDEX(sequence);
-               cmd_index = get_cmd_index(txq, index);
+               cmd_index = iwl_pcie_get_cmd_index(txq, index);
 
                if (rxq->id == 0)
                        iwl_op_mode_rx(trans->op_mode, &rxq->napi,
index 382d7c251066e81a8870f7bb580db11d9b11e379..3ecafa2ad922ac8c920bdc744dfbf6cd90af45dc 100644 (file)
@@ -2835,7 +2835,7 @@ static struct iwl_trans_dump_data
        spin_lock_bh(&cmdq->lock);
        ptr = cmdq->write_ptr;
        for (i = 0; i < cmdq->n_window; i++) {
-               u8 idx = get_cmd_index(cmdq, ptr);
+               u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
                u32 caplen, cmdlen;
 
                cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds +
index 4db45e56b6ba63583d3698b589c862e6006ac3f8..d74613fcb756c85d51e45f5fb082dc9d05ca3ba0 100644 (file)
@@ -88,14 +88,14 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_txq *txq, u16 byte_cnt,
                                          int num_tbs)
 {
        struct iwlagn_scd_bc_tbl *scd_bc_tbl = txq->bc_tbl.addr;
-       int write_ptr = txq->write_ptr;
+       int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
        u8 filled_tfd_size, num_fetch_chunks;
        u16 len = byte_cnt;
        __le16 bc_ent;
 
        len = DIV_ROUND_UP(len, 4);
 
-       if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX))
+       if (WARN_ON(len > 0xFFF || idx >= txq->n_window))
                return;
 
        filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) +
@@ -111,7 +111,7 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_txq *txq, u16 byte_cnt,
        num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
 
        bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
-       scd_bc_tbl->tfd_offset[write_ptr] = bc_ent;
+       scd_bc_tbl->tfd_offset[idx] = bc_ent;
 }
 
 /*
@@ -176,16 +176,12 @@ static void iwl_pcie_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
        /* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and
         * idx is bounded by n_window
         */
-       int rd_ptr = txq->read_ptr;
-       int idx = get_cmd_index(txq, rd_ptr);
+       int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
 
        lockdep_assert_held(&txq->lock);
 
-       /* We have only q->n_window txq->entries, but we use
-        * TFD_QUEUE_SIZE_MAX tfds
-        */
        iwl_pcie_gen2_tfd_unmap(trans, &txq->entries[idx].meta,
-                               iwl_pcie_get_tfd(trans_pcie, txq, rd_ptr));
+                               iwl_pcie_get_tfd(trans_pcie, txq, idx));
 
        /* free SKB */
        if (txq->entries) {
@@ -373,8 +369,9 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
        struct iwl_tfh_tfd *tfd =
-               iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
+               iwl_pcie_get_tfd(trans_pcie, txq, idx);
        dma_addr_t tb_phys;
        bool amsdu;
        int i, len, tb1_len, tb2_len, hdr_len;
@@ -386,10 +383,10 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
                (*ieee80211_get_qos_ctl(hdr) &
                 IEEE80211_QOS_CTL_A_MSDU_PRESENT);
 
-       tb_phys = iwl_pcie_get_first_tb_dma(txq, txq->write_ptr);
+       tb_phys = iwl_pcie_get_first_tb_dma(txq, idx);
        /* The first TB points to bi-directional DMA data */
        if (!amsdu)
-               memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+               memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr,
                       IWL_FIRST_TB_SIZE);
 
        iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE);
@@ -431,7 +428,7 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
                 * building the A-MSDU might have changed this data, so memcpy
                 * it now
                 */
-               memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+               memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr,
                       IWL_FIRST_TB_SIZE);
                return tfd;
        }
@@ -484,6 +481,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
        struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
        struct iwl_cmd_meta *out_meta;
        struct iwl_txq *txq = trans_pcie->txq[txq_id];
+       int idx;
        void *tfd;
 
        if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
@@ -497,16 +495,18 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
 
        spin_lock(&txq->lock);
 
+       idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
+
        /* Set up driver data for this TFD */
-       txq->entries[txq->write_ptr].skb = skb;
-       txq->entries[txq->write_ptr].cmd = dev_cmd;
+       txq->entries[idx].skb = skb;
+       txq->entries[idx].cmd = dev_cmd;
 
        dev_cmd->hdr.sequence =
                cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-                           INDEX_TO_SEQ(txq->write_ptr)));
+                           INDEX_TO_SEQ(idx)));
 
        /* Set up first empty entry in queue's array of Tx/cmd buffers */
-       out_meta = &txq->entries[txq->write_ptr].meta;
+       out_meta = &txq->entries[idx].meta;
        out_meta->flags = 0;
 
        tfd = iwl_pcie_gen2_build_tfd(trans, txq, dev_cmd, skb, out_meta);
@@ -562,7 +562,7 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
        unsigned long flags;
        void *dup_buf = NULL;
        dma_addr_t phys_addr;
-       int idx, i, cmd_pos;
+       int i, cmd_pos, idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
        u16 copy_size, cmd_size, tb0_size;
        bool had_nocopy = false;
        u8 group_id = iwl_cmd_groupid(cmd->id);
@@ -651,7 +651,6 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
                goto free_dup_buf;
        }
 
-       idx = get_cmd_index(txq, txq->write_ptr);
        out_cmd = txq->entries[idx].cmd;
        out_meta = &txq->entries[idx].meta;
 
@@ -938,7 +937,7 @@ void iwl_pcie_gen2_txq_unmap(struct iwl_trans *trans, int txq_id)
                                   txq_id, txq->read_ptr);
 
                if (txq_id != trans_pcie->cmd_queue) {
-                       int idx = get_cmd_index(txq, txq->read_ptr);
+                       int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
                        struct sk_buff *skb = txq->entries[idx].skb;
 
                        if (WARN_ON_ONCE(!skb))
@@ -1070,7 +1069,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
 
        cmd->tfdq_addr = cpu_to_le64(txq->dma_addr);
        cmd->byte_cnt_addr = cpu_to_le64(txq->bc_tbl.dma);
-       cmd->cb_size = cpu_to_le32(TFD_QUEUE_CB_SIZE(TFD_QUEUE_SIZE_MAX));
+       cmd->cb_size = cpu_to_le32(TFD_QUEUE_CB_SIZE(TFD_TX_CMD_SLOTS));
 
        ret = iwl_trans_send_cmd(trans, &hcmd);
        if (ret)
index c893f9088f9d51a71cca336f673c36d1e13c0bc3..c645d10d37072c3c6883ea4f21c415a0a89924c1 100644 (file)
@@ -106,7 +106,7 @@ static int iwl_queue_init(struct iwl_txq *q, int slots_num)
        q->n_window = slots_num;
 
        /* slots_num must be power-of-two size, otherwise
-        * get_cmd_index is broken. */
+        * iwl_pcie_get_cmd_index is broken. */
        if (WARN_ON(!is_power_of_2(slots_num)))
                return -EINVAL;
 
@@ -428,7 +428,7 @@ void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
         * idx is bounded by n_window
         */
        int rd_ptr = txq->read_ptr;
-       int idx = get_cmd_index(txq, rd_ptr);
+       int idx = iwl_pcie_get_cmd_index(txq, rd_ptr);
 
        lockdep_assert_held(&txq->lock);
 
@@ -1100,7 +1100,8 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
        for (;
             txq->read_ptr != tfd_num;
             txq->read_ptr = iwl_queue_inc_wrap(txq->read_ptr)) {
-               struct sk_buff *skb = txq->entries[txq->read_ptr].skb;
+               int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
+               struct sk_buff *skb = txq->entries[idx].skb;
 
                if (WARN_ON_ONCE(!skb))
                        continue;
@@ -1109,7 +1110,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
 
                __skb_queue_tail(skbs, skb);
 
-               txq->entries[txq->read_ptr].skb = NULL;
+               txq->entries[idx].skb = NULL;
 
                if (!trans->cfg->use_tfh)
                        iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
@@ -1559,7 +1560,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                goto free_dup_buf;
        }
 
-       idx = get_cmd_index(txq, txq->write_ptr);
+       idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
        out_cmd = txq->entries[idx].cmd;
        out_meta = &txq->entries[idx].meta;
 
@@ -1751,7 +1752,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
 
        spin_lock_bh(&txq->lock);
 
-       cmd_index = get_cmd_index(txq, index);
+       cmd_index = iwl_pcie_get_cmd_index(txq, index);
        cmd = txq->entries[cmd_index].cmd;
        meta = &txq->entries[cmd_index].meta;
        group_id = cmd->hdr.group_id;