forked from Openwrt/openwrt
9309cfe37a
This is an automatically generated commit. When doing `git bisect`, consider `git bisect --skip`. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
65 lines
2.5 KiB
Diff
65 lines
2.5 KiB
Diff
From d0055b03d9c8d48ad2b971821989b09ba95c39f8 Mon Sep 17 00:00:00 2001
|
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
|
Date: Sun, 17 Sep 2023 20:18:31 +0200
|
|
Subject: [PATCH] net: qualcomm: ipqess: fix TX timeout errors
|
|
|
|
Currently logic to handle napi tx completion is flawed and on the long
|
|
run on loaded condition cause TX timeout error with the queue not being
|
|
able to handle any new packet.
|
|
|
|
There are 2 main cause of this:
|
|
- incrementing the packet done value wrongly
|
|
- handling 2 times the tx_ring tail
|
|
|
|
ipqess_tx_unmap_and_free may return 2 kind values:
|
|
- 0: we are handling first and middle descriptor for the packet
|
|
- packet len: we are at the last descriptor for the packet
|
|
|
|
Done value was wrongly incremented also for first and intermediate
|
|
descriptor for the packet resulting causing panic and TX timeouts by
|
|
comunicating to the kernel an inconsistent value of packet handling not
|
|
matching the expected ones.
|
|
|
|
Tx_ring tail was handled twice for ipqess_tx_complete run resulting in
|
|
again done value incremented wrongly and also problem with idx handling
|
|
by actually skipping descriptor for some packets.
|
|
|
|
Rework the loop logic to fix these 2 problem and also add some comments
|
|
to make sure ipqess_tx_unmap_and_free ret value is better
|
|
understandable.
|
|
|
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|
---
|
|
drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 13 ++++++++++---
|
|
1 file changed, 10 insertions(+), 3 deletions(-)
|
|
|
|
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
|
|
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
|
|
@@ -453,13 +453,22 @@ static int ipqess_tx_complete(struct ipq
|
|
tail >>= IPQESS_TPD_CONS_IDX_SHIFT;
|
|
tail &= IPQESS_TPD_CONS_IDX_MASK;
|
|
|
|
- do {
|
|
+ while ((tx_ring->tail != tail) && (done < budget)) {
|
|
ret = ipqess_tx_unmap_and_free(&tx_ring->ess->pdev->dev,
|
|
&tx_ring->buf[tx_ring->tail]);
|
|
- tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count);
|
|
+ /* ipqess_tx_unmap_and_free may return 2 kind values:
|
|
+ * - 0: we are handling first and middle descriptor for the packet
|
|
+ * - packet len: we are at the last descriptor for the packet
|
|
+ * Increment total bytes handled and packet done only if we are
|
|
+ * handling the last descriptor for the packet.
|
|
+ */
|
|
+ if (ret) {
|
|
+ total += ret;
|
|
+ done++;
|
|
+ }
|
|
|
|
- total += ret;
|
|
- } while ((++done < budget) && (tx_ring->tail != tail));
|
|
+ tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count);
|
|
+ };
|
|
|
|
ipqess_w32(tx_ring->ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx),
|
|
tx_ring->tail);
|