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 --- drivers/net/wireless/ath/ath12k/dp_mon.c | 671 ----------------- drivers/net/wireless/ath/ath12k/dp_mon.h | 11 - .../net/wireless/ath/ath12k/wifi7/dp_mon.c | 676 ++++++++++++++++++ .../net/wireless/ath/ath12k/wifi7/dp_mon.h | 6 + 4 files changed, 682 insertions(+), 682 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c index dc4827771a64..d3e662399c31 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c @@ -2366,677 +2366,6 @@ int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab, 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, diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.h b/drivers/net/wireless/ath/ath12k/dp_mon.h index bfea7d4041cb..1d2ec4072a83 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.h +++ b/drivers/net/wireless/ath/ath12k/dp_mon.h @@ -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, diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c index 076fb75a101f..abdfd3cfd0e4 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c @@ -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, diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h index 3cf82864c41c..148d1e0b70fe 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.h @@ -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 -- 2.34.1