From 69b2d06dafa4a61b718704d655dd370ba660052a Mon Sep 17 00:00:00 2001 From: Kang Yang Date: Fri, 28 Aug 2026 14:55:34 +0800 Subject: [PATCH] wifi: ath12k: preserve PPDU state across monitor status buffers A monitor PPDU may span multiple status buffers. However, __ath12k_wifi7_dp_mon_process_ring() clears mon_ppdu_info before processing every buffer. As a result, continuation buffers lose PPDU state collected from earlier buffers, including ppdu_id and PHY metadata. This can cause monitor RX processing to fail when ath12k_wifi7_dp_rx_mon_dest_process() observes a PPDU ID mismatch between status and destination rings, preventing MSDUs from being delivered. It can also produce incomplete EHT metadata that triggers warnings from mac80211: Rate marked as an EHT rate but data is invalid: MCS:0, NSS:0 ath12k_wifi7_dp_mon_srng_process() already tracks status TLV continuations via ppdu_continuation. Apply the same logic here and only reinitialize mon_ppdu_info when starting a new PPDU. mon_ppdu_info persists across ar->monitor_started transitions. If monitor mode stops while a PPDU is mid-continuation, ppdu_continuation stays set and could leak into the next monitor session. Reset it when monitor mode starts. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Fixes: 78d3d907d0f1 ("wifi: ath12k: add support to reap and process monitor status ring") Signed-off-by: Kang Yang Reviewed-by: Baochen Qiang Reviewed-by: Tamizh Chelvam Raja Link: https://patch.msgid.link/20260828065534.1537-1-kang.yang@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/mac.c | 7 ++++++ .../net/wireless/ath/ath12k/wifi7/dp_mon.c | 23 +++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 347bdea9b9ec..d4116ba0da08 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -1506,6 +1506,13 @@ static int ath12k_mac_monitor_start(struct ath12k *ar) return ret; } + /* + * A previous monitor session may have stopped mid-PPDU, leaving + * ppdu_continuation set. Clear it so the first status buffer of + * this session is not merged with stale state from before. + */ + ar->dp.mon_data.mon_ppdu_info.ppdu_continuation = false; + ar->monitor_started = true; ar->num_started_vdevs++; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c index 016b0c38e51e..ded7d56cd79b 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c @@ -3211,18 +3211,23 @@ __ath12k_wifi7_dp_mon_process_ring(struct ath12k *ar, int mac_id, goto exit; while ((skb = __skb_dequeue(&skb_list))) { - memset(ppdu_info, 0, sizeof(*ppdu_info)); - ppdu_info->peer_id = HAL_INVALID_PEERID; + if (!ppdu_info->ppdu_continuation) + ath12k_wifi7_dp_mon_rx_memset_ppdu_info(ppdu_info); hal_status = ath12k_wifi7_dp_mon_parse_rx_dest(&ar->dp, pmon, skb); - if (ar->monitor_started && - pmon->mon_ppdu_status == DP_PPDU_STATUS_START && - hal_status == HAL_TLV_STATUS_PPDU_DONE) { - rx_mon_stats->status_ppdu_done++; - pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE; - ath12k_wifi7_dp_rx_mon_dest_process(ar, mac_id, *budget, napi); - pmon->mon_ppdu_status = DP_PPDU_STATUS_START; + if (hal_status == HAL_TLV_STATUS_PPDU_DONE) { + ppdu_info->ppdu_continuation = false; + if (ar->monitor_started && + pmon->mon_ppdu_status == DP_PPDU_STATUS_START) { + rx_mon_stats->status_ppdu_done++; + pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE; + ath12k_wifi7_dp_rx_mon_dest_process(ar, mac_id, + *budget, napi); + pmon->mon_ppdu_status = DP_PPDU_STATUS_START; + } + } else { + ppdu_info->ppdu_continuation = true; } dev_kfree_skb_any(skb);