1
0

0048-wifi-ath11k-fix-BUFFER_DONE-read-on-monitor-ring-rx-.patch 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. From 68e93ac5a31d4975b25f819b2dfe914c72abc3bb Mon Sep 17 00:00:00 2001
  2. From: Harshitha Prem <quic_hprem@quicinc.com>
  3. Date: Wed, 15 Mar 2023 12:24:43 +0200
  4. Subject: [PATCH] wifi: ath11k: fix BUFFER_DONE read on monitor ring rx buffer
  5. Perform dma_sync_single_for_cpu() on monitor ring rx buffer before
  6. reading BUFFER_DONE tag and do dma_unmap_single() only after device
  7. had set BUFFER_DONE tag to the buffer.
  8. Also when BUFFER_DONE tag is not set, allow the buffer to get read
  9. next time without freeing skb.
  10. This helps to fix AP+Monitor VAP with flood traffic scenario to see
  11. monitor ring rx buffer overrun missing BUFFER_DONE tag to be set.
  12. Also remove redundant rx dma buf free performed on DP
  13. rx_mon_status_refill_ring.
  14. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
  15. Signed-off-by: Sathishkumar Muruganandam <quic_murugana@quicinc.com>
  16. Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
  17. Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
  18. Link: https://lore.kernel.org/r/20230309164434.32660-1-quic_hprem@quicinc.com
  19. ---
  20. drivers/net/wireless/ath/ath11k/dp_rx.c | 57 ++++++++++---------------
  21. 1 file changed, 23 insertions(+), 34 deletions(-)
  22. --- a/drivers/net/wireless/ath/ath11k/dp_rx.c
  23. +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
  24. @@ -435,7 +435,6 @@ fail_free_skb:
  25. static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
  26. struct dp_rxdma_ring *rx_ring)
  27. {
  28. - struct ath11k_pdev_dp *dp = &ar->dp;
  29. struct sk_buff *skb;
  30. int buf_id;
  31. @@ -453,28 +452,6 @@ static int ath11k_dp_rxdma_buf_ring_free
  32. idr_destroy(&rx_ring->bufs_idr);
  33. spin_unlock_bh(&rx_ring->idr_lock);
  34. - /* if rxdma1_enable is false, mon_status_refill_ring
  35. - * isn't setup, so don't clean.
  36. - */
  37. - if (!ar->ab->hw_params.rxdma1_enable)
  38. - return 0;
  39. -
  40. - rx_ring = &dp->rx_mon_status_refill_ring[0];
  41. -
  42. - spin_lock_bh(&rx_ring->idr_lock);
  43. - idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
  44. - idr_remove(&rx_ring->bufs_idr, buf_id);
  45. - /* XXX: Understand where internal driver does this dma_unmap
  46. - * of rxdma_buffer.
  47. - */
  48. - dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
  49. - skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL);
  50. - dev_kfree_skb_any(skb);
  51. - }
  52. -
  53. - idr_destroy(&rx_ring->bufs_idr);
  54. - spin_unlock_bh(&rx_ring->idr_lock);
  55. -
  56. return 0;
  57. }
  58. @@ -3029,39 +3006,51 @@ static int ath11k_dp_rx_reap_mon_status_
  59. spin_lock_bh(&rx_ring->idr_lock);
  60. skb = idr_find(&rx_ring->bufs_idr, buf_id);
  61. + spin_unlock_bh(&rx_ring->idr_lock);
  62. +
  63. if (!skb) {
  64. ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n",
  65. buf_id);
  66. - spin_unlock_bh(&rx_ring->idr_lock);
  67. pmon->buf_state = DP_MON_STATUS_REPLINISH;
  68. goto move_next;
  69. }
  70. - idr_remove(&rx_ring->bufs_idr, buf_id);
  71. - spin_unlock_bh(&rx_ring->idr_lock);
  72. -
  73. rxcb = ATH11K_SKB_RXCB(skb);
  74. - dma_unmap_single(ab->dev, rxcb->paddr,
  75. - skb->len + skb_tailroom(skb),
  76. - DMA_FROM_DEVICE);
  77. + dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
  78. + skb->len + skb_tailroom(skb),
  79. + DMA_FROM_DEVICE);
  80. tlv = (struct hal_tlv_hdr *)skb->data;
  81. if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) !=
  82. HAL_RX_STATUS_BUFFER_DONE) {
  83. - ath11k_warn(ab, "mon status DONE not set %lx\n",
  84. + ath11k_warn(ab, "mon status DONE not set %lx, buf_id %d\n",
  85. FIELD_GET(HAL_TLV_HDR_TAG,
  86. - tlv->tl));
  87. - dev_kfree_skb_any(skb);
  88. + tlv->tl), buf_id);
  89. + /* If done status is missing, hold onto status
  90. + * ring until status is done for this status
  91. + * ring buffer.
  92. + * Keep HP in mon_status_ring unchanged,
  93. + * and break from here.
  94. + * Check status for same buffer for next time
  95. + */
  96. pmon->buf_state = DP_MON_STATUS_NO_DMA;
  97. - goto move_next;
  98. + break;
  99. }
  100. + spin_lock_bh(&rx_ring->idr_lock);
  101. + idr_remove(&rx_ring->bufs_idr, buf_id);
  102. + spin_unlock_bh(&rx_ring->idr_lock);
  103. if (ab->hw_params.full_monitor_mode) {
  104. ath11k_dp_rx_mon_update_status_buf_state(pmon, tlv);
  105. if (paddr == pmon->mon_status_paddr)
  106. pmon->buf_state = DP_MON_STATUS_MATCH;
  107. }
  108. +
  109. + dma_unmap_single(ab->dev, rxcb->paddr,
  110. + skb->len + skb_tailroom(skb),
  111. + DMA_FROM_DEVICE);
  112. +
  113. __skb_queue_tail(skb_list, skb);
  114. } else {
  115. pmon->buf_state = DP_MON_STATUS_REPLINISH;