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 --- .../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