iwlwifi: pcie: remove TR/CR tail allocations
authorJohannes Berg <johannes.berg@intel.com>
Thu, 17 Jun 2021 08:07:28 +0000 (11:07 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Tue, 22 Jun 2021 13:57:55 +0000 (16:57 +0300)
The TR/CR tail data are meant to be per-queue-arrays, however,
we allocate them completely wrong (we have a separate allocation
per queue).

Looking at this more closely, it turns out that the hardware
never uses these - we have a separate free list per RX queue
and maintain a write pointer for that in a register, and the
RX itself is indicated in the RB status (rb_stts) DMA region.

Despite nothing using the tail pointers, the hardware will
unconditionally access them to write updates, even when we aren't
using CRs/TRs.

Give it dummy values that we never use/update so it can do that
without causing trouble.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210617110647.5f5764e04c46.I4d5de1929be048085767f1234a1e07b517ab6a2d@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/rx.c

index cecc32e..49560e5 100644 (file)
@@ -138,8 +138,15 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
 
        /* Allocate prph information
         * currently we don't assign to the prph info anything, but it would get
-        * assigned later */
-       prph_info = dma_alloc_coherent(trans->dev, sizeof(*prph_info),
+        * assigned later
+        *
+        * We also use the second half of this page to give the device some
+        * dummy TR/CR tail pointers - which shouldn't be necessary as we don't
+        * use this, but the hardware still reads/writes there and we can't let
+        * it go do that with a NULL pointer.
+        */
+       BUILD_BUG_ON(sizeof(*prph_info) > PAGE_SIZE / 2);
+       prph_info = dma_alloc_coherent(trans->dev, PAGE_SIZE,
                                       &trans_pcie->prph_info_dma_addr,
                                       GFP_KERNEL);
        if (!prph_info) {
@@ -166,13 +173,9 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
        ctxt_info_gen3->cr_head_idx_arr_base_addr =
                cpu_to_le64(trans_pcie->rxq->rb_stts_dma);
        ctxt_info_gen3->tr_tail_idx_arr_base_addr =
-               cpu_to_le64(trans_pcie->rxq->tr_tail_dma);
+               cpu_to_le64(trans_pcie->prph_info_dma_addr + PAGE_SIZE / 2);
        ctxt_info_gen3->cr_tail_idx_arr_base_addr =
-               cpu_to_le64(trans_pcie->rxq->cr_tail_dma);
-       ctxt_info_gen3->cr_idx_arr_size =
-               cpu_to_le16(IWL_NUM_OF_COMPLETION_RINGS);
-       ctxt_info_gen3->tr_idx_arr_size =
-               cpu_to_le16(IWL_NUM_OF_TRANSFER_RINGS);
+               cpu_to_le64(trans_pcie->prph_info_dma_addr + 3 * PAGE_SIZE / 4);
        ctxt_info_gen3->mtr_base_addr =
                cpu_to_le64(trans->txqs.txq[trans->txqs.cmd.q_id]->dma_addr);
        ctxt_info_gen3->mcr_base_addr =
@@ -216,10 +219,8 @@ err_free_ctxt_info:
                          trans_pcie->ctxt_info_dma_addr);
        trans_pcie->ctxt_info_gen3 = NULL;
 err_free_prph_info:
-       dma_free_coherent(trans->dev,
-                         sizeof(*prph_info),
-                       prph_info,
-                       trans_pcie->prph_info_dma_addr);
+       dma_free_coherent(trans->dev, PAGE_SIZE, prph_info,
+                         trans_pcie->prph_info_dma_addr);
 
 err_free_prph_scratch:
        dma_free_coherent(trans->dev,
@@ -251,8 +252,7 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans)
        trans_pcie->prph_scratch_dma_addr = 0;
        trans_pcie->prph_scratch = NULL;
 
-       dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_info),
-                         trans_pcie->prph_info,
+       dma_free_coherent(trans->dev, PAGE_SIZE, trans_pcie->prph_info,
                          trans_pcie->prph_info_dma_addr);
        trans_pcie->prph_info_dma_addr = 0;
        trans_pcie->prph_info = NULL;
index 1c740c3..292b972 100644 (file)
@@ -111,10 +111,6 @@ struct iwl_rx_completion_desc {
  * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
  * @used_bd: driver's pointer to buffer of used receive buffer descriptors (rbd)
  * @used_bd_dma: physical address of buffer of used receive buffer descriptors (rbd)
- * @tr_tail: driver's pointer to the transmission ring tail buffer
- * @tr_tail_dma: physical address of the buffer for the transmission ring tail
- * @cr_tail: driver's pointer to the completion ring tail buffer
- * @cr_tail_dma: physical address of the buffer for the completion ring tail
  * @read: Shared index to newest available Rx buffer
  * @write: Shared index to oldest written Rx packet
  * @free_count: Number of pre-allocated buffers in rx_free
@@ -142,10 +138,6 @@ struct iwl_rxq {
                struct iwl_rx_completion_desc *cd;
        };
        dma_addr_t used_bd_dma;
-       __le16 *tr_tail;
-       dma_addr_t tr_tail_dma;
-       __le16 *cr_tail;
-       dma_addr_t cr_tail_dma;
        u32 read;
        u32 write;
        u32 free_count;
@@ -533,9 +525,6 @@ static inline void _iwl_disable_interrupts(struct iwl_trans *trans)
        IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
 }
 
-#define IWL_NUM_OF_COMPLETION_RINGS    31
-#define IWL_NUM_OF_TRANSFER_RINGS      527
-
 static inline int iwl_pcie_get_num_sections(const struct fw_img *fw,
                                            int start)
 {
index fb84914..4f6f4b2 100644 (file)
@@ -663,7 +663,6 @@ static int iwl_pcie_free_bd_size(struct iwl_trans *trans, bool use_rx_td)
 static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
                                  struct iwl_rxq *rxq)
 {
-       struct device *dev = trans->dev;
        bool use_rx_td = (trans->trans_cfg->device_family >=
                          IWL_DEVICE_FAMILY_AX210);
        int free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
@@ -685,21 +684,6 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
                                  rxq->used_bd, rxq->used_bd_dma);
        rxq->used_bd_dma = 0;
        rxq->used_bd = NULL;
-
-       if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
-               return;
-
-       if (rxq->tr_tail)
-               dma_free_coherent(dev, sizeof(__le16),
-                                 rxq->tr_tail, rxq->tr_tail_dma);
-       rxq->tr_tail_dma = 0;
-       rxq->tr_tail = NULL;
-
-       if (rxq->cr_tail)
-               dma_free_coherent(dev, sizeof(__le16),
-                                 rxq->cr_tail, rxq->cr_tail_dma);
-       rxq->cr_tail_dma = 0;
-       rxq->cr_tail = NULL;
 }
 
 static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
@@ -744,21 +728,6 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
        rxq->rb_stts_dma =
                trans_pcie->base_rb_stts_dma + rxq->id * rb_stts_size;
 
-       if (!use_rx_td)
-               return 0;
-
-       /* Allocate the driver's pointer to TR tail */
-       rxq->tr_tail = dma_alloc_coherent(dev, sizeof(__le16),
-                                         &rxq->tr_tail_dma, GFP_KERNEL);
-       if (!rxq->tr_tail)
-               goto err;
-
-       /* Allocate the driver's pointer to CR tail */
-       rxq->cr_tail = dma_alloc_coherent(dev, sizeof(__le16),
-                                         &rxq->cr_tail_dma, GFP_KERNEL);
-       if (!rxq->cr_tail)
-               goto err;
-
        return 0;
 
 err:
@@ -1590,9 +1559,6 @@ restart:
 out:
        /* Backtrack one entry */
        rxq->read = i;
-       /* update cr tail with the rxq read pointer */
-       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
-               *rxq->cr_tail = cpu_to_le16(r);
        spin_unlock(&rxq->lock);
 
        /*