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