diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index a4d5813e34..ff1c4ff937 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -1115,6 +1115,7 @@ enum cdp_peer_param_type { * @CDP_CONFIG_BSS_COLOR: configure bss color * @CDP_SET_ATF_STATS_ENABLE: set ATF stats flag * @CDP_CONFIG_SPECIAL_VAP: Configure Special vap + * @CDP_RESET_SPCL_VAP_STATS_ENABLE: Enable spcl vap stats reset */ enum cdp_pdev_param_type { CDP_CONFIG_DEBUG_SNIFFER, @@ -1146,6 +1147,7 @@ enum cdp_pdev_param_type { CDP_CONFIG_BSS_COLOR, CDP_SET_ATF_STATS_ENABLE, CDP_CONFIG_SPECIAL_VAP, + CDP_RESET_SPCL_VAP_STATS_ENABLE, }; /* @@ -1279,6 +1281,7 @@ typedef union cdp_config_param_t { uint32_t cdp_pdev_param_tx_pending; bool cdp_pdev_param_atf_stats_enable; bool cdp_pdev_param_config_special_vap; + bool cdp_pdev_param_reset_spcl_vap_stats_enable; /* psoc params */ bool cdp_psoc_param_en_rate_stats; @@ -2567,4 +2570,24 @@ struct cdp_rx_flow_info { struct cdp_rx_flow_tuple_info flow_tuple_info; uint16_t fse_metadata; }; + +/** + * cdp_spcl_vap_stats - Special vap statistics info + * @rx_ok_pkts: rx fcs ok pkts count + * @rx_ok_bytes: rx fcs ok bytes count + * @rx_err_pkts: rx fcs err pkts count + * @rx_err_bytes: rx fcs err bytes count + * @rx_mgmt_pkts: rx mgmt pkts count + * @rx_ctrl_pkts: rx ctrl pkts count + * @rx_data_pkts: rx data pkts count + */ +struct cdp_spcl_vap_stats { + uint64_t rx_ok_pkts; + uint64_t rx_ok_bytes; + uint64_t rx_err_pkts; + uint64_t rx_err_bytes; + uint64_t rx_mgmt_pkts; + uint64_t rx_ctrl_pkts; + uint64_t rx_data_pkts; +}; #endif diff --git a/dp/inc/cdp_txrx_host_stats.h b/dp/inc/cdp_txrx_host_stats.h index 128aac2ef1..9ae337abc6 100644 --- a/dp/inc/cdp_txrx_host_stats.h +++ b/dp/inc/cdp_txrx_host_stats.h @@ -733,4 +733,23 @@ cdp_host_get_radio_stats(ol_txrx_soc_handle soc, return soc->ops->host_stats_ops->txrx_get_radio_stats(soc, pdev_id, buf); } + +static inline int +cdp_get_spcl_vap_stats(ol_txrx_soc_handle soc, + uint8_t vdev_id, + struct cdp_spcl_vap_stats *stats) +{ + if (!soc || !soc->ops) { + dp_cdp_debug("Invalid Instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->host_stats_ops || + !soc->ops->host_stats_ops->txrx_get_spcl_vap_stats) + return QDF_STATUS_E_FAILURE; + + return soc->ops->host_stats_ops->txrx_get_spcl_vap_stats(soc, vdev_id, + stats); +} #endif /* _CDP_TXRX_HOST_STATS_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index f66352adef..b8e6cb53a1 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -986,6 +986,10 @@ struct cdp_host_stats_ops { uint8_t *peer_mac, void *stats, uint32_t last_tx_rate_mcs, uint32_t stats_id); + + QDF_STATUS + (*txrx_get_spcl_vap_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, + struct cdp_spcl_vap_stats *stats); }; struct cdp_wds_ops { diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 0bb9baa993..2ca1bc1fa9 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -590,6 +590,17 @@ static inline bool monitor_is_enable_enhanced_stats(struct dp_pdev *pdev) { return false; } + +static inline +void dp_monitor_pdev_config_spcl_vap(struct dp_pdev *pdev) +{ +} + +static inline +void dp_monitor_pdev_reset_spcl_vap_stats_enable(struct dp_pdev *pdev, + bool val) +{ +} #endif #define DP_MAX_TIMER_EXEC_TIME_TICKS \ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 54f35738ff..4729c2bc53 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -8528,8 +8528,14 @@ static QDF_STATUS dp_set_pdev_param(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, val.cdp_pdev_param_atf_stats_enable); break; case CDP_CONFIG_SPECIAL_VAP: + dp_monitor_pdev_config_spcl_vap(pdev, + val.cdp_pdev_param_config_special_vap); monitor_vdev_set_monitor_mode_buf_rings(pdev); break; + case CDP_RESET_SPCL_VAP_STATS_ENABLE: + dp_monitor_pdev_reset_spcl_vap_stats_enable(pdev, + val.cdp_pdev_param_reset_spcl_vap_stats_enable); + break; default: return QDF_STATUS_E_INVAL; } diff --git a/dp/wifi3.0/monitor/dp_mon.c b/dp/wifi3.0/monitor/dp_mon.c index a8d865c6a8..91877c3b9d 100644 --- a/dp/wifi3.0/monitor/dp_mon.c +++ b/dp/wifi3.0/monitor/dp_mon.c @@ -610,6 +610,25 @@ dp_deliver_tx_mgmt(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf) return QDF_STATUS_SUCCESS; } +/** + * dp_reset_spcl_vap_stats() - reset spcl vap rx stats + * @vdev: Datapath VDEV handle + * + * Return: void + */ +static inline void +dp_reset_spcl_vap_stats(struct dp_vdev *vdev) +{ + struct dp_mon_vdev *mon_vdev; + + mon_vdev = vdev->monitor_vdev; + if (!mon_vdev) + return; + + qdf_mem_zero(&mon_vdev->spcl_vap_stats, + sizeof(mon_vdev->spcl_vap_stats)); +} + /** * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode * @vdev_handle: Datapath VDEV handle @@ -657,6 +676,10 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *dp_soc, goto fail; } + if (mon_pdev->spcl_vap_configured && + mon_pdev->reset_spcl_vap_stats_enable) + dp_reset_spcl_vap_stats(vdev); + /*Check if current pdev's monitor_vdev exists */ if (mon_pdev->monitor_configured) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, @@ -5251,6 +5274,29 @@ static void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) } #endif +static QDF_STATUS +dp_get_spcl_vap_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + struct cdp_spcl_vap_stats *stats) +{ + struct dp_mon_vdev *mon_vdev = NULL; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, + DP_MOD_ID_CDP); + + if (!vdev || !stats) + return QDF_STATUS_E_INVAL; + + mon_vdev = vdev->monitor_vdev; + if (!mon_vdev) + return QDF_STATUS_E_INVAL; + + qdf_mem_copy(stats, &mon_vdev->spcl_vap_stats, + sizeof(struct cdp_spcl_vap_stats)); + + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); + return QDF_STATUS_SUCCESS; +} + QDF_STATUS dp_mon_soc_cfg_init(struct dp_soc *soc) { int target_type; @@ -5670,6 +5716,8 @@ void dp_mon_cdp_ops_register(struct dp_soc *soc) #ifdef WDI_EVENT_ENABLE ops->ctrl_ops->txrx_get_pldev = dp_get_pldev; #endif + ops->host_stats_ops->txrx_get_spcl_vap_stats = + dp_get_spcl_vap_stats; return; } diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index d25a17947c..cba301b00f 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -351,11 +351,16 @@ struct dp_mon_pdev { qdf_nbuf_t mcopy_status_nbuf; bool is_dp_mon_pdev_initialized; + /* indicates if spcl vap is configured */ + bool spcl_vap_configured; + /* enable spcl vap stats reset on ch change */ + bool reset_spcl_vap_stats_enable; }; struct dp_mon_vdev { /* callback to hand rx monitor 802.11 MPDU to the OS shim */ ol_txrx_rx_mon_fp osif_rx_mon; + struct cdp_spcl_vap_stats spcl_vap_stats; }; struct dp_mon_peer { @@ -2261,6 +2266,25 @@ void monitor_pdev_set_mon_vdev(struct dp_vdev *vdev) mon_pdev->mvdev = vdev; } +static inline +void dp_monitor_pdev_config_spcl_vap(struct dp_pdev *pdev, bool val) +{ + if (!pdev || !pdev->monitor_pdev) + return; + + pdev->monitor_pdev->spcl_vap_configured = val; +} + +static inline +void dp_monitor_pdev_reset_spcl_vap_stats_enable(struct dp_pdev *pdev, + bool val) +{ + if (!pdev || !pdev->monitor_pdev) + return; + + pdev->monitor_pdev->reset_spcl_vap_stats_enable = val; +} + QDF_STATUS dp_mon_soc_attach(struct dp_soc *soc); QDF_STATUS dp_mon_soc_detach(struct dp_soc *soc); QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev); diff --git a/dp/wifi3.0/monitor/dp_rx_mon_status.c b/dp/wifi3.0/monitor/dp_rx_mon_status.c index e046fc5c2a..9b334423f7 100644 --- a/dp/wifi3.0/monitor/dp_rx_mon_status.c +++ b/dp/wifi3.0/monitor/dp_rx_mon_status.c @@ -1730,6 +1730,51 @@ dp_rx_mon_handle_mu_ul_info(struct hal_rx_ppdu_info *ppdu_info) } #endif +/** + * dp_rx_mon_update_spcl_vap_stats() - Update special vap stats + * @pdev: dp pdev context + * @ppdu_info: ppdu info structure from ppdu ring + * + * Return: none + */ +static inline void +dp_rx_mon_update_spcl_vap_stats(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + struct mon_rx_user_status *rx_user_status = NULL; + struct dp_mon_pdev *mon_pdev = NULL; + struct dp_mon_vdev *mon_vdev = NULL; + uint32_t num_users = 0; + uint32_t user = 0; + + mon_pdev = pdev->monitor_pdev; + if (!mon_pdev || !mon_pdev->mvdev) + return; + + mon_vdev = mon_pdev->mvdev->monitor_vdev; + if (!mon_vdev) + return; + + num_users = ppdu_info->com_info.num_users; + for (user = 0; user < num_users; user++) { + rx_user_status = &ppdu_info->rx_user_status[user]; + mon_vdev->spcl_vap_stats.rx_ok_pkts += + rx_user_status->mpdu_cnt_fcs_ok; + mon_vdev->spcl_vap_stats.rx_ok_bytes += + rx_user_status->mpdu_ok_byte_count; + mon_vdev->spcl_vap_stats.rx_err_pkts += + rx_user_status->mpdu_cnt_fcs_err; + mon_vdev->spcl_vap_stats.rx_err_bytes += + rx_user_status->mpdu_err_byte_count; + } + mon_vdev->spcl_vap_stats.rx_mgmt_pkts += + ppdu_info->frm_type_info.rx_mgmt_cnt; + mon_vdev->spcl_vap_stats.rx_ctrl_pkts += + ppdu_info->frm_type_info.rx_ctrl_cnt; + mon_vdev->spcl_vap_stats.rx_data_pkts += + ppdu_info->frm_type_info.rx_data_cnt; +} + /** * dp_rx_mon_status_process_tlv() - Process status TLV in status * buffer on Rx status Queue posted by status SRNG processing. @@ -1873,6 +1918,11 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, struct dp_intr *int_ctx, mon_pdev->mon_ppdu_status = DP_PPDU_STATUS_DONE; + /* Collect spcl vap stats if configured */ + if (mon_pdev->spcl_vap_configured) + dp_rx_mon_update_spcl_vap_stats(pdev, + ppdu_info); + /* * if chan_num is not fetched correctly from ppdu RX TLV, * get it from pdev saved. diff --git a/hal/wifi3.0/hal_api_mon.h b/hal/wifi3.0/hal_api_mon.h index 1e88d38bde..1cb7dd53de 100644 --- a/hal/wifi3.0/hal_api_mon.h +++ b/hal/wifi3.0/hal_api_mon.h @@ -162,6 +162,13 @@ /* Max pilot count */ #define HAL_RX_MAX_SU_EVM_COUNT 32 +#define HAL_RX_FRAMECTRL_TYPE_MASK 0x0C +#define HAL_RX_GET_FRAME_CTRL_TYPE(fc)\ + (((fc) & HAL_RX_FRAMECTRL_TYPE_MASK) >> 2) +#define HAL_RX_FRAME_CTRL_TYPE_MGMT 0x0 +#define HAL_RX_FRAME_CTRL_TYPE_CTRL 0x1 +#define HAL_RX_FRAME_CTRL_TYPE_DATA 0x2 + /** * struct hal_rx_mon_desc_info () - HAL Rx Monitor descriptor info * @@ -656,6 +663,12 @@ struct mon_rx_user_info { uint8_t qos_control_info_valid; }; +struct hal_rx_frm_type_info { + uint32_t rx_mgmt_cnt; + uint32_t rx_ctrl_cnt; + uint32_t rx_data_cnt; +}; + struct hal_rx_ppdu_info { struct hal_rx_ppdu_common_info com_info; struct mon_rx_status rx_status; @@ -693,6 +706,8 @@ struct hal_rx_ppdu_info { * and for CFR correlation as well */ struct hal_rx_ppdu_cfr_info cfr_info; + /* per frame type counts */ + struct hal_rx_frm_type_info frm_type_info; }; static inline uint32_t diff --git a/hal/wifi3.0/li/hal_li_generic_api.h b/hal/wifi3.0/li/hal_li_generic_api.h index 6a3b228200..18c85a66b1 100644 --- a/hal/wifi3.0/li/hal_li_generic_api.h +++ b/hal/wifi3.0/li/hal_li_generic_api.h @@ -1494,6 +1494,21 @@ hal_rx_status_get_tlv_info_generic_li(void *rx_tlv_hdr, void *ppduinfo, uint8_t *rx_mpdu_start = (uint8_t *)rx_tlv; uint32_t ppdu_id = HAL_RX_GET_PPDU_ID(rx_mpdu_start); uint8_t filter_category = 0; + uint16_t frame_ctrl; + uint8_t fc_type; + + if (HAL_RX_GET_FC_VALID(rx_mpdu_start)) { + frame_ctrl = HAL_RX_GET(rx_mpdu_start, + RX_MPDU_INFO_14, + MPDU_FRAME_CONTROL_FIELD); + fc_type = HAL_RX_GET_FRAME_CTRL_TYPE(frame_ctrl); + if (fc_type == HAL_RX_FRAME_CTRL_TYPE_MGMT) + ppdu_info->frm_type_info.rx_mgmt_cnt++; + else if (fc_type == HAL_RX_FRAME_CTRL_TYPE_CTRL) + ppdu_info->frm_type_info.rx_ctrl_cnt++; + else if (fc_type == HAL_RX_FRAME_CTRL_TYPE_DATA) + ppdu_info->frm_type_info.rx_data_cnt++; + } ppdu_info->nac_info.fc_valid = HAL_RX_GET_FC_VALID(rx_mpdu_start);