diff --git a/hal/wifi3.0/be/hal_be_api_mon.h b/hal/wifi3.0/be/hal_be_api_mon.h index c81f2f2a1f..de4e3ec354 100644 --- a/hal/wifi3.0/be/hal_be_api_mon.h +++ b/hal/wifi3.0/be/hal_be_api_mon.h @@ -238,6 +238,48 @@ enum hal_tx_tlv_status { HAL_MON_TX_STATUS_PPDU_NOT_DONE, }; +enum txmon_transmission_type { + TXMON_SU_TRANSMISSION = 0, + TXMON_MU_TRANSMISSION, + TXMON_MU_SU_TRANSMISSION, + TXMON_MU_MIMO_TRANSMISSION = 1, + TXMON_MU_OFDMA_TRANMISSION +}; + +#define TXMON_HAL(hal_tx_ppdu_info, field) \ + hal_tx_ppdu_info->field +#define TXMON_HAL_STATUS(hal_tx_ppdu_info, field) \ + hal_tx_ppdu_info->rx_status.field +#define TXMON_HAL_USER(hal_tx_ppdu_info, user_id, field) \ + hal_tx_ppdu_info->rx_user_status[user_id].field + +#define TXMON_STATUS_INFO(hal_tx_status_info, field) \ + hal_tx_status_info->field + +struct hal_tx_status_info { + uint8_t reception_type; + uint8_t transmission_type; + uint8_t medium_prot_type; + + void *buffer; + uint32_t offset; + uint32_t len_bytes; +}; + +struct hal_tx_ppdu_info { + uint32_t ppdu_id; + + uint32_t num_users :8, + is_used :1, + is_data :1, + reserved :23; + + uint32_t prot_tlv_status; + + struct mon_rx_status rx_status; + struct mon_rx_user_status rx_user_status[]; +}; + /** * hal_tx_status_get_next_tlv() - get next tx status TLV * @tx_tlv: pointer to TLV header @@ -255,7 +297,57 @@ hal_tx_status_get_next_tlv(uint8_t *tx_tlv) { HAL_RX_TLV32_HDR_SIZE + 3)) & (~3)); } -/* +/** + * hal_txmon_status_parse_tlv() - process transmit info TLV + * @hal_soc: HAL soc handle + * @data_ppdu_info: pointer to hal data ppdu info + * @prot_ppdu_info: pointer to hal prot ppdu info + * @data_status_info: pointer to data status info + * @prot_status_info: pointer to prot status info + * @tx_tlv_hdr: pointer to TLV header + * @status_frag: pointer to status frag + * + * Return: HAL_TLV_STATUS_PPDU_NOT_DONE + */ +static inline uint32_t +hal_txmon_status_parse_tlv(hal_soc_handle_t hal_soc_hdl, + void *data_ppdu_info, + void *prot_ppdu_info, + void *data_status_info, + void *prot_status_info, + void *tx_tlv_hdr, + qdf_frag_t status_frag) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_txmon_status_parse_tlv(data_ppdu_info, + prot_ppdu_info, + data_status_info, + prot_status_info, + tx_tlv_hdr, + status_frag); +} + +/** + * hal_txmon_status_get_num_users() - api to get num users from start of fes + * window + * @hal_soc: HAL soc handle + * @tx_tlv_hdr: pointer to TLV header + * @num_users: reference to number of user + * + * Return: status + */ +static inline uint32_t +hal_txmon_status_get_num_users(hal_soc_handle_t hal_soc_hdl, + void *tx_tlv_hdr, uint8_t *num_users) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_txmon_status_get_num_users(tx_tlv_hdr, + num_users); +} + +/** * hal_txmon_status_free_buffer() - api to free status buffer * @hal_soc: HAL soc handle * @status_frag: qdf_frag_t buffer @@ -271,5 +363,21 @@ hal_txmon_status_free_buffer(hal_soc_handle_t hal_soc_hdl, if (hal_soc->ops->hal_txmon_status_free_buffer) hal_soc->ops->hal_txmon_status_free_buffer(status_frag); } + +/** + * hal_tx_status_get_tlv_tag() - api to get tlv tag + * @tx_tlv_hdr: pointer to TLV header + * + * Return tlv_tag + */ +static inline uint32_t +hal_tx_status_get_tlv_tag(void *tx_tlv_hdr) +{ + uint32_t tlv_tag = 0; + + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(tx_tlv_hdr); + + return tlv_tag; +} #endif /* QCA_MONITOR_2_0_SUPPORT */ #endif /* _HAL_BE_API_MON_H_ */ diff --git a/hal/wifi3.0/be/hal_be_generic_api.h b/hal/wifi3.0/be/hal_be_generic_api.h index d5b168ac1c..8064ba2e2b 100644 --- a/hal/wifi3.0/be/hal_be_generic_api.h +++ b/hal/wifi3.0/be/hal_be_generic_api.h @@ -2564,6 +2564,116 @@ hal_txmon_get_buffer_addr_generic_be(void *tx_tlv, return buf_addr; } +#if defined(TX_MONITOR_WORD_MASK) +/** + * hal_txmon_get_num_users() - get num users from tx_fes_setup tlv + * + * @tx_tlv: pointer to tx_fes_setup tlv header + * + * Return: number of users + */ +static inline uint8_t +hal_txmon_get_num_users(void *tx_tlv) +{ + hal_tx_fes_setup_t *tx_fes_setup = (hal_tx_fes_setup_t *)tx_tlv; + + return tx_fes_setup->number_of_users; +} + +/** + * hal_txmon_parse_tx_fes_setup() - parse tx_fes_setup tlv + * + * @tx_tlv: pointer to tx_fes_setup tlv header + * @ppdu_info: pointer to hal_tx_ppdu_info + * + * Return: void + */ +static inline void +hal_txmon_parse_tx_fes_setup(void *tx_tlv, + struct hal_tx_ppdu_info *tx_ppdu_info) +{ + hal_tx_fes_setup_t *tx_fes_setup = (hal_tx_fes_setup_t *)tx_tlv; + + tx_ppdu_info->num_users = tx_fes_setup->number_of_users; +} +#else +/** + * hal_txmon_get_num_users() - get num users from tx_fes_setup tlv + * + * @tx_tlv: pointer to tx_fes_setup tlv header + * + * Return: number of users + */ +static inline uint8_t +hal_txmon_get_num_users(void *tx_tlv) +{ + uint8_t num_users = HAL_TX_DESC_GET(tx_tlv, + TX_FES_SETUP, NUMBER_OF_USERS); + + return num_users; +} + +/** + * hal_txmon_parse_tx_fes_setup() - parse tx_fes_setup tlv + * + * @tx_tlv: pointer to tx_fes_setup tlv header + * @ppdu_info: pointer to hal_tx_ppdu_info + * + * Return: void + */ +static inline void +hal_txmon_parse_tx_fes_setup(void *tx_tlv, + struct hal_tx_ppdu_info *tx_ppdu_info) +{ + tx_ppdu_info->num_users = HAL_TX_DESC_GET(tx_tlv, + TX_FES_SETUP, + NUMBER_OF_USERS); +} +#endif + +/** + * hal_txmon_status_get_num_users_generic_be() - api to get num users + * from start of fes window + * + * @tx_tlv_hdr: pointer to TLV header + * @num_users: reference to number of user + * + * Return: status + */ +static inline uint32_t +hal_txmon_status_get_num_users_generic_be(void *tx_tlv_hdr, uint8_t *num_users) +{ + uint32_t tlv_tag, user_id, tlv_len; + uint32_t tlv_status = HAL_MON_TX_STATUS_PPDU_NOT_DONE; + void *tx_tlv; + + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(tx_tlv_hdr); + user_id = HAL_RX_GET_USER_TLV32_USERID(tx_tlv_hdr); + tlv_len = HAL_RX_GET_USER_TLV32_LEN(tx_tlv_hdr); + + tx_tlv = (uint8_t *)tx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + /* window starts with either initiator or response */ + switch (tlv_tag) { + case WIFITX_FES_SETUP_E: + { + *num_users = hal_txmon_get_num_users(tx_tlv); + + tlv_status = HAL_MON_TX_FES_SETUP; + break; + } + case WIFIRX_RESPONSE_REQUIRED_INFO_E: + { + *num_users = HAL_TX_DESC_GET(tx_tlv, + RX_RESPONSE_REQUIRED_INFO, + RESPONSE_STA_COUNT); + tlv_status = HAL_MON_RX_RESPONSE_REQUIRED_INFO; + break; + } + }; + + return tlv_status; +} + /** * hal_txmon_free_status_buffer() - api to free status buffer * @pdev_handle: DP_PDEV handle @@ -2602,6 +2712,124 @@ hal_txmon_status_free_buffer_generic_be(qdf_frag_t status_frag) break; } while (tlv_status == HAL_MON_TX_STATUS_PPDU_NOT_DONE); } + +/** + * hal_tx_get_ppdu_info() - api to get tx ppdu info + * @pdev_handle: DP_PDEV handle + * @prot_ppdu_info: populate dp_ppdu_info protection + * @tx_data_ppdu_info: populate dp_ppdu_info data + * @tlv_tag: Tag + * + * Return: dp_tx_ppdu_info pointer + */ +static inline void * +hal_tx_get_ppdu_info(void *data_info, void *prot_info, uint32_t tlv_tag) +{ + struct hal_tx_ppdu_info *prot_ppdu_info = prot_info; + + switch (tlv_tag) { + case WIFITX_FES_SETUP_E:/* DOWNSTREAM */ + case WIFITX_FLUSH_E:/* DOWNSTREAM */ + case WIFIPCU_PPDU_SETUP_INIT_E:/* DOWNSTREAM */ + case WIFITX_PEER_ENTRY_E:/* DOWNSTREAM */ + case WIFITX_QUEUE_EXTENSION_E:/* DOWNSTREAM */ + case WIFITX_MPDU_START_E:/* DOWNSTREAM */ + case WIFITX_MSDU_START_E:/* DOWNSTREAM */ + case WIFITX_DATA_E:/* DOWNSTREAM */ + case WIFIMON_BUFFER_ADDR_E:/* DOWNSTREAM */ + case WIFITX_MPDU_END_E:/* DOWNSTREAM */ + case WIFITX_MSDU_END_E:/* DOWNSTREAM */ + case WIFITX_LAST_MPDU_FETCHED_E:/* DOWNSTREAM */ + case WIFITX_LAST_MPDU_END_E:/* DOWNSTREAM */ + case WIFICOEX_TX_REQ_E:/* DOWNSTREAM */ + case WIFITX_RAW_OR_NATIVE_FRAME_SETUP_E:/* DOWNSTREAM */ + case WIFINDP_PREAMBLE_DONE_E:/* DOWNSTREAM */ + case WIFISCH_CRITICAL_TLV_REFERENCE_E:/* DOWNSTREAM */ + case WIFITX_LOOPBACK_SETUP_E:/* DOWNSTREAM */ + case WIFITX_FES_SETUP_COMPLETE_E:/* DOWNSTREAM */ + case WIFITQM_MPDU_GLOBAL_START_E:/* DOWNSTREAM */ + case WIFITX_WUR_DATA_E:/* DOWNSTREAM */ + case WIFISCHEDULER_END_E:/* DOWNSTREAM */ + { + return data_info; + } + } + + /* + * check current prot_tlv_status is start protection + * check current tlv_tag is either start protection or end protection + */ + if (TXMON_HAL(prot_ppdu_info, + prot_tlv_status) == WIFITX_FES_STATUS_START_PROT_E) { + return prot_info; + } else if (tlv_tag == WIFITX_FES_STATUS_PROT_E || + tlv_tag == WIFITX_FES_STATUS_START_PROT_E) { + TXMON_HAL(prot_ppdu_info, prot_tlv_status) = tlv_tag; + return prot_info; + } else { + return data_info; + } + + return data_info; +} + +/** + * hal_txmon_status_parse_tlv_generic_be() - api to parse status tlv. + * @data_ppdu_info: hal_txmon data ppdu info + * @prot_ppdu_info: hal_txmon prot ppdu info + * @data_status_info: pointer to data status info + * @prot_status_info: pointer to prot status info + * @tx_tlv_hdr: fragment of tx_tlv_hdr + * @status_frag: qdf_frag_t buffer + * + * Return: status + */ +static inline uint32_t +hal_txmon_status_parse_tlv_generic_be(void *data_ppdu_info, + void *prot_ppdu_info, + void *data_status_info, + void *prot_status_info, + void *tx_tlv_hdr, + qdf_frag_t status_frag) +{ + struct hal_tx_ppdu_info *tx_ppdu_info; + struct hal_tx_status_info *tx_status_info; + uint32_t tlv_tag, user_id, tlv_len; + qdf_frag_t frag_buf = NULL; + uint32_t status = HAL_MON_TX_STATUS_PPDU_NOT_DONE; + void *tx_tlv; + + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(tx_tlv_hdr); + user_id = HAL_RX_GET_USER_TLV32_USERID(tx_tlv_hdr); + tlv_len = HAL_RX_GET_USER_TLV32_LEN(tx_tlv_hdr); + + tx_tlv = (uint8_t *)tx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + + tx_ppdu_info = hal_tx_get_ppdu_info(data_ppdu_info, + prot_ppdu_info, tlv_tag); + tx_status_info = (tx_ppdu_info->is_data ? data_status_info : + prot_status_info); + + /* parse tlv and populate tx_ppdu_info */ + switch (tlv_tag) { + case WIFIMON_BUFFER_ADDR_E: + { + frag_buf = hal_txmon_get_buffer_addr_generic_be(tx_tlv, NULL); + if (frag_buf) + qdf_frag_free(frag_buf); + frag_buf = NULL; + status = HAL_MON_TX_BUFFER_ADDR; + break; + } + case WIFITX_FES_STATUS_START_PROT_E: + { + TXMON_HAL(tx_ppdu_info, prot_tlv_status) = tlv_tag; + break; + } + } + + return status; +} #endif /* QCA_MONITOR_2_0_SUPPORT */ #ifdef REO_SHARED_QREF_TABLE_EN diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index cf2001b929..a5b13fa7dc 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1026,6 +1026,14 @@ struct hal_hw_txrx_ops { /* TX MONITOR */ #ifdef QCA_MONITOR_2_0_SUPPORT + uint32_t (*hal_txmon_status_parse_tlv)(void *data_ppdu_info, + void *prot_ppdu_info, + void *data_status_info, + void *prot_status_info, + void *tx_tlv_hdr, + qdf_frag_t status_frag); + uint32_t (*hal_txmon_status_get_num_users)(void *tx_tlv_hdr, + uint8_t *num_users); void (*hal_txmon_status_free_buffer)(qdf_frag_t status_frag); #endif /* QCA_MONITOR_2_0_SUPPORT */ void (*hal_reo_shared_qaddr_setup)(hal_soc_handle_t hal_soc_hdl); diff --git a/hal/wifi3.0/qcn9224/hal_9224.c b/hal/wifi3.0/qcn9224/hal_9224.c index 412d97d99e..803cf31fb4 100644 --- a/hal/wifi3.0/qcn9224/hal_9224.c +++ b/hal/wifi3.0/qcn9224/hal_9224.c @@ -1840,6 +1840,15 @@ static void hal_hw_txrx_ops_attach_qcn9224(struct hal_soc *hal_soc) hal_soc->ops->hal_reo_shared_qaddr_detach = hal_reo_shared_qaddr_detach_be; hal_soc->ops->hal_reo_shared_qaddr_write = hal_reo_shared_qaddr_write_be; #endif + /* TX MONITOR */ +#ifdef QCA_MONITOR_2_0_SUPPORT + hal_soc->ops->hal_txmon_status_parse_tlv = + hal_txmon_status_parse_tlv_generic_be; + hal_soc->ops->hal_txmon_status_get_num_users = + hal_txmon_status_get_num_users_generic_be; + hal_soc->ops->hal_txmon_status_free_buffer = + hal_txmon_status_free_buffer_generic_be; +#endif /* QCA_MONITOR_2_0_SUPPORT */ }; struct hal_hw_srng_config hw_srng_table_9224[] = { diff --git a/hal/wifi3.0/qcn9224/hal_9224_tx.h b/hal/wifi3.0/qcn9224/hal_9224_tx.h index bf0b49e334..4500148271 100644 --- a/hal/wifi3.0/qcn9224/hal_9224_tx.h +++ b/hal/wifi3.0/qcn9224/hal_9224_tx.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -16,6 +16,9 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#ifndef _HAL_9224_TX_H_ +#define _HAL_9224_TX_H_ + #include "tcl_data_cmd.h" #include "phyrx_rssi_legacy.h" #include "hal_internal.h" @@ -189,3 +192,38 @@ hal_tx_init_cmd_credit_ring_9224(hal_soc_handle_t hal_soc_hdl, hal_ring_handle_t hal_ring_hdl) { } + +/* TX MONITOR */ +#ifdef QCA_MONITOR_2_0_SUPPORT + +#if defined(TX_MONITOR_WORD_MASK) +typedef struct tx_fes_setup_compact_9224 hal_tx_fes_setup_t; +struct tx_fes_setup_compact_9224 { + /* DWORD - 0 */ + uint32_t schedule_id; + /* DWORD - 1 */ + uint32_t reserved_1a : 7, // [0: 6] + transmit_start_reason : 3, // [7: 9] + reserved_1b : 13, // [10: 22] + number_of_users : 6, // [28: 23] + MU_type : 1, // [29] + reserved_1c : 2; // [30] + /* DWORD - 2 */ + uint32_t reserved_2a : 4, // [0: 3] + ndp_frame : 2, // [4: 5] + txbf : 1, // [6] + reserved_2b : 3, // [7: 9] + static_bandwidth : 3, // [12: 10] + reserved_2c : 1, // [13] + transmission_contains_MU_RTS : 1, // [14] + reserved_2d : 17; // [15: 31] + /* DWORD - 3 */ + uint32_t reserved_3a : 15, // [0: 14] + mu_ndp : 1, // [15] + reserved_3b : 11, // [16: 26] + ndpa : 1, // [27] + reserved_3c : 4; // [28: 31] +}; +#endif +#endif /* QCA_MONITOR_2_0_SUPPORT */ +#endif /* _HAL_9224_TX_H_ */