From: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
To: jjohnson@kernel.org
Cc: ath12k@lists.infradead.org, linux-wireless@vger.kernel.org,
linux-kernel@vger.kernel.org,
Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
Subject: [PATCH ath-next 4/5] wifi: ath12k: add dp_mon support 32-bit TLV headers
Date: Sat, 9 May 2026 10:58:18 +0800 [thread overview]
Message-ID: <20260509025819.1641630-5-miaoqing.pan@oss.qualcomm.com> (raw)
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>
Wi-Fi 7 monitor status parsing in dp_mon currently assumes a 64-bit TLV
header and directly decodes tag/len/userid from struct hal_tlv_64_hdr.
On chips using a 32-bit TLV header (e.g. QCC2072), this causes monitor RX
status packets to be dropped during TLV parsing.
Introduce HAL helpers to decode TLV header fields (tag/len/userid/value)
for both 32-bit and 64-bit header layouts. Without changing the actual TLV
parsing logic.
Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---
.../net/wireless/ath/ath12k/wifi7/dp_mon.c | 57 ++++++++++---------
1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
index 77f5d23be78d..4266bd1d0d3d 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
@@ -1565,16 +1565,17 @@ ath12k_wifi7_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
static enum hal_rx_mon_status
ath12k_wifi7_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
- const struct hal_tlv_64_hdr *tlv)
+ const void *tlv)
{
struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
- const void *tlv_data = tlv->value;
- u32 info[7], userid;
- u16 tlv_tag, tlv_len;
+ struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+ struct ath12k_hal *hal = &ar->ab->hal;
+ u16 tlv_tag, tlv_len, userid;
+ void *tlv_data;
+ u32 info[7];
- tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
- tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
- userid = le64_get_bits(tlv->tl, HAL_TLV_64_USR_ID);
+ tlv_data = hal->ops->mon_rx_status_dec_tlv_hdr((void *)tlv, &tlv_tag,
+ &tlv_len, &userid);
if (ppdu_info->tlv_aggr.in_progress && ppdu_info->tlv_aggr.tlv_tag != tlv_tag) {
ath12k_wifi7_dp_mon_parse_eht_sig_hdr(ppdu_info,
@@ -2931,11 +2932,12 @@ static enum dp_mon_status_buf_state
ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
struct dp_rxdma_mon_ring *rx_ring)
{
+ struct ath12k_hal *hal = &ab->hal;
struct ath12k_skb_rxcb *rxcb;
- struct hal_tlv_64_hdr *tlv;
struct sk_buff *skb;
void *status_desc;
dma_addr_t paddr;
+ u16 tlv_tag;
u32 cookie;
int buf_id;
u8 rbm;
@@ -2960,8 +2962,8 @@ ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
- tlv = (struct hal_tlv_64_hdr *)skb->data;
- if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE)
+ hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag, NULL, NULL);
+ if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE)
return DP_MON_STATUS_NO_DMA;
return DP_MON_STATUS_REPLINISH;
@@ -2973,39 +2975,38 @@ ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *skb)
{
struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
- struct hal_tlv_64_hdr *tlv;
+ struct ath12k_hal *hal = &ar->ab->hal;
+ u8 *tlv_value, *tlv = skb->data;
struct ath12k_skb_rxcb *rxcb;
enum hal_rx_mon_status hal_status;
u16 tlv_tag, tlv_len;
- u8 *ptr = skb->data;
+ u32 tlv_hdr_len;
+
+ tlv_hdr_len = hal->ops->get_tlv_hdr_align();
do {
- tlv = (struct hal_tlv_64_hdr *)ptr;
- tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
+ tlv_value = hal->ops->mon_rx_status_dec_tlv_hdr(tlv, &tlv_tag,
+ &tlv_len, NULL);
/* The actual length of PPDU_END is the combined length of many PHY
* TLVs that follow. Skip the TLV header and
* rx_rxpcu_classification_overview that follows the header to get to
* next TLV.
*/
-
if (tlv_tag == HAL_RX_PPDU_END)
tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview);
- else
- tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
hal_status = ath12k_wifi7_dp_mon_rx_parse_status_tlv(dp_pdev, pmon,
tlv);
if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable &&
ath12k_wifi7_dp_mon_parse_rx_dest_tlv(dp_pdev, pmon, hal_status,
- tlv->value))
+ tlv_value))
return HAL_RX_MON_STATUS_PPDU_DONE;
- ptr += sizeof(*tlv) + tlv_len;
- ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN);
+ tlv = PTR_ALIGN(tlv + tlv_len + tlv_hdr_len, tlv_hdr_len);
- if ((ptr - skb->data) > skb->len)
+ if ((tlv - skb->data) > skb->len)
break;
} while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) ||
@@ -3057,15 +3058,16 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
int buf_id, srng_id, num_buffs_reaped = 0;
enum dp_mon_status_buf_state reap_status;
struct dp_rxdma_mon_ring *rx_ring;
+ struct ath12k_hal *hal = &ab->hal;
struct ath12k_mon_data *pmon;
struct ath12k_skb_rxcb *rxcb;
- struct hal_tlv_64_hdr *tlv;
void *rx_mon_status_desc;
struct hal_srng *srng;
struct ath12k_dp *dp;
struct sk_buff *skb;
struct ath12k *ar;
dma_addr_t paddr;
+ u16 tlv_tag;
u32 cookie;
u8 rbm;
@@ -3110,14 +3112,13 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
- tlv = (struct hal_tlv_64_hdr *)skb->data;
- if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) !=
- HAL_RX_STATUS_BUFFER_DONE) {
+ hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag,
+ NULL, NULL);
+ if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE) {
pmon->buf_state = DP_MON_STATUS_NO_DMA;
ath12k_warn(ab,
- "mon status DONE not set %llx, buf_id %d\n",
- le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG),
- buf_id);
+ "mon status DONE not set %x, buf_id %d\n",
+ tlv_tag, buf_id);
/* RxDMA status done bit might not be set even
* though tp is moved by HW.
*/
--
2.34.1
next prev parent reply other threads:[~2026-05-09 2:59 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-09 2:58 [PATCH ath-next 0/5] wifi: ath12k: fix dp_mon RX parsing for 32-bit TLV Miaoqing Pan
2026-05-09 2:58 ` [PATCH ath-next 1/5] wifi: ath12k: fix TLV32 length mask Miaoqing Pan
2026-05-09 2:58 ` [PATCH ath-next 2/5] wifi: ath12k: refactor HAL TLV32/64 decode helpers Miaoqing Pan
2026-05-09 2:58 ` [PATCH ath-next 3/5] wifi: ath12k: add HAL ops for monitor TLV header decode and alignment Miaoqing Pan
2026-05-09 2:58 ` Miaoqing Pan [this message]
2026-05-09 2:58 ` [PATCH ath-next 5/5] wifi: ath12k: tighten RX monitor TLV bounds check Miaoqing Pan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260509025819.1641630-5-miaoqing.pan@oss.qualcomm.com \
--to=miaoqing.pan@oss.qualcomm.com \
--cc=ath12k@lists.infradead.org \
--cc=jjohnson@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox