[PATCH ath-next] wifi: ath12k: preserve PPDU state across monitor status buffers

Tamizh Raja tamizh.raja at oss.qualcomm.com
Sun Aug 30 22:53:12 PDT 2026


On Fri, Aug 28, 2026 at 12:26 PM Kang Yang <kang.yang at oss.qualcomm.com> wrote:
>
> 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 <kang.yang at oss.qualcomm.com>
> ---
>  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 9a775602775d..bda055a86f06 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -1502,6 +1502,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) {
Consider HAL_RX_MON_STATUS_PPDU_DONE instead of
HAL_TLV_STATUS_PPDU_DONE to match the declared return type of
ath12k_wifi7_dp_mon_parse_rx_dest().
This is a preexisting inconsistency, but it is good to clean it up

> +                       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);
>
> base-commit: ca800a9302764c445de0da0e84d2252400a770ee
> --
> 2.34.1
>
>
Actual code change looks good to me

Reviewed-by: Tamizh Chelvam Raja <tamizh.raja at oss.qualcomm.com>

-- 
- Tamizh.



More information about the ath12k mailing list