]> 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:28:35 +0000 (16:28 +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 169e16c6ed650f04087cb5edc953a66015e465cb..5dd251b878584f66ea4a5cd4fc3161be3d4189d1 100644 (file)
@@ -1728,13 +1728,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()