]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: ath12k: fix dest ring-buffer corruption
authorJohan Hovold <johan+linaro@kernel.org>
Tue, 17 Jun 2025 08:43:59 +0000 (10:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Aug 2025 14:30:57 +0000 (16:30 +0200)
commit 8157ce533a60521f21d466eb4de45d9735b19484 upstream.

Add the missing memory barrier to make sure that destination ring
descriptors are read after the head pointers to avoid using stale data
on weakly ordered architectures like aarch64.

The barrier is added to the ath12k_hal_srng_access_begin() helper for
symmetry with follow-on fixes for source ring buffer corruption which
will add barriers to ath12k_hal_srng_access_end().

Tested-on: WCN7850 hw2.0 WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Cc: stable@vger.kernel.org # 6.3
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Reviewed-by: Baochen Qiang <quic_bqiang@quicinc.com>
Link: https://patch.msgid.link/20250617084402.14475-2-johan+linaro@kernel.org
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/ath/ath12k/ce.c
drivers/net/wireless/ath/ath12k/hal.c

index 740586fe49d1f9b7f46f0b4ed8865ca7aa158459..b66d23d6b2bd9e36d1972a6fbf4dea2cabaf58d7 100644 (file)
@@ -343,9 +343,6 @@ static int ath12k_ce_completed_recv_next(struct ath12k_ce_pipe *pipe,
                goto err;
        }
 
-       /* Make sure descriptor is read after the head pointer. */
-       dma_rmb();
-
        *nbytes = ath12k_hal_ce_dst_status_get_length(desc);
 
        *skb = pipe->dest_ring->skb[sw_index];
index 3afb11c7bf18eb3310bd9aa2438015092e51f82a..18231343474c55bc26d18feafdb65a50ab2e28fc 100644 (file)
@@ -2107,13 +2107,24 @@ void *ath12k_hal_srng_src_get_next_reaped(struct ath12k_base *ab,
 
 void ath12k_hal_srng_access_begin(struct ath12k_base *ab, struct hal_srng *srng)
 {
+       u32 hp;
+
        lockdep_assert_held(&srng->lock);
 
-       if (srng->ring_dir == HAL_SRNG_DIR_SRC)
+       if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
                srng->u.src_ring.cached_tp =
                        *(volatile u32 *)srng->u.src_ring.tp_addr;
-       else
-               srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
+       } else {
+               hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
+
+               if (hp != srng->u.dst_ring.cached_hp) {
+                       srng->u.dst_ring.cached_hp = hp;
+                       /* Make sure descriptor is read after the head
+                        * pointer.
+                        */
+                       dma_rmb();
+               }
+       }
 }
 
 /* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin()