iwlwifi: pcie: generalize and increase the size of scratchbuf
authorSara Sharon <sara.sharon@intel.com>
Thu, 9 Jun 2016 14:56:38 +0000 (17:56 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Wed, 6 Jul 2016 07:21:29 +0000 (10:21 +0300)
Currently the scratch buffer is set to 16 bytes and indicates
the size of the bi-directional DMA.
However, next HW generation will perform additional offloading,
and will write the result in the key location of the TX command,
so the size of the bi-directional consistent memory should grow
accordingly - increase it to 40.
Generalize the code to get rid of now irrelevant scratch references.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index 190f611af8ee2d34af55e21ccf75c3ee3d1a9792..c3d89744c35e2e5326496dda3aa1c171d2ae5182 100644 (file)
@@ -232,15 +232,16 @@ struct iwl_queue {
 #define TFD_CMD_SLOTS 32
 
 /*
- * The FH will write back to the first TB only, so we need
- * to copy some data into the buffer regardless of whether
- * it should be mapped or not. This indicates how big the
- * first TB must be to include the scratch buffer. Since
- * the scratch is 4 bytes at offset 12, it's 16 now. If we
- * make it bigger then allocations will be bigger and copy
- * slower, so that's probably not useful.
+ * The FH will write back to the first TB only, so we need to copy some data
+ * into the buffer regardless of whether it should be mapped or not.
+ * This indicates how big the first TB must be to include the scratch buffer
+ * and the assigned PN.
+ * Since PN location is 16 bytes at offset 24, it's 40 now.
+ * If we make it bigger then allocations will be bigger and copy slower, so
+ * that's probably not useful.
  */
-#define IWL_HCMD_SCRATCHBUF_SIZE       16
+#define IWL_FIRST_TB_SIZE      40
+#define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
 
 struct iwl_pcie_txq_entry {
        struct iwl_device_cmd *cmd;
@@ -250,20 +251,18 @@ struct iwl_pcie_txq_entry {
        struct iwl_cmd_meta meta;
 };
 
-struct iwl_pcie_txq_scratch_buf {
-       struct iwl_cmd_header hdr;
-       u8 buf[8];
-       __le32 scratch;
+struct iwl_pcie_first_tb_buf {
+       u8 buf[IWL_FIRST_TB_SIZE_ALIGN];
 };
 
 /**
  * struct iwl_txq - Tx Queue for DMA
  * @q: generic Rx/Tx queue descriptor
  * @tfds: transmit frame descriptors (DMA memory)
- * @scratchbufs: start of command headers, including scratch buffers, for
+ * @first_tb_bufs: start of command headers, including scratch buffers, for
  *     the writeback -- this is DMA memory and an array holding one buffer
  *     for each command on the queue
- * @scratchbufs_dma: DMA address for the scratchbufs start
+ * @first_tb_dma: DMA address for the first_tb_bufs start
  * @entries: transmit entries (driver state)
  * @lock: queue lock
  * @stuck_timer: timer that fires if queue gets stuck
@@ -281,8 +280,8 @@ struct iwl_pcie_txq_scratch_buf {
 struct iwl_txq {
        struct iwl_queue q;
        struct iwl_tfd *tfds;
-       struct iwl_pcie_txq_scratch_buf *scratchbufs;
-       dma_addr_t scratchbufs_dma;
+       struct iwl_pcie_first_tb_buf *first_tb_bufs;
+       dma_addr_t first_tb_dma;
        struct iwl_pcie_txq_entry *entries;
        spinlock_t lock;
        unsigned long frozen_expiry_remainder;
@@ -298,10 +297,10 @@ struct iwl_txq {
 };
 
 static inline dma_addr_t
-iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
+iwl_pcie_get_first_tb_dma(struct iwl_txq *txq, int idx)
 {
-       return txq->scratchbufs_dma +
-              sizeof(struct iwl_pcie_txq_scratch_buf) * idx;
+       return txq->first_tb_dma +
+              sizeof(struct iwl_pcie_first_tb_buf) * idx;
 }
 
 struct iwl_tso_hdr_page {
index 2b688260a6a97736ab19835f6a082002cf602a68..9a1c00623247f8a3d8fea54de3f08058faa58cdd 100644 (file)
@@ -393,7 +393,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
                return;
        }
 
-       /* first TB is never freed - it's the scratchbuf data */
+       /* first TB is never freed - it's the bidirectional DMA data */
 
        for (i = 1; i < num_tbs; i++) {
                if (meta->flags & BIT(i + CMD_TB_BITMAP_POS))
@@ -491,7 +491,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
-       size_t scratchbuf_sz;
+       size_t tb0_buf_sz;
        int i;
 
        if (WARN_ON(txq->entries || txq->tfds))
@@ -526,17 +526,14 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
        if (!txq->tfds)
                goto error;
 
-       BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs));
-       BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) !=
-                       sizeof(struct iwl_cmd_header) +
-                       offsetof(struct iwl_tx_cmd, scratch));
+       BUILD_BUG_ON(IWL_FIRST_TB_SIZE_ALIGN != sizeof(*txq->first_tb_bufs));
 
-       scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num;
+       tb0_buf_sz = sizeof(*txq->first_tb_bufs) * slots_num;
 
-       txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz,
-                                             &txq->scratchbufs_dma,
+       txq->first_tb_bufs = dma_alloc_coherent(trans->dev, tb0_buf_sz,
+                                             &txq->first_tb_dma,
                                              GFP_KERNEL);
-       if (!txq->scratchbufs)
+       if (!txq->first_tb_bufs)
                goto err_free_tfds;
 
        txq->q.id = txq_id;
@@ -708,8 +705,8 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
                txq->tfds = NULL;
 
                dma_free_coherent(dev,
-                                 sizeof(*txq->scratchbufs) * txq->q.n_window,
-                                 txq->scratchbufs, txq->scratchbufs_dma);
+                                 sizeof(*txq->first_tb_bufs) * txq->q.n_window,
+                                 txq->first_tb_bufs, txq->first_tb_dma);
        }
 
        kfree(txq->entries);
@@ -1422,7 +1419,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        void *dup_buf = NULL;
        dma_addr_t phys_addr;
        int idx;
-       u16 copy_size, cmd_size, scratch_size;
+       u16 copy_size, cmd_size, tb0_size;
        bool had_nocopy = false;
        u8 group_id = iwl_cmd_groupid(cmd->id);
        int i, ret;
@@ -1453,9 +1450,9 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                if (!cmd->len[i])
                        continue;
 
-               /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
-               if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
-                       int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
+               /* need at least IWL_FIRST_TB_SIZE copied */
+               if (copy_size < IWL_FIRST_TB_SIZE) {
+                       int copy = IWL_FIRST_TB_SIZE - copy_size;
 
                        if (copy > cmdlen[i])
                                copy = cmdlen[i];
@@ -1576,8 +1573,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                }
 
                /*
-                * Otherwise we need at least IWL_HCMD_SCRATCHBUF_SIZE copied
-                * in total (for the scratchbuf handling), but copy up to what
+                * Otherwise we need at least IWL_FIRST_TB_SIZE copied
+                * in total (for bi-directional DMA), but copy up to what
                 * we can fit into the payload for debug dump purposes.
                 */
                copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]);
@@ -1586,8 +1583,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                cmd_pos += copy;
 
                /* However, treat copy_size the proper way, we need it below */
-               if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
-                       copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
+               if (copy_size < IWL_FIRST_TB_SIZE) {
+                       copy = IWL_FIRST_TB_SIZE - copy_size;
 
                        if (copy > cmd->len[i])
                                copy = cmd->len[i];
@@ -1602,18 +1599,18 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                     le16_to_cpu(out_cmd->hdr.sequence),
                     cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
 
-       /* start the TFD with the scratchbuf */
-       scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE);
-       memcpy(&txq->scratchbufs[idx], &out_cmd->hdr, scratch_size);
+       /* start the TFD with the minimum copy bytes */
+       tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE);
+       memcpy(&txq->first_tb_bufs[idx], &out_cmd->hdr, tb0_size);
        iwl_pcie_txq_build_tfd(trans, txq,
-                              iwl_pcie_get_scratchbuf_dma(txq, idx),
-                              scratch_size, true);
+                              iwl_pcie_get_first_tb_dma(txq, idx),
+                              tb0_size, true);
 
        /* map first command fragment, if any remains */
-       if (copy_size > scratch_size) {
+       if (copy_size > tb0_size) {
                phys_addr = dma_map_single(trans->dev,
-                                          ((u8 *)&out_cmd->hdr) + scratch_size,
-                                          copy_size - scratch_size,
+                                          ((u8 *)&out_cmd->hdr) + tb0_size,
+                                          copy_size - tb0_size,
                                           DMA_TO_DEVICE);
                if (dma_mapping_error(trans->dev, phys_addr)) {
                        iwl_pcie_tfd_unmap(trans, out_meta,
@@ -1623,7 +1620,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                }
 
                iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
-                                      copy_size - scratch_size, false);
+                                      copy_size - tb0_size, false);
        }
 
        /* map the remaining (adjusted) nocopy/dup fragments */
@@ -1968,7 +1965,7 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,
        trace_iwlwifi_dev_tx(trans->dev, skb,
                             &txq->tfds[txq->q.write_ptr],
                             sizeof(struct iwl_tfd),
-                            &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len,
+                            &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len,
                             skb->data + hdr_len, tb2_len);
        trace_iwlwifi_dev_tx_data(trans->dev, skb,
                                  hdr_len, skb->len - hdr_len);
@@ -2044,7 +2041,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
        trace_iwlwifi_dev_tx(trans->dev, skb,
                             &txq->tfds[txq->q.write_ptr],
                             sizeof(struct iwl_tfd),
-                            &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len,
+                            &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len,
                             NULL, 0);
 
        ip_hdrlen = skb_transport_header(skb) - skb_network_header(skb);
@@ -2306,7 +2303,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
                cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
                            INDEX_TO_SEQ(q->write_ptr)));
 
-       tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr);
+       tb0_phys = iwl_pcie_get_first_tb_dma(txq, q->write_ptr);
        scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
                       offsetof(struct iwl_tx_cmd, scratch);
 
@@ -2324,7 +2321,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
         * setup of the first TB)
         */
        len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
-             hdr_len - IWL_HCMD_SCRATCHBUF_SIZE;
+             hdr_len - IWL_FIRST_TB_SIZE;
        /* do not align A-MSDU to dword as the subframe header aligns it */
        amsdu = ieee80211_is_data_qos(fc) &&
                (*ieee80211_get_qos_ctl(hdr) &
@@ -2338,17 +2335,17 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
                tb1_len = len;
        }
 
-       /* The first TB points to the scratchbuf data - min_copy bytes */
-       memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
-              IWL_HCMD_SCRATCHBUF_SIZE);
+       /* The first TB points to bi-directional DMA data */
+       memcpy(&txq->first_tb_bufs[q->write_ptr], &dev_cmd->hdr,
+              IWL_FIRST_TB_SIZE);
        iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
-                              IWL_HCMD_SCRATCHBUF_SIZE, true);
+                              IWL_FIRST_TB_SIZE, true);
 
        /* there must be data left over for TB1 or this code must be changed */
-       BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
+       BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE);
 
        /* map the data for TB1 */
-       tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE;
+       tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE;
        tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
        if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
                goto out_err;