711-net-qualcomm-ipqess-fix-TX-timeout-errors.patch 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. From d0055b03d9c8d48ad2b971821989b09ba95c39f8 Mon Sep 17 00:00:00 2001
  2. From: Christian Marangi <[email protected]>
  3. Date: Sun, 17 Sep 2023 20:18:31 +0200
  4. Subject: [PATCH] net: qualcomm: ipqess: fix TX timeout errors
  5. Currently logic to handle napi tx completion is flawed and on the long
  6. run on loaded condition cause TX timeout error with the queue not being
  7. able to handle any new packet.
  8. There are 2 main cause of this:
  9. - incrementing the packet done value wrongly
  10. - handling 2 times the tx_ring tail
  11. ipqess_tx_unmap_and_free may return 2 kind values:
  12. - 0: we are handling first and middle descriptor for the packet
  13. - packet len: we are at the last descriptor for the packet
  14. Done value was wrongly incremented also for first and intermediate
  15. descriptor for the packet resulting causing panic and TX timeouts by
  16. comunicating to the kernel an inconsistent value of packet handling not
  17. matching the expected ones.
  18. Tx_ring tail was handled twice for ipqess_tx_complete run resulting in
  19. again done value incremented wrongly and also problem with idx handling
  20. by actually skipping descriptor for some packets.
  21. Rework the loop logic to fix these 2 problem and also add some comments
  22. to make sure ipqess_tx_unmap_and_free ret value is better
  23. understandable.
  24. Signed-off-by: Christian Marangi <[email protected]>
  25. ---
  26. drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 13 ++++++++++---
  27. 1 file changed, 10 insertions(+), 3 deletions(-)
  28. --- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
  29. +++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
  30. @@ -453,13 +453,22 @@ static int ipqess_tx_complete(struct ipq
  31. tail >>= IPQESS_TPD_CONS_IDX_SHIFT;
  32. tail &= IPQESS_TPD_CONS_IDX_MASK;
  33. - do {
  34. + while ((tx_ring->tail != tail) && (done < budget)) {
  35. ret = ipqess_tx_unmap_and_free(&tx_ring->ess->pdev->dev,
  36. &tx_ring->buf[tx_ring->tail]);
  37. - tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count);
  38. + /* ipqess_tx_unmap_and_free may return 2 kind values:
  39. + * - 0: we are handling first and middle descriptor for the packet
  40. + * - packet len: we are at the last descriptor for the packet
  41. + * Increment total bytes handled and packet done only if we are
  42. + * handling the last descriptor for the packet.
  43. + */
  44. + if (ret) {
  45. + total += ret;
  46. + done++;
  47. + }
  48. - total += ret;
  49. - } while ((++done < budget) && (tx_ring->tail != tail));
  50. + tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count);
  51. + };
  52. ipqess_w32(tx_ring->ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx),
  53. tx_ring->tail);