12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- From d0055b03d9c8d48ad2b971821989b09ba95c39f8 Mon Sep 17 00:00:00 2001
- From: Christian Marangi <[email protected]>
- 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 <[email protected]>
- ---
- 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);
|