mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 03:35:32 -04:00
wifi: ath12k: add dp_mon support 32-bit TLV headers
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> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Link: https://patch.msgid.link/20260509025819.1641630-5-miaoqing.pan@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
committed by
Jeff Johnson
parent
9d1d61121b
commit
4c09bbf0c1
@@ -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,
|
||||
@@ -2930,11 +2931,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;
|
||||
@@ -2959,8 +2961,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;
|
||||
@@ -2972,39 +2974,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) ||
|
||||
@@ -3056,15 +3057,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;
|
||||
|
||||
@@ -3109,14 +3111,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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user