iwlwifi: pcie: don't init a Tx queue with an SSN > size of the queue
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 13 Jul 2017 06:49:32 +0000 (09:49 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Wed, 9 Aug 2017 18:14:42 +0000 (21:14 +0300)
The TVQM tells us the initial write pointer for a queue,
but that write pointer is in WiFi sequence number unit
and not in TFD index unit. Which means that the write
pointer in the TVQM's response can be bigger than the
Tx queue ring size.

Fix that by modulo'ing the write pointer from the TVQM
with the Tx queue size.

Fixes: 66128fa08806 ("iwlwifi: move to TVQM mode")
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c

index 5dc785d4c167653e4d3e636a0a406464070b6af1..83a28892dc4f53e01d7fbe98f08687c5fdd76610 100644 (file)
@@ -1033,6 +1033,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
                .flags = CMD_WANT_SKB,
        };
        int ret, qid;
+       u32 wr_ptr;
 
        txq = kzalloc(sizeof(*txq), GFP_KERNEL);
        if (!txq)
@@ -1073,6 +1074,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
 
        rsp = (void *)hcmd.resp_pkt->data;
        qid = le16_to_cpu(rsp->queue_number);
+       wr_ptr = le16_to_cpu(rsp->write_pointer);
 
        if (qid >= ARRAY_SIZE(trans_pcie->txq)) {
                WARN_ONCE(1, "queue index %d unsupported", qid);
@@ -1088,10 +1090,11 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
 
        txq->id = qid;
        trans_pcie->txq[qid] = txq;
+       wr_ptr &= (TFD_QUEUE_SIZE_MAX - 1);
 
        /* Place first TFD at index corresponding to start sequence number */
-       txq->read_ptr = le16_to_cpu(rsp->write_pointer);
-       txq->write_ptr = le16_to_cpu(rsp->write_pointer);
+       txq->read_ptr = wr_ptr;
+       txq->write_ptr = wr_ptr;
        iwl_write_direct32(trans, HBUS_TARG_WRPTR,
                           (txq->write_ptr) | (qid << 16));
        IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d\n", qid);