From 39fff7599397e1c9fdf54093f1f4c3146066c24b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 13 Jul 2017 09:49:32 +0300 Subject: [PATCH] iwlwifi: pcie: don't init a Tx queue with an SSN > size of the queue 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 Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 5dc785d4c167..83a28892dc4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -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); -- 2.45.2