]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Move TX monitor functionality to Wi-Fi 7 module
authorAlok Singh <quic_aloksing@quicinc.com>
Mon, 10 Nov 2025 10:37:06 +0000 (16:07 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Tue, 11 Nov 2025 15:21:33 +0000 (07:21 -0800)
Separate Wi-Fi 7-specific TX monitor functionality from ath12k
common code to improve modularity and maintainability.

Move following TX monitor processing functions to wifi7/dp_mon.c and
rename the functions with the ath12k_wifi7_ prefix:
- ath12k_dp_mon_tx_get_ppdu_info()
- ath12k_dp_mon_hal_tx_ppdu_info()
- ath12k_dp_mon_tx_alloc_skb()
- ath12k_dp_mon_tx_gen_cts2self_frame()
- ath12k_dp_mon_tx_gen_rts_frame()
- ath12k_dp_mon_tx_gen_3addr_qos_null_frame()
- ath12k_dp_mon_tx_gen_4addr_qos_null_frame()
- ath12k_dp_mon_tx_gen_ack_frame()
- ath12k_dp_mon_tx_gen_prot_frame()
- ath12k_dp_mon_tx_parse_status_tlv()
- ath12k_dp_mon_tx_status_get_num_user()
- ath12k_dp_mon_tx_process_ppdu_info()
- ath12k_dp_mon_tx_parse_mon_status()

Export helper functions required by the ath12k_wifi7 module.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1

Signed-off-by: Alok Singh <quic_aloksing@quicinc.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20251110103713.3484779-6-quic_aloksing@quicinc.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_mon.c
drivers/net/wireless/ath/ath12k/dp_mon.h
drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h

index dc4827771a64c3b5d5837b4b599af0dfb50212bb..d3e662399c3116906b9ea54f4deb4cec8475355f 100644 (file)
@@ -2366,677 +2366,6 @@ fail_free_skb:
        return req_entries - num_remain;
 }
 
-static struct dp_mon_tx_ppdu_info *
-ath12k_dp_mon_tx_get_ppdu_info(struct ath12k_mon_data *pmon,
-                              unsigned int ppdu_id,
-                              enum dp_mon_tx_ppdu_info_type type)
-{
-       struct dp_mon_tx_ppdu_info *tx_ppdu_info;
-
-       if (type == DP_MON_TX_PROT_PPDU_INFO) {
-               tx_ppdu_info = pmon->tx_prot_ppdu_info;
-
-               if (tx_ppdu_info && !tx_ppdu_info->is_used)
-                       return tx_ppdu_info;
-               kfree(tx_ppdu_info);
-       } else {
-               tx_ppdu_info = pmon->tx_data_ppdu_info;
-
-               if (tx_ppdu_info && !tx_ppdu_info->is_used)
-                       return tx_ppdu_info;
-               kfree(tx_ppdu_info);
-       }
-
-       /* allocate new tx_ppdu_info */
-       tx_ppdu_info = kzalloc(sizeof(*tx_ppdu_info), GFP_ATOMIC);
-       if (!tx_ppdu_info)
-               return NULL;
-
-       tx_ppdu_info->is_used = 0;
-       tx_ppdu_info->ppdu_id = ppdu_id;
-
-       if (type == DP_MON_TX_PROT_PPDU_INFO)
-               pmon->tx_prot_ppdu_info = tx_ppdu_info;
-       else
-               pmon->tx_data_ppdu_info = tx_ppdu_info;
-
-       return tx_ppdu_info;
-}
-
-static struct dp_mon_tx_ppdu_info *
-ath12k_dp_mon_hal_tx_ppdu_info(struct ath12k_mon_data *pmon,
-                              u16 tlv_tag)
-{
-       switch (tlv_tag) {
-       case HAL_TX_FES_SETUP:
-       case HAL_TX_FLUSH:
-       case HAL_PCU_PPDU_SETUP_INIT:
-       case HAL_TX_PEER_ENTRY:
-       case HAL_TX_QUEUE_EXTENSION:
-       case HAL_TX_MPDU_START:
-       case HAL_TX_MSDU_START:
-       case HAL_TX_DATA:
-       case HAL_MON_BUF_ADDR:
-       case HAL_TX_MPDU_END:
-       case HAL_TX_LAST_MPDU_FETCHED:
-       case HAL_TX_LAST_MPDU_END:
-       case HAL_COEX_TX_REQ:
-       case HAL_TX_RAW_OR_NATIVE_FRAME_SETUP:
-       case HAL_SCH_CRITICAL_TLV_REFERENCE:
-       case HAL_TX_FES_SETUP_COMPLETE:
-       case HAL_TQM_MPDU_GLOBAL_START:
-       case HAL_SCHEDULER_END:
-       case HAL_TX_FES_STATUS_USER_PPDU:
-               break;
-       case HAL_TX_FES_STATUS_PROT: {
-               if (!pmon->tx_prot_ppdu_info->is_used)
-                       pmon->tx_prot_ppdu_info->is_used = true;
-
-               return pmon->tx_prot_ppdu_info;
-       }
-       }
-
-       if (!pmon->tx_data_ppdu_info->is_used)
-               pmon->tx_data_ppdu_info->is_used = true;
-
-       return pmon->tx_data_ppdu_info;
-}
-
-#define MAX_MONITOR_HEADER 512
-#define MAX_DUMMY_FRM_BODY 128
-
-struct sk_buff *ath12k_dp_mon_tx_alloc_skb(void)
-{
-       struct sk_buff *skb;
-
-       skb = dev_alloc_skb(MAX_MONITOR_HEADER + MAX_DUMMY_FRM_BODY);
-       if (!skb)
-               return NULL;
-
-       skb_reserve(skb, MAX_MONITOR_HEADER);
-
-       if (!IS_ALIGNED((unsigned long)skb->data, 4))
-               skb_pull(skb, PTR_ALIGN(skb->data, 4) - skb->data);
-
-       return skb;
-}
-
-static int
-ath12k_dp_mon_tx_gen_cts2self_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       struct sk_buff *skb;
-       struct ieee80211_cts *cts;
-
-       skb = ath12k_dp_mon_tx_alloc_skb();
-       if (!skb)
-               return -ENOMEM;
-
-       cts = (struct ieee80211_cts *)skb->data;
-       memset(cts, 0, MAX_DUMMY_FRM_BODY);
-       cts->frame_control =
-               cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
-       cts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
-       memcpy(cts->ra, tx_ppdu_info->rx_status.addr1, sizeof(cts->ra));
-
-       skb_put(skb, sizeof(*cts));
-       tx_ppdu_info->tx_mon_mpdu->head = skb;
-       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
-       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
-                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
-       return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_rts_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       struct sk_buff *skb;
-       struct ieee80211_rts *rts;
-
-       skb = ath12k_dp_mon_tx_alloc_skb();
-       if (!skb)
-               return -ENOMEM;
-
-       rts = (struct ieee80211_rts *)skb->data;
-       memset(rts, 0, MAX_DUMMY_FRM_BODY);
-       rts->frame_control =
-               cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
-       rts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
-       memcpy(rts->ra, tx_ppdu_info->rx_status.addr1, sizeof(rts->ra));
-       memcpy(rts->ta, tx_ppdu_info->rx_status.addr2, sizeof(rts->ta));
-
-       skb_put(skb, sizeof(*rts));
-       tx_ppdu_info->tx_mon_mpdu->head = skb;
-       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
-       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
-                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
-       return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_3addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       struct sk_buff *skb;
-       struct ieee80211_qos_hdr *qhdr;
-
-       skb = ath12k_dp_mon_tx_alloc_skb();
-       if (!skb)
-               return -ENOMEM;
-
-       qhdr = (struct ieee80211_qos_hdr *)skb->data;
-       memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
-       qhdr->frame_control =
-               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
-       qhdr->duration_id = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
-       memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
-       memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
-       memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
-
-       skb_put(skb, sizeof(*qhdr));
-       tx_ppdu_info->tx_mon_mpdu->head = skb;
-       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
-       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
-                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
-       return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_4addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       struct sk_buff *skb;
-       struct dp_mon_qosframe_addr4 *qhdr;
-
-       skb = ath12k_dp_mon_tx_alloc_skb();
-       if (!skb)
-               return -ENOMEM;
-
-       qhdr = (struct dp_mon_qosframe_addr4 *)skb->data;
-       memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
-       qhdr->frame_control =
-               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
-       qhdr->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
-       memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
-       memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
-       memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
-       memcpy(qhdr->addr4, tx_ppdu_info->rx_status.addr4, ETH_ALEN);
-
-       skb_put(skb, sizeof(*qhdr));
-       tx_ppdu_info->tx_mon_mpdu->head = skb;
-       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
-       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
-                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
-       return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_ack_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       struct sk_buff *skb;
-       struct dp_mon_frame_min_one *fbmhdr;
-
-       skb = ath12k_dp_mon_tx_alloc_skb();
-       if (!skb)
-               return -ENOMEM;
-
-       fbmhdr = (struct dp_mon_frame_min_one *)skb->data;
-       memset(fbmhdr, 0, MAX_DUMMY_FRM_BODY);
-       fbmhdr->frame_control =
-               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_CFACK);
-       memcpy(fbmhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
-
-       /* set duration zero for ack frame */
-       fbmhdr->duration = 0;
-
-       skb_put(skb, sizeof(*fbmhdr));
-       tx_ppdu_info->tx_mon_mpdu->head = skb;
-       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
-       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
-                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
-
-       return 0;
-}
-
-static int
-ath12k_dp_mon_tx_gen_prot_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       int ret = 0;
-
-       switch (tx_ppdu_info->rx_status.medium_prot_type) {
-       case DP_MON_TX_MEDIUM_RTS_LEGACY:
-       case DP_MON_TX_MEDIUM_RTS_11AC_STATIC_BW:
-       case DP_MON_TX_MEDIUM_RTS_11AC_DYNAMIC_BW:
-               ret = ath12k_dp_mon_tx_gen_rts_frame(tx_ppdu_info);
-               break;
-       case DP_MON_TX_MEDIUM_CTS2SELF:
-               ret = ath12k_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
-               break;
-       case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_3ADDR:
-               ret = ath12k_dp_mon_tx_gen_3addr_qos_null_frame(tx_ppdu_info);
-               break;
-       case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_4ADDR:
-               ret = ath12k_dp_mon_tx_gen_4addr_qos_null_frame(tx_ppdu_info);
-               break;
-       }
-
-       return ret;
-}
-
-static enum dp_mon_tx_tlv_status
-ath12k_dp_mon_tx_parse_status_tlv(struct ath12k_base *ab,
-                                 struct ath12k_mon_data *pmon,
-                                 u16 tlv_tag, const void *tlv_data, u32 userid)
-{
-       struct dp_mon_tx_ppdu_info *tx_ppdu_info;
-       enum dp_mon_tx_tlv_status status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
-       u32 info[7];
-
-       tx_ppdu_info = ath12k_dp_mon_hal_tx_ppdu_info(pmon, tlv_tag);
-
-       switch (tlv_tag) {
-       case HAL_TX_FES_SETUP: {
-               const struct hal_tx_fes_setup *tx_fes_setup = tlv_data;
-
-               info[0] = __le32_to_cpu(tx_fes_setup->info0);
-               tx_ppdu_info->ppdu_id = __le32_to_cpu(tx_fes_setup->schedule_id);
-               tx_ppdu_info->num_users =
-                       u32_get_bits(info[0], HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
-               status = DP_MON_TX_FES_SETUP;
-               break;
-       }
-
-       case HAL_TX_FES_STATUS_END: {
-               const struct hal_tx_fes_status_end *tx_fes_status_end = tlv_data;
-               u32 tst_15_0, tst_31_16;
-
-               info[0] = __le32_to_cpu(tx_fes_status_end->info0);
-               tst_15_0 =
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_15_0);
-               tst_31_16 =
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_31_16);
-
-               tx_ppdu_info->rx_status.ppdu_ts = (tst_15_0 | (tst_31_16 << 16));
-               status = DP_MON_TX_FES_STATUS_END;
-               break;
-       }
-
-       case HAL_RX_RESPONSE_REQUIRED_INFO: {
-               const struct hal_rx_resp_req_info *rx_resp_req_info = tlv_data;
-               u32 addr_32;
-               u16 addr_16;
-
-               info[0] = __le32_to_cpu(rx_resp_req_info->info0);
-               info[1] = __le32_to_cpu(rx_resp_req_info->info1);
-               info[2] = __le32_to_cpu(rx_resp_req_info->info2);
-               info[3] = __le32_to_cpu(rx_resp_req_info->info3);
-               info[4] = __le32_to_cpu(rx_resp_req_info->info4);
-               info[5] = __le32_to_cpu(rx_resp_req_info->info5);
-
-               tx_ppdu_info->rx_status.ppdu_id =
-                       u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_PPDU_ID);
-               tx_ppdu_info->rx_status.reception_type =
-                       u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_RECEPTION_TYPE);
-               tx_ppdu_info->rx_status.rx_duration =
-                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_DURATION);
-               tx_ppdu_info->rx_status.mcs =
-                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_RATE_MCS);
-               tx_ppdu_info->rx_status.sgi =
-                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_SGI);
-               tx_ppdu_info->rx_status.is_stbc =
-                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_STBC);
-               tx_ppdu_info->rx_status.ldpc =
-                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_LDPC);
-               tx_ppdu_info->rx_status.is_ampdu =
-                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_IS_AMPDU);
-               tx_ppdu_info->rx_status.num_users =
-                       u32_get_bits(info[2], HAL_RX_RESP_REQ_INFO2_NUM_USER);
-
-               addr_32 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO3_ADDR1_31_0);
-               addr_16 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO4_ADDR1_47_32);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
-
-               addr_16 = u32_get_bits(info[4], HAL_RX_RESP_REQ_INFO4_ADDR1_15_0);
-               addr_32 = u32_get_bits(info[5], HAL_RX_RESP_REQ_INFO5_ADDR1_47_16);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
-
-               if (tx_ppdu_info->rx_status.reception_type == 0)
-                       ath12k_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
-               status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
-               break;
-       }
-
-       case HAL_PCU_PPDU_SETUP_INIT: {
-               const struct hal_tx_pcu_ppdu_setup_init *ppdu_setup = tlv_data;
-               u32 addr_32;
-               u16 addr_16;
-
-               info[0] = __le32_to_cpu(ppdu_setup->info0);
-               info[1] = __le32_to_cpu(ppdu_setup->info1);
-               info[2] = __le32_to_cpu(ppdu_setup->info2);
-               info[3] = __le32_to_cpu(ppdu_setup->info3);
-               info[4] = __le32_to_cpu(ppdu_setup->info4);
-               info[5] = __le32_to_cpu(ppdu_setup->info5);
-               info[6] = __le32_to_cpu(ppdu_setup->info6);
-
-               /* protection frame address 1 */
-               addr_32 = u32_get_bits(info[1],
-                                      HAL_TX_PPDU_SETUP_INFO1_PROT_FRAME_ADDR1_31_0);
-               addr_16 = u32_get_bits(info[2],
-                                      HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR1_47_32);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
-
-               /* protection frame address 2 */
-               addr_16 = u32_get_bits(info[2],
-                                      HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR2_15_0);
-               addr_32 = u32_get_bits(info[3],
-                                      HAL_TX_PPDU_SETUP_INFO3_PROT_FRAME_ADDR2_47_16);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
-
-               /* protection frame address 3 */
-               addr_32 = u32_get_bits(info[4],
-                                      HAL_TX_PPDU_SETUP_INFO4_PROT_FRAME_ADDR3_31_0);
-               addr_16 = u32_get_bits(info[5],
-                                      HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR3_47_32);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr3);
-
-               /* protection frame address 4 */
-               addr_16 = u32_get_bits(info[5],
-                                      HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR4_15_0);
-               addr_32 = u32_get_bits(info[6],
-                                      HAL_TX_PPDU_SETUP_INFO6_PROT_FRAME_ADDR4_47_16);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr4);
-
-               status = u32_get_bits(info[0],
-                                     HAL_TX_PPDU_SETUP_INFO0_MEDIUM_PROT_TYPE);
-               break;
-       }
-
-       case HAL_TX_QUEUE_EXTENSION: {
-               const struct hal_tx_queue_exten *tx_q_exten = tlv_data;
-
-               info[0] = __le32_to_cpu(tx_q_exten->info0);
-
-               tx_ppdu_info->rx_status.frame_control =
-                       u32_get_bits(info[0],
-                                    HAL_TX_Q_EXT_INFO0_FRAME_CTRL);
-               tx_ppdu_info->rx_status.fc_valid = true;
-               break;
-       }
-
-       case HAL_TX_FES_STATUS_START: {
-               const struct hal_tx_fes_status_start *tx_fes_start = tlv_data;
-
-               info[0] = __le32_to_cpu(tx_fes_start->info0);
-
-               tx_ppdu_info->rx_status.medium_prot_type =
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STATUS_START_INFO0_MEDIUM_PROT_TYPE);
-               break;
-       }
-
-       case HAL_TX_FES_STATUS_PROT: {
-               const struct hal_tx_fes_status_prot *tx_fes_status = tlv_data;
-               u32 start_timestamp;
-               u32 end_timestamp;
-
-               info[0] = __le32_to_cpu(tx_fes_status->info0);
-               info[1] = __le32_to_cpu(tx_fes_status->info1);
-
-               start_timestamp =
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_15_0);
-               start_timestamp |=
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_31_16) << 15;
-               end_timestamp =
-                       u32_get_bits(info[1],
-                                    HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_15_0);
-               end_timestamp |=
-                       u32_get_bits(info[1],
-                                    HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_31_16) << 15;
-               tx_ppdu_info->rx_status.rx_duration = end_timestamp - start_timestamp;
-
-               ath12k_dp_mon_tx_gen_prot_frame(tx_ppdu_info);
-               break;
-       }
-
-       case HAL_TX_FES_STATUS_START_PPDU:
-       case HAL_TX_FES_STATUS_START_PROT: {
-               const struct hal_tx_fes_status_start_prot *tx_fes_stat_start = tlv_data;
-               u64 ppdu_ts;
-
-               info[0] = __le32_to_cpu(tx_fes_stat_start->info0);
-
-               tx_ppdu_info->rx_status.ppdu_ts =
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STAT_STRT_INFO0_PROT_TS_LOWER_32);
-               ppdu_ts = (u32_get_bits(info[1],
-                                       HAL_TX_FES_STAT_STRT_INFO1_PROT_TS_UPPER_32));
-               tx_ppdu_info->rx_status.ppdu_ts |= ppdu_ts << 32;
-               break;
-       }
-
-       case HAL_TX_FES_STATUS_USER_PPDU: {
-               const struct hal_tx_fes_status_user_ppdu *tx_fes_usr_ppdu = tlv_data;
-
-               info[0] = __le32_to_cpu(tx_fes_usr_ppdu->info0);
-
-               tx_ppdu_info->rx_status.rx_duration =
-                       u32_get_bits(info[0],
-                                    HAL_TX_FES_STAT_USR_PPDU_INFO0_DURATION);
-               break;
-       }
-
-       case HAL_MACTX_HE_SIG_A_SU:
-               ath12k_dp_mon_parse_he_sig_su(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_HE_SIG_A_MU_DL:
-               ath12k_dp_mon_parse_he_sig_mu(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_HE_SIG_B1_MU:
-               ath12k_dp_mon_parse_he_sig_b1_mu(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_HE_SIG_B2_MU:
-               ath12k_dp_mon_parse_he_sig_b2_mu(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_HE_SIG_B2_OFDMA:
-               ath12k_dp_mon_parse_he_sig_b2_ofdma(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_VHT_SIG_A:
-               ath12k_dp_mon_parse_vht_sig_a(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_L_SIG_A:
-               ath12k_dp_mon_parse_l_sig_a(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_MACTX_L_SIG_B:
-               ath12k_dp_mon_parse_l_sig_b(tlv_data, &tx_ppdu_info->rx_status);
-               break;
-
-       case HAL_RX_FRAME_BITMAP_ACK: {
-               const struct hal_rx_frame_bitmap_ack *fbm_ack = tlv_data;
-               u32 addr_32;
-               u16 addr_16;
-
-               info[0] = __le32_to_cpu(fbm_ack->info0);
-               info[1] = __le32_to_cpu(fbm_ack->info1);
-
-               addr_32 = u32_get_bits(info[0],
-                                      HAL_RX_FBM_ACK_INFO0_ADDR1_31_0);
-               addr_16 = u32_get_bits(info[1],
-                                      HAL_RX_FBM_ACK_INFO1_ADDR1_47_32);
-               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
-
-               ath12k_dp_mon_tx_gen_ack_frame(tx_ppdu_info);
-               break;
-       }
-
-       case HAL_MACTX_PHY_DESC: {
-               const struct hal_tx_phy_desc *tx_phy_desc = tlv_data;
-
-               info[0] = __le32_to_cpu(tx_phy_desc->info0);
-               info[1] = __le32_to_cpu(tx_phy_desc->info1);
-               info[2] = __le32_to_cpu(tx_phy_desc->info2);
-               info[3] = __le32_to_cpu(tx_phy_desc->info3);
-
-               tx_ppdu_info->rx_status.beamformed =
-                       u32_get_bits(info[0],
-                                    HAL_TX_PHY_DESC_INFO0_BF_TYPE);
-               tx_ppdu_info->rx_status.preamble_type =
-                       u32_get_bits(info[0],
-                                    HAL_TX_PHY_DESC_INFO0_PREAMBLE_11B);
-               tx_ppdu_info->rx_status.mcs =
-                       u32_get_bits(info[1],
-                                    HAL_TX_PHY_DESC_INFO1_MCS);
-               tx_ppdu_info->rx_status.ltf_size =
-                       u32_get_bits(info[3],
-                                    HAL_TX_PHY_DESC_INFO3_LTF_SIZE);
-               tx_ppdu_info->rx_status.nss =
-                       u32_get_bits(info[2],
-                                    HAL_TX_PHY_DESC_INFO2_NSS);
-               tx_ppdu_info->rx_status.chan_num =
-                       u32_get_bits(info[3],
-                                    HAL_TX_PHY_DESC_INFO3_ACTIVE_CHANNEL);
-               tx_ppdu_info->rx_status.bw =
-                       u32_get_bits(info[0],
-                                    HAL_TX_PHY_DESC_INFO0_BANDWIDTH);
-               break;
-       }
-
-       case HAL_TX_MPDU_START: {
-               struct dp_mon_mpdu *mon_mpdu = tx_ppdu_info->tx_mon_mpdu;
-
-               mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC);
-               if (!mon_mpdu)
-                       return DP_MON_TX_STATUS_PPDU_NOT_DONE;
-               status = DP_MON_TX_MPDU_START;
-               break;
-       }
-
-       case HAL_TX_MPDU_END:
-               list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
-                             &tx_ppdu_info->dp_tx_mon_mpdu_list);
-               break;
-       }
-
-       return status;
-}
-
-enum dp_mon_tx_tlv_status
-ath12k_dp_mon_tx_status_get_num_user(u16 tlv_tag,
-                                    struct hal_tlv_hdr *tx_tlv,
-                                    u8 *num_users)
-{
-       u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
-       u32 info0;
-
-       switch (tlv_tag) {
-       case HAL_TX_FES_SETUP: {
-               struct hal_tx_fes_setup *tx_fes_setup =
-                               (struct hal_tx_fes_setup *)tx_tlv;
-
-               info0 = __le32_to_cpu(tx_fes_setup->info0);
-
-               *num_users = u32_get_bits(info0, HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
-               tlv_status = DP_MON_TX_FES_SETUP;
-               break;
-       }
-
-       case HAL_RX_RESPONSE_REQUIRED_INFO: {
-               /* TODO: need to update *num_users */
-               tlv_status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
-               break;
-       }
-       }
-
-       return tlv_status;
-}
-
-static void
-ath12k_dp_mon_tx_process_ppdu_info(struct ath12k_pdev_dp *dp_pdev,
-                                  struct napi_struct *napi,
-                                  struct dp_mon_tx_ppdu_info *tx_ppdu_info)
-{
-       struct dp_mon_mpdu *tmp, *mon_mpdu;
-
-       list_for_each_entry_safe(mon_mpdu, tmp,
-                                &tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
-               list_del(&mon_mpdu->list);
-
-               if (mon_mpdu->head)
-                       ath12k_dp_mon_rx_deliver(dp_pdev, mon_mpdu,
-                                                &tx_ppdu_info->rx_status, napi);
-
-               kfree(mon_mpdu);
-       }
-}
-
-enum hal_rx_mon_status
-ath12k_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
-                                 struct ath12k_mon_data *pmon,
-                                 struct sk_buff *skb,
-                                 struct napi_struct *napi,
-                                 u32 ppdu_id)
-{
-       struct ath12k_dp *dp = dp_pdev->dp;
-       struct ath12k_base *ab = dp->ab;
-       struct dp_mon_tx_ppdu_info *tx_prot_ppdu_info, *tx_data_ppdu_info;
-       struct hal_tlv_hdr *tlv;
-       u8 *ptr = skb->data;
-       u16 tlv_tag;
-       u16 tlv_len;
-       u32 tlv_userid = 0;
-       u8 num_user;
-       u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
-
-       tx_prot_ppdu_info = ath12k_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
-                                                          DP_MON_TX_PROT_PPDU_INFO);
-       if (!tx_prot_ppdu_info)
-               return -ENOMEM;
-
-       tlv = (struct hal_tlv_hdr *)ptr;
-       tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
-
-       tlv_status = ath12k_dp_mon_tx_status_get_num_user(tlv_tag, tlv, &num_user);
-       if (tlv_status == DP_MON_TX_STATUS_PPDU_NOT_DONE || !num_user)
-               return -EINVAL;
-
-       tx_data_ppdu_info = ath12k_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
-                                                          DP_MON_TX_DATA_PPDU_INFO);
-       if (!tx_data_ppdu_info)
-               return -ENOMEM;
-
-       do {
-               tlv = (struct hal_tlv_hdr *)ptr;
-               tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
-               tlv_len = le32_get_bits(tlv->tl, HAL_TLV_HDR_LEN);
-               tlv_userid = le32_get_bits(tlv->tl, HAL_TLV_USR_ID);
-
-               tlv_status = ath12k_dp_mon_tx_parse_status_tlv(ab, pmon,
-                                                              tlv_tag, ptr,
-                                                              tlv_userid);
-               ptr += tlv_len;
-               ptr = PTR_ALIGN(ptr, HAL_TLV_ALIGN);
-               if ((ptr - skb->data) >= DP_TX_MONITOR_BUF_SIZE)
-                       break;
-       } while (tlv_status != DP_MON_TX_FES_STATUS_END);
-
-       ath12k_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_data_ppdu_info);
-       ath12k_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_prot_ppdu_info);
-
-       return tlv_status;
-}
-
 static void
 ath12k_dp_mon_rx_update_peer_rate_table_stats(struct ath12k_rx_peer_stats *rx_stats,
                                              struct hal_rx_mon_ppdu_info *ppdu_info,
index bfea7d4041cb9dcbf8a31469ee0550ab1768da3c..1d2ec4072a83cac76f608c96df70c9e188873bb3 100644 (file)
@@ -85,17 +85,6 @@ int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
 int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
                                        struct dp_rxdma_mon_ring *rx_ring,
                                        int req_entries);
-struct sk_buff *ath12k_dp_mon_tx_alloc_skb(void);
-enum dp_mon_tx_tlv_status
-ath12k_dp_mon_tx_status_get_num_user(u16 tlv_tag,
-                                    struct hal_tlv_hdr *tx_tlv,
-                                    u8 *num_users);
-enum hal_rx_mon_status
-ath12k_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
-                                 struct ath12k_mon_data *pmon,
-                                 struct sk_buff *skb,
-                                 struct napi_struct *napi,
-                                 u32 ppdu_id);
 void ath12k_dp_mon_rx_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info);
 void
 ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k_base *ab,
index 076fb75a101f199a964baf5961d7fa4e6fdb3ddb..abdfd3cfd0e48048fc2f42fa6a5e58cdb8e16222 100644 (file)
@@ -331,6 +331,682 @@ ath12k_wifi7_dp_mon_parse_rx_dest_tlv(struct ath12k_pdev_dp *dp_pdev,
        return 0;
 }
 
+static struct dp_mon_tx_ppdu_info *
+ath12k_wifi7_dp_mon_tx_get_ppdu_info(struct ath12k_mon_data *pmon,
+                                    unsigned int ppdu_id,
+                                    enum dp_mon_tx_ppdu_info_type type)
+{
+       struct dp_mon_tx_ppdu_info *tx_ppdu_info;
+
+       if (type == DP_MON_TX_PROT_PPDU_INFO) {
+               tx_ppdu_info = pmon->tx_prot_ppdu_info;
+
+               if (tx_ppdu_info && !tx_ppdu_info->is_used)
+                       return tx_ppdu_info;
+               kfree(tx_ppdu_info);
+       } else {
+               tx_ppdu_info = pmon->tx_data_ppdu_info;
+
+               if (tx_ppdu_info && !tx_ppdu_info->is_used)
+                       return tx_ppdu_info;
+               kfree(tx_ppdu_info);
+       }
+
+       /* allocate new tx_ppdu_info */
+       tx_ppdu_info = kzalloc(sizeof(*tx_ppdu_info), GFP_ATOMIC);
+       if (!tx_ppdu_info)
+               return NULL;
+
+       tx_ppdu_info->is_used = 0;
+       tx_ppdu_info->ppdu_id = ppdu_id;
+
+       if (type == DP_MON_TX_PROT_PPDU_INFO)
+               pmon->tx_prot_ppdu_info = tx_ppdu_info;
+       else
+               pmon->tx_data_ppdu_info = tx_ppdu_info;
+
+       return tx_ppdu_info;
+}
+
+static struct dp_mon_tx_ppdu_info *
+ath12k_wifi7_dp_mon_hal_tx_ppdu_info(struct ath12k_mon_data *pmon,
+                                    u16 tlv_tag)
+{
+       switch (tlv_tag) {
+       case HAL_TX_FES_SETUP:
+       case HAL_TX_FLUSH:
+       case HAL_PCU_PPDU_SETUP_INIT:
+       case HAL_TX_PEER_ENTRY:
+       case HAL_TX_QUEUE_EXTENSION:
+       case HAL_TX_MPDU_START:
+       case HAL_TX_MSDU_START:
+       case HAL_TX_DATA:
+       case HAL_MON_BUF_ADDR:
+       case HAL_TX_MPDU_END:
+       case HAL_TX_LAST_MPDU_FETCHED:
+       case HAL_TX_LAST_MPDU_END:
+       case HAL_COEX_TX_REQ:
+       case HAL_TX_RAW_OR_NATIVE_FRAME_SETUP:
+       case HAL_SCH_CRITICAL_TLV_REFERENCE:
+       case HAL_TX_FES_SETUP_COMPLETE:
+       case HAL_TQM_MPDU_GLOBAL_START:
+       case HAL_SCHEDULER_END:
+       case HAL_TX_FES_STATUS_USER_PPDU:
+               break;
+       case HAL_TX_FES_STATUS_PROT: {
+               if (!pmon->tx_prot_ppdu_info->is_used)
+                       pmon->tx_prot_ppdu_info->is_used = true;
+
+               return pmon->tx_prot_ppdu_info;
+       }
+       }
+
+       if (!pmon->tx_data_ppdu_info->is_used)
+               pmon->tx_data_ppdu_info->is_used = true;
+
+       return pmon->tx_data_ppdu_info;
+}
+
+#define MAX_MONITOR_HEADER 512
+#define MAX_DUMMY_FRM_BODY 128
+
+static struct
+sk_buff *ath12k_wifi7_dp_mon_tx_alloc_skb(void)
+{
+       struct sk_buff *skb;
+
+       skb = dev_alloc_skb(MAX_MONITOR_HEADER + MAX_DUMMY_FRM_BODY);
+       if (!skb)
+               return NULL;
+
+       skb_reserve(skb, MAX_MONITOR_HEADER);
+
+       if (!IS_ALIGNED((unsigned long)skb->data, 4))
+               skb_pull(skb, PTR_ALIGN(skb->data, 4) - skb->data);
+
+       return skb;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_cts2self_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       struct sk_buff *skb;
+       struct ieee80211_cts *cts;
+
+       skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+       if (!skb)
+               return -ENOMEM;
+
+       cts = (struct ieee80211_cts *)skb->data;
+       memset(cts, 0, MAX_DUMMY_FRM_BODY);
+       cts->frame_control =
+               cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
+       cts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+       memcpy(cts->ra, tx_ppdu_info->rx_status.addr1, sizeof(cts->ra));
+
+       skb_put(skb, sizeof(*cts));
+       tx_ppdu_info->tx_mon_mpdu->head = skb;
+       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+       return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_rts_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       struct sk_buff *skb;
+       struct ieee80211_rts *rts;
+
+       skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+       if (!skb)
+               return -ENOMEM;
+
+       rts = (struct ieee80211_rts *)skb->data;
+       memset(rts, 0, MAX_DUMMY_FRM_BODY);
+       rts->frame_control =
+               cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
+       rts->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+       memcpy(rts->ra, tx_ppdu_info->rx_status.addr1, sizeof(rts->ra));
+       memcpy(rts->ta, tx_ppdu_info->rx_status.addr2, sizeof(rts->ta));
+
+       skb_put(skb, sizeof(*rts));
+       tx_ppdu_info->tx_mon_mpdu->head = skb;
+       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+       return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_3addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       struct sk_buff *skb;
+       struct ieee80211_qos_hdr *qhdr;
+
+       skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+       if (!skb)
+               return -ENOMEM;
+
+       qhdr = (struct ieee80211_qos_hdr *)skb->data;
+       memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
+       qhdr->frame_control =
+               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
+       qhdr->duration_id = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+       memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
+       memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
+       memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
+
+       skb_put(skb, sizeof(*qhdr));
+       tx_ppdu_info->tx_mon_mpdu->head = skb;
+       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+       return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_4addr_qos_null_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       struct sk_buff *skb;
+       struct dp_mon_qosframe_addr4 *qhdr;
+
+       skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+       if (!skb)
+               return -ENOMEM;
+
+       qhdr = (struct dp_mon_qosframe_addr4 *)skb->data;
+       memset(qhdr, 0, MAX_DUMMY_FRM_BODY);
+       qhdr->frame_control =
+               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
+       qhdr->duration = cpu_to_le16(tx_ppdu_info->rx_status.rx_duration);
+       memcpy(qhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
+       memcpy(qhdr->addr2, tx_ppdu_info->rx_status.addr2, ETH_ALEN);
+       memcpy(qhdr->addr3, tx_ppdu_info->rx_status.addr3, ETH_ALEN);
+       memcpy(qhdr->addr4, tx_ppdu_info->rx_status.addr4, ETH_ALEN);
+
+       skb_put(skb, sizeof(*qhdr));
+       tx_ppdu_info->tx_mon_mpdu->head = skb;
+       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+       return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_ack_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       struct sk_buff *skb;
+       struct dp_mon_frame_min_one *fbmhdr;
+
+       skb = ath12k_wifi7_dp_mon_tx_alloc_skb();
+       if (!skb)
+               return -ENOMEM;
+
+       fbmhdr = (struct dp_mon_frame_min_one *)skb->data;
+       memset(fbmhdr, 0, MAX_DUMMY_FRM_BODY);
+       fbmhdr->frame_control =
+               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_CFACK);
+       memcpy(fbmhdr->addr1, tx_ppdu_info->rx_status.addr1, ETH_ALEN);
+
+       /* set duration zero for ack frame */
+       fbmhdr->duration = 0;
+
+       skb_put(skb, sizeof(*fbmhdr));
+       tx_ppdu_info->tx_mon_mpdu->head = skb;
+       tx_ppdu_info->tx_mon_mpdu->tail = NULL;
+       list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+                     &tx_ppdu_info->dp_tx_mon_mpdu_list);
+
+       return 0;
+}
+
+static int
+ath12k_wifi7_dp_mon_tx_gen_prot_frame(struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       int ret = 0;
+
+       switch (tx_ppdu_info->rx_status.medium_prot_type) {
+       case DP_MON_TX_MEDIUM_RTS_LEGACY:
+       case DP_MON_TX_MEDIUM_RTS_11AC_STATIC_BW:
+       case DP_MON_TX_MEDIUM_RTS_11AC_DYNAMIC_BW:
+               ret = ath12k_wifi7_dp_mon_tx_gen_rts_frame(tx_ppdu_info);
+               break;
+       case DP_MON_TX_MEDIUM_CTS2SELF:
+               ret = ath12k_wifi7_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
+               break;
+       case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_3ADDR:
+               ret = ath12k_wifi7_dp_mon_tx_gen_3addr_qos_null_frame(tx_ppdu_info);
+               break;
+       case DP_MON_TX_MEDIUM_QOS_NULL_NO_ACK_4ADDR:
+               ret = ath12k_wifi7_dp_mon_tx_gen_4addr_qos_null_frame(tx_ppdu_info);
+               break;
+       }
+
+       return ret;
+}
+
+static enum dp_mon_tx_tlv_status
+ath12k_wifi7_dp_mon_tx_parse_status_tlv(struct ath12k_base *ab,
+                                       struct ath12k_mon_data *pmon,
+                                       u16 tlv_tag, const void *tlv_data,
+                                       u32 userid)
+{
+       struct dp_mon_tx_ppdu_info *tx_ppdu_info;
+       enum dp_mon_tx_tlv_status status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
+       u32 info[7];
+
+       tx_ppdu_info = ath12k_wifi7_dp_mon_hal_tx_ppdu_info(pmon, tlv_tag);
+
+       switch (tlv_tag) {
+       case HAL_TX_FES_SETUP: {
+               const struct hal_tx_fes_setup *tx_fes_setup = tlv_data;
+
+               info[0] = __le32_to_cpu(tx_fes_setup->info0);
+               tx_ppdu_info->ppdu_id = __le32_to_cpu(tx_fes_setup->schedule_id);
+               tx_ppdu_info->num_users =
+                       u32_get_bits(info[0], HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
+               status = DP_MON_TX_FES_SETUP;
+               break;
+       }
+
+       case HAL_TX_FES_STATUS_END: {
+               const struct hal_tx_fes_status_end *tx_fes_status_end = tlv_data;
+               u32 tst_15_0, tst_31_16;
+
+               info[0] = __le32_to_cpu(tx_fes_status_end->info0);
+               tst_15_0 =
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_15_0);
+               tst_31_16 =
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STATUS_END_INFO0_START_TIMESTAMP_31_16);
+
+               tx_ppdu_info->rx_status.ppdu_ts = (tst_15_0 | (tst_31_16 << 16));
+               status = DP_MON_TX_FES_STATUS_END;
+               break;
+       }
+
+       case HAL_RX_RESPONSE_REQUIRED_INFO: {
+               const struct hal_rx_resp_req_info *rx_resp_req_info = tlv_data;
+               u32 addr_32;
+               u16 addr_16;
+
+               info[0] = __le32_to_cpu(rx_resp_req_info->info0);
+               info[1] = __le32_to_cpu(rx_resp_req_info->info1);
+               info[2] = __le32_to_cpu(rx_resp_req_info->info2);
+               info[3] = __le32_to_cpu(rx_resp_req_info->info3);
+               info[4] = __le32_to_cpu(rx_resp_req_info->info4);
+               info[5] = __le32_to_cpu(rx_resp_req_info->info5);
+
+               tx_ppdu_info->rx_status.ppdu_id =
+                       u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_PPDU_ID);
+               tx_ppdu_info->rx_status.reception_type =
+                       u32_get_bits(info[0], HAL_RX_RESP_REQ_INFO0_RECEPTION_TYPE);
+               tx_ppdu_info->rx_status.rx_duration =
+                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_DURATION);
+               tx_ppdu_info->rx_status.mcs =
+                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_RATE_MCS);
+               tx_ppdu_info->rx_status.sgi =
+                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_SGI);
+               tx_ppdu_info->rx_status.is_stbc =
+                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_STBC);
+               tx_ppdu_info->rx_status.ldpc =
+                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_LDPC);
+               tx_ppdu_info->rx_status.is_ampdu =
+                       u32_get_bits(info[1], HAL_RX_RESP_REQ_INFO1_IS_AMPDU);
+               tx_ppdu_info->rx_status.num_users =
+                       u32_get_bits(info[2], HAL_RX_RESP_REQ_INFO2_NUM_USER);
+
+               addr_32 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO3_ADDR1_31_0);
+               addr_16 = u32_get_bits(info[3], HAL_RX_RESP_REQ_INFO4_ADDR1_47_32);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
+
+               addr_16 = u32_get_bits(info[4], HAL_RX_RESP_REQ_INFO4_ADDR1_15_0);
+               addr_32 = u32_get_bits(info[5], HAL_RX_RESP_REQ_INFO5_ADDR1_47_16);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
+
+               if (tx_ppdu_info->rx_status.reception_type == 0)
+                       ath12k_wifi7_dp_mon_tx_gen_cts2self_frame(tx_ppdu_info);
+               status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
+               break;
+       }
+
+       case HAL_PCU_PPDU_SETUP_INIT: {
+               const struct hal_tx_pcu_ppdu_setup_init *ppdu_setup = tlv_data;
+               u32 addr_32;
+               u16 addr_16;
+
+               info[0] = __le32_to_cpu(ppdu_setup->info0);
+               info[1] = __le32_to_cpu(ppdu_setup->info1);
+               info[2] = __le32_to_cpu(ppdu_setup->info2);
+               info[3] = __le32_to_cpu(ppdu_setup->info3);
+               info[4] = __le32_to_cpu(ppdu_setup->info4);
+               info[5] = __le32_to_cpu(ppdu_setup->info5);
+               info[6] = __le32_to_cpu(ppdu_setup->info6);
+
+               /* protection frame address 1 */
+               addr_32 = u32_get_bits(info[1],
+                                      HAL_TX_PPDU_SETUP_INFO1_PROT_FRAME_ADDR1_31_0);
+               addr_16 = u32_get_bits(info[2],
+                                      HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR1_47_32);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
+
+               /* protection frame address 2 */
+               addr_16 = u32_get_bits(info[2],
+                                      HAL_TX_PPDU_SETUP_INFO2_PROT_FRAME_ADDR2_15_0);
+               addr_32 = u32_get_bits(info[3],
+                                      HAL_TX_PPDU_SETUP_INFO3_PROT_FRAME_ADDR2_47_16);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr2);
+
+               /* protection frame address 3 */
+               addr_32 = u32_get_bits(info[4],
+                                      HAL_TX_PPDU_SETUP_INFO4_PROT_FRAME_ADDR3_31_0);
+               addr_16 = u32_get_bits(info[5],
+                                      HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR3_47_32);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr3);
+
+               /* protection frame address 4 */
+               addr_16 = u32_get_bits(info[5],
+                                      HAL_TX_PPDU_SETUP_INFO5_PROT_FRAME_ADDR4_15_0);
+               addr_32 = u32_get_bits(info[6],
+                                      HAL_TX_PPDU_SETUP_INFO6_PROT_FRAME_ADDR4_47_16);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr4);
+
+               status = u32_get_bits(info[0],
+                                     HAL_TX_PPDU_SETUP_INFO0_MEDIUM_PROT_TYPE);
+               break;
+       }
+
+       case HAL_TX_QUEUE_EXTENSION: {
+               const struct hal_tx_queue_exten *tx_q_exten = tlv_data;
+
+               info[0] = __le32_to_cpu(tx_q_exten->info0);
+
+               tx_ppdu_info->rx_status.frame_control =
+                       u32_get_bits(info[0],
+                                    HAL_TX_Q_EXT_INFO0_FRAME_CTRL);
+               tx_ppdu_info->rx_status.fc_valid = true;
+               break;
+       }
+
+       case HAL_TX_FES_STATUS_START: {
+               const struct hal_tx_fes_status_start *tx_fes_start = tlv_data;
+
+               info[0] = __le32_to_cpu(tx_fes_start->info0);
+
+               tx_ppdu_info->rx_status.medium_prot_type =
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STATUS_START_INFO0_MEDIUM_PROT_TYPE);
+               break;
+       }
+
+       case HAL_TX_FES_STATUS_PROT: {
+               const struct hal_tx_fes_status_prot *tx_fes_status = tlv_data;
+               u32 start_timestamp;
+               u32 end_timestamp;
+
+               info[0] = __le32_to_cpu(tx_fes_status->info0);
+               info[1] = __le32_to_cpu(tx_fes_status->info1);
+
+               start_timestamp =
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_15_0);
+               start_timestamp |=
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STAT_PROT_INFO0_STRT_FRM_TS_31_16) << 15;
+               end_timestamp =
+                       u32_get_bits(info[1],
+                                    HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_15_0);
+               end_timestamp |=
+                       u32_get_bits(info[1],
+                                    HAL_TX_FES_STAT_PROT_INFO1_END_FRM_TS_31_16) << 15;
+               tx_ppdu_info->rx_status.rx_duration = end_timestamp - start_timestamp;
+
+               ath12k_wifi7_dp_mon_tx_gen_prot_frame(tx_ppdu_info);
+               break;
+       }
+
+       case HAL_TX_FES_STATUS_START_PPDU:
+       case HAL_TX_FES_STATUS_START_PROT: {
+               const struct hal_tx_fes_status_start_prot *tx_fes_stat_start = tlv_data;
+               u64 ppdu_ts;
+
+               info[0] = __le32_to_cpu(tx_fes_stat_start->info0);
+
+               tx_ppdu_info->rx_status.ppdu_ts =
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STAT_STRT_INFO0_PROT_TS_LOWER_32);
+               ppdu_ts = (u32_get_bits(info[1],
+                                       HAL_TX_FES_STAT_STRT_INFO1_PROT_TS_UPPER_32));
+               tx_ppdu_info->rx_status.ppdu_ts |= ppdu_ts << 32;
+               break;
+       }
+
+       case HAL_TX_FES_STATUS_USER_PPDU: {
+               const struct hal_tx_fes_status_user_ppdu *tx_fes_usr_ppdu = tlv_data;
+
+               info[0] = __le32_to_cpu(tx_fes_usr_ppdu->info0);
+
+               tx_ppdu_info->rx_status.rx_duration =
+                       u32_get_bits(info[0],
+                                    HAL_TX_FES_STAT_USR_PPDU_INFO0_DURATION);
+               break;
+       }
+
+       case HAL_MACTX_HE_SIG_A_SU:
+               ath12k_dp_mon_parse_he_sig_su(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_HE_SIG_A_MU_DL:
+               ath12k_dp_mon_parse_he_sig_mu(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_HE_SIG_B1_MU:
+               ath12k_dp_mon_parse_he_sig_b1_mu(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_HE_SIG_B2_MU:
+               ath12k_dp_mon_parse_he_sig_b2_mu(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_HE_SIG_B2_OFDMA:
+               ath12k_dp_mon_parse_he_sig_b2_ofdma(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_VHT_SIG_A:
+               ath12k_dp_mon_parse_vht_sig_a(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_L_SIG_A:
+               ath12k_dp_mon_parse_l_sig_a(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_MACTX_L_SIG_B:
+               ath12k_dp_mon_parse_l_sig_b(tlv_data, &tx_ppdu_info->rx_status);
+               break;
+
+       case HAL_RX_FRAME_BITMAP_ACK: {
+               const struct hal_rx_frame_bitmap_ack *fbm_ack = tlv_data;
+               u32 addr_32;
+               u16 addr_16;
+
+               info[0] = __le32_to_cpu(fbm_ack->info0);
+               info[1] = __le32_to_cpu(fbm_ack->info1);
+
+               addr_32 = u32_get_bits(info[0],
+                                      HAL_RX_FBM_ACK_INFO0_ADDR1_31_0);
+               addr_16 = u32_get_bits(info[1],
+                                      HAL_RX_FBM_ACK_INFO1_ADDR1_47_32);
+               ath12k_dp_get_mac_addr(addr_32, addr_16, tx_ppdu_info->rx_status.addr1);
+
+               ath12k_wifi7_dp_mon_tx_gen_ack_frame(tx_ppdu_info);
+               break;
+       }
+
+       case HAL_MACTX_PHY_DESC: {
+               const struct hal_tx_phy_desc *tx_phy_desc = tlv_data;
+
+               info[0] = __le32_to_cpu(tx_phy_desc->info0);
+               info[1] = __le32_to_cpu(tx_phy_desc->info1);
+               info[2] = __le32_to_cpu(tx_phy_desc->info2);
+               info[3] = __le32_to_cpu(tx_phy_desc->info3);
+
+               tx_ppdu_info->rx_status.beamformed =
+                       u32_get_bits(info[0],
+                                    HAL_TX_PHY_DESC_INFO0_BF_TYPE);
+               tx_ppdu_info->rx_status.preamble_type =
+                       u32_get_bits(info[0],
+                                    HAL_TX_PHY_DESC_INFO0_PREAMBLE_11B);
+               tx_ppdu_info->rx_status.mcs =
+                       u32_get_bits(info[1],
+                                    HAL_TX_PHY_DESC_INFO1_MCS);
+               tx_ppdu_info->rx_status.ltf_size =
+                       u32_get_bits(info[3],
+                                    HAL_TX_PHY_DESC_INFO3_LTF_SIZE);
+               tx_ppdu_info->rx_status.nss =
+                       u32_get_bits(info[2],
+                                    HAL_TX_PHY_DESC_INFO2_NSS);
+               tx_ppdu_info->rx_status.chan_num =
+                       u32_get_bits(info[3],
+                                    HAL_TX_PHY_DESC_INFO3_ACTIVE_CHANNEL);
+               tx_ppdu_info->rx_status.bw =
+                       u32_get_bits(info[0],
+                                    HAL_TX_PHY_DESC_INFO0_BANDWIDTH);
+               break;
+       }
+
+       case HAL_TX_MPDU_START: {
+               struct dp_mon_mpdu *mon_mpdu = tx_ppdu_info->tx_mon_mpdu;
+
+               mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC);
+               if (!mon_mpdu)
+                       return DP_MON_TX_STATUS_PPDU_NOT_DONE;
+               status = DP_MON_TX_MPDU_START;
+               break;
+       }
+
+       case HAL_TX_MPDU_END:
+               list_add_tail(&tx_ppdu_info->tx_mon_mpdu->list,
+                             &tx_ppdu_info->dp_tx_mon_mpdu_list);
+               break;
+       }
+
+       return status;
+}
+
+static enum dp_mon_tx_tlv_status
+ath12k_wifi7_dp_mon_tx_status_get_num_user(u16 tlv_tag,
+                                          struct hal_tlv_hdr *tx_tlv,
+                                          u8 *num_users)
+{
+       u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
+       u32 info0;
+
+       switch (tlv_tag) {
+       case HAL_TX_FES_SETUP: {
+               struct hal_tx_fes_setup *tx_fes_setup =
+                               (struct hal_tx_fes_setup *)tx_tlv;
+
+               info0 = __le32_to_cpu(tx_fes_setup->info0);
+
+               *num_users = u32_get_bits(info0, HAL_TX_FES_SETUP_INFO0_NUM_OF_USERS);
+               tlv_status = DP_MON_TX_FES_SETUP;
+               break;
+       }
+
+       case HAL_RX_RESPONSE_REQUIRED_INFO: {
+               /* TODO: need to update *num_users */
+               tlv_status = DP_MON_RX_RESPONSE_REQUIRED_INFO;
+               break;
+       }
+       }
+
+       return tlv_status;
+}
+
+static void
+ath12k_wifi7_dp_mon_tx_process_ppdu_info(struct ath12k_pdev_dp *dp_pdev,
+                                        struct napi_struct *napi,
+                                        struct dp_mon_tx_ppdu_info *tx_ppdu_info)
+{
+       struct dp_mon_mpdu *tmp, *mon_mpdu;
+
+       list_for_each_entry_safe(mon_mpdu, tmp,
+                                &tx_ppdu_info->dp_tx_mon_mpdu_list, list) {
+               list_del(&mon_mpdu->list);
+
+               if (mon_mpdu->head)
+                       ath12k_dp_mon_rx_deliver(dp_pdev, mon_mpdu,
+                                                &tx_ppdu_info->rx_status, napi);
+
+               kfree(mon_mpdu);
+       }
+}
+
+enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
+                                       struct ath12k_mon_data *pmon,
+                                       struct sk_buff *skb,
+                                       struct napi_struct *napi,
+                                       u32 ppdu_id)
+{
+       struct ath12k_dp *dp = dp_pdev->dp;
+       struct ath12k_base *ab = dp->ab;
+       struct dp_mon_tx_ppdu_info *tx_prot_ppdu_info, *tx_data_ppdu_info;
+       struct hal_tlv_hdr *tlv;
+       u8 *ptr = skb->data;
+       u16 tlv_tag;
+       u16 tlv_len;
+       u32 tlv_userid = 0;
+       u8 num_user;
+       u32 tlv_status = DP_MON_TX_STATUS_PPDU_NOT_DONE;
+
+       tx_prot_ppdu_info =
+               ath12k_wifi7_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
+                                                    DP_MON_TX_PROT_PPDU_INFO);
+       if (!tx_prot_ppdu_info)
+               return -ENOMEM;
+
+       tlv = (struct hal_tlv_hdr *)ptr;
+       tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
+
+       tlv_status = ath12k_wifi7_dp_mon_tx_status_get_num_user(tlv_tag, tlv,
+                                                               &num_user);
+       if (tlv_status == DP_MON_TX_STATUS_PPDU_NOT_DONE || !num_user)
+               return -EINVAL;
+
+       tx_data_ppdu_info =
+               ath12k_wifi7_dp_mon_tx_get_ppdu_info(pmon, ppdu_id,
+                                                    DP_MON_TX_DATA_PPDU_INFO);
+       if (!tx_data_ppdu_info)
+               return -ENOMEM;
+
+       do {
+               tlv = (struct hal_tlv_hdr *)ptr;
+               tlv_tag = le32_get_bits(tlv->tl, HAL_TLV_HDR_TAG);
+               tlv_len = le32_get_bits(tlv->tl, HAL_TLV_HDR_LEN);
+               tlv_userid = le32_get_bits(tlv->tl, HAL_TLV_USR_ID);
+
+               tlv_status = ath12k_wifi7_dp_mon_tx_parse_status_tlv(ab, pmon,
+                                                                    tlv_tag, ptr,
+                                                                    tlv_userid);
+               ptr += tlv_len;
+               ptr = PTR_ALIGN(ptr, HAL_TLV_ALIGN);
+               if ((ptr - skb->data) >= DP_TX_MONITOR_BUF_SIZE)
+                       break;
+       } while (tlv_status != DP_MON_TX_FES_STATUS_END);
+
+       ath12k_wifi7_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_data_ppdu_info);
+       ath12k_wifi7_dp_mon_tx_process_ppdu_info(dp_pdev, napi, tx_prot_ppdu_info);
+
+       return tlv_status;
+}
+
 static u32
 ath12k_wifi7_dp_rx_mon_mpdu_pop(struct ath12k *ar, int mac_id,
                                void *ring_entry, struct sk_buff **head_msdu,
index 3cf82864c41cd1bffbafd3540c2a1b5be3ca2b57..148d1e0b70fe82513267d0b8d83588b46bd6749d 100644 (file)
@@ -14,4 +14,10 @@ enum dp_monitor_mode;
 int ath12k_wifi7_dp_mon_process_ring(struct ath12k_dp *dp, int mac_id,
                                     struct napi_struct *napi, int budget,
                                     enum dp_monitor_mode monitor_mode);
+enum hal_rx_mon_status
+ath12k_wifi7_dp_mon_tx_parse_mon_status(struct ath12k_pdev_dp *dp_pdev,
+                                       struct ath12k_mon_data *pmon,
+                                       struct sk_buff *skb,
+                                       struct napi_struct *napi,
+                                       u32 ppdu_id);
 #endif