Blob Blame History Raw
From 5238205b08433bd8934b09a6d310617dd719e67d Mon Sep 17 00:00:00 2001
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Thu, 13 Jul 2017 09:49:32 +0300
Subject: [PATCH 39/68] iwlwifi: pcie: don't init a Tx queue with an SSN > size
 of the queue
References: FATE#322675
Patch-mainline: v4.14-rc1
Git-commit: 39fff7599397e1c9fdf54093f1f4c3146066c24b

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>
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -1034,6 +1034,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct
 		.flags = CMD_WANT_SKB,
 	};
 	int ret, qid;
+	u32 wr_ptr;
 
 	txq = kzalloc(sizeof(*txq), GFP_KERNEL);
 	if (!txq)
@@ -1074,6 +1075,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct
 
 	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);
@@ -1089,10 +1091,11 @@ int iwl_trans_pcie_dyn_txq_alloc(struct
 
 	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);