From 9ba823644484e69a3997fb6ad745486ca379206f Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 1 Jul 2022 07:16:57 -0700 Subject: [PATCH] qcacmn: Add support to track high watermark for SRNGs Add support to track the high watermark for the number of entries which are used at any given instant. This helps in identifying if the ring size is sufficient or is being full for certain use-cases. Change-Id: Id3ffa52c653696699fbcfbb556a815d5f7908863 CRs-Fixed: 3235115 --- dp/inc/cdp_txrx_cmn_struct.h | 4 ++ dp/wifi3.0/be/dp_be_rx.c | 2 + dp/wifi3.0/dp_internal.h | 25 +++++++ dp/wifi3.0/dp_main.c | 34 ++++++++- dp/wifi3.0/dp_stats.c | 30 ++++++++ hal/wifi3.0/hal_api.h | 131 +++++++++++++++++++++++++++++++++++ hal/wifi3.0/hal_internal.h | 38 ++++++++++ hal/wifi3.0/hal_srng.c | 32 +++++++++ 8 files changed, 294 insertions(+), 2 deletions(-) diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 5dea2f4aef..c9c54cf12f 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -283,6 +283,9 @@ enum htt_cmn_dbg_stats_type { * @TXRX_NAPI_STATS: Print NAPI scheduling statistics * @TXRX_SOC_INTERRUPT_STATS: Print soc interrupt stats * @TXRX_HAL_REG_WRITE_STATS: Hal Reg Write stats + * @TXRX_SOC_REO_HW_DESC_DUMP: HW REO queue desc dump + * @TXRX_SOC_WBM_IDLE_HPTP_DUMP: WBM idle link desc SRNG HP/TP dump + * @TXRX_SRNG_USAGE_WM_STATS: SRNG usage watermark stats */ enum cdp_host_txrx_stats { TXRX_HOST_STATS_INVALID = -1, @@ -303,6 +306,7 @@ enum cdp_host_txrx_stats { TXRX_HAL_REG_WRITE_STATS = 14, TXRX_SOC_REO_HW_DESC_DUMP = 15, TXRX_SOC_WBM_IDLE_HPTP_DUMP = 16, + TXRX_SRNG_USAGE_WM_STATS = 17, TXRX_HOST_STATS_MAX, }; diff --git a/dp/wifi3.0/be/dp_be_rx.c b/dp/wifi3.0/be/dp_be_rx.c index 23e588deb9..eb107378d3 100644 --- a/dp/wifi3.0/be/dp_be_rx.c +++ b/dp/wifi3.0/be/dp_be_rx.c @@ -243,6 +243,8 @@ more_data: goto done; } + hal_srng_update_ring_usage_wm_no_lock(soc->hal_soc, hal_ring_hdl); + /* * start reaping the buffers from reo ring and queue * them in per vdev queue. diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 60c2722061..7ed459ac3c 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2347,6 +2347,31 @@ void dp_print_soc_tx_stats(struct dp_soc *soc); */ void dp_print_soc_interrupt_stats(struct dp_soc *soc); +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING +/** + * dp_dump_srng_high_wm_stats() - Print the ring usage high watermark stats + * for all SRNGs + * @soc: DP soc handle + * @srng_mask: SRNGs mask for dumping usage watermark stats + * + * Return: None + */ +void dp_dump_srng_high_wm_stats(struct dp_soc *soc, uint64_t srng_mask); +#else +/** + * dp_dump_srng_high_wm_stats() - Print the ring usage high watermark stats + * for all SRNGs + * @soc: DP soc handle + * @srng_mask: SRNGs mask for dumping usage watermark stats + * + * Return: None + */ +static inline +void dp_dump_srng_high_wm_stats(struct dp_soc *soc, uint64_t srng_mask) +{ +} +#endif + /** * dp_print_soc_rx_stats: Print SOC level Rx stats * @soc: DP_SOC Handle diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 97058013b0..8f9f995a81 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -404,11 +404,13 @@ const int dp_stats_mapping_table[][STATS_TYPE_MAX] = { {TXRX_FW_STATS_INVALID, TXRX_REO_QUEUE_STATS}, {TXRX_FW_STATS_INVALID, TXRX_SOC_CFG_PARAMS}, {TXRX_FW_STATS_INVALID, TXRX_PDEV_CFG_PARAMS}, + {TXRX_FW_STATS_INVALID, TXRX_NAPI_STATS}, {TXRX_FW_STATS_INVALID, TXRX_SOC_INTERRUPT_STATS}, {TXRX_FW_STATS_INVALID, TXRX_SOC_FSE_STATS}, {TXRX_FW_STATS_INVALID, TXRX_HAL_REG_WRITE_STATS}, {TXRX_FW_STATS_INVALID, TXRX_SOC_REO_HW_DESC_DUMP}, {TXRX_FW_STATS_INVALID, TXRX_SOC_WBM_IDLE_HPTP_DUMP}, + {TXRX_FW_STATS_INVALID, TXRX_SRNG_USAGE_WM_STATS}, {HTT_DBG_EXT_STATS_PDEV_RX_RATE_EXT, TXRX_HOST_STATS_INVALID}, {HTT_DBG_EXT_STATS_TX_SOUNDING_INFO, TXRX_HOST_STATS_INVALID} }; @@ -9197,6 +9199,21 @@ dp_txrx_host_peer_stats_clr(struct dp_soc *soc, #endif } +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING +static inline void dp_srng_clear_ring_usage_wm_stats(struct dp_soc *soc) +{ + int ring; + + for (ring = 0; ring < soc->num_reo_dest_rings; ring++) + hal_srng_clear_ring_usage_wm_locked(soc->hal_soc, + soc->reo_dest_ring[ring].hal_srng); +} +#else +static inline void dp_srng_clear_ring_usage_wm_stats(struct dp_soc *soc) +{ +} +#endif + /** * dp_txrx_host_stats_clr(): Reinitialize the txrx stats * @vdev: DP_VDEV handle @@ -9233,6 +9250,8 @@ dp_txrx_host_stats_clr(struct dp_vdev *vdev, struct dp_soc *soc) dp_vdev_iterate_peer(vdev, dp_txrx_host_peer_stats_clr, NULL, DP_MOD_ID_GENERIC_STATS); + dp_srng_clear_ring_usage_wm_stats(soc); + #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, vdev->pdev->soc, &vdev->stats, vdev->vdev_id, @@ -9570,8 +9589,13 @@ static void dp_txrx_stats_help(void) dp_info(" 28 -- Host REO Queue Statistics"); dp_info(" 29 -- Host Soc cfg param Statistics"); dp_info(" 30 -- Host pdev cfg param Statistics"); - dp_info(" 31 -- Host FISA stats"); - dp_info(" 32 -- Host Register Work stats"); + dp_info(" 31 -- Host NAPI stats"); + dp_info(" 32 -- Host Interrupt stats"); + dp_info(" 33 -- Host FISA stats"); + dp_info(" 34 -- Host Register Work stats"); + dp_info(" 35 -- HW REO Queue stats"); + dp_info(" 36 -- Host WBM IDLE link desc ring HP/TP"); + dp_info(" 37 -- Host SRNG usage watermark stats"); } /** @@ -9652,6 +9676,10 @@ dp_print_host_stats(struct dp_vdev *vdev, case TXRX_SOC_WBM_IDLE_HPTP_DUMP: dp_dump_wbm_idle_hptp(pdev->soc, pdev); break; + case TXRX_SRNG_USAGE_WM_STATS: + /* Dump usage watermark stats for all SRNGs */ + dp_dump_srng_high_wm_stats(soc, 0xFF); + break; default: dp_info("Wrong Input For TxRx Host Stats"); dp_txrx_stats_help(); @@ -11147,6 +11175,8 @@ static QDF_STATUS dp_txrx_dump_stats(struct cdp_soc_t *psoc, uint16_t value, dp_print_soc_interrupt_stats(soc); hal_dump_reg_write_stats(soc->hal_soc); dp_pdev_print_tx_delay_stats(soc); + /* Dump usage watermark stats for core TX/RX SRNGs */ + dp_dump_srng_high_wm_stats(soc, (1 << REO_DST)); break; case CDP_RX_RING_STATS: diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index 3a2b13ca08..a9a4c8c393 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -7610,6 +7610,36 @@ int dp_fill_tx_interrupt_ctx_stats(struct dp_intr *intr_ctx, return pos; } +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING +#define DP_SRNG_HIGH_WM_STATS_STRING_LEN 512 +void dp_dump_srng_high_wm_stats(struct dp_soc *soc, uint64_t srng_mask) +{ + char *buf; + int ring, pos, buf_len; + char srng_high_wm_str[DP_SRNG_HIGH_WM_STATS_STRING_LEN] = {'\0'}; + + if (!srng_mask) + return; + + buf = srng_high_wm_str; + buf_len = DP_SRNG_HIGH_WM_STATS_STRING_LEN; + + dp_info("%8s %7s %12s %10s %10s %10s %10s %10s %10s", + "ring_id", "high_wm", "time", "<50", "50-60", "60-70", + "70-80", "80-90", "90-100"); + + if (srng_mask & (1 << REO_DST)) { + for (ring = 0; ring < soc->num_reo_dest_rings; ring++) { + pos = 0; + pos += hal_dump_srng_high_wm_stats(soc->hal_soc, + soc->reo_dest_ring[ring].hal_srng, + buf, buf_len, pos); + dp_info("%s", srng_high_wm_str); + } + } +} +#endif + #define DP_INT_CTX_STATS_STRING_LEN 512 void dp_print_soc_interrupt_stats(struct dp_soc *soc) { diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index a510fbfa06..1d047d144b 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -2139,6 +2139,137 @@ hal_srng_src_num_avail(void *hal_soc, return ((srng->ring_size - hp + tp) / srng->entry_size) - 1; } +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING +/** + * hal_srng_clear_ring_usage_wm_locked() - Clear SRNG usage watermark stats + * @hal_soc_hdl: HAL soc handle + * @hal_ring_hdl: SRNG handle + * + * This function tries to acquire SRNG lock, and hence should not be called + * from a context which has already acquired the SRNG lock. + * + * Return: None + */ +static inline +void hal_srng_clear_ring_usage_wm_locked(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + SRNG_LOCK(&srng->lock); + srng->high_wm.val = 0; + srng->high_wm.timestamp = 0; + qdf_mem_zero(&srng->high_wm.bins[0], sizeof(srng->high_wm.bins[0]) * + HAL_SRNG_HIGH_WM_BIN_MAX); + SRNG_UNLOCK(&srng->lock); +} + +/** + * hal_srng_update_ring_usage_wm_no_lock() - Update the SRNG usage wm stats + * @hal_soc_hdl: HAL soc handle + * @hal_ring_hdl: SRNG handle + * + * This function should be called with the SRNG lock held. + * + * Return: None + */ +static inline +void hal_srng_update_ring_usage_wm_no_lock(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + uint32_t curr_wm_val = 0; + + if (srng->ring_dir == HAL_SRNG_SRC_RING) + curr_wm_val = hal_srng_src_num_avail(hal_soc_hdl, hal_ring_hdl, + 0); + else + curr_wm_val = hal_srng_dst_num_valid(hal_soc_hdl, hal_ring_hdl, + 0); + + if (curr_wm_val > srng->high_wm.val) { + srng->high_wm.val = curr_wm_val; + srng->high_wm.timestamp = qdf_get_system_timestamp(); + } + + if (curr_wm_val >= + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_90_to_100]) + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_90_to_100]++; + else if (curr_wm_val >= + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_80_to_90]) + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_80_to_90]++; + else if (curr_wm_val >= + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_70_to_80]) + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_70_to_80]++; + else if (curr_wm_val >= + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_60_to_70]) + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_60_to_70]++; + else if (curr_wm_val >= + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_50_to_60]) + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_50_to_60]++; + else + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_BELOW_50_PERCENT]++; +} + +static inline +int hal_dump_srng_high_wm_stats(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl, + char *buf, int buf_len, int pos) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + return qdf_scnprintf(buf + pos, buf_len - pos, + "%8u %7u %12llu %10u %10u %10u %10u %10u %10u", + srng->ring_id, srng->high_wm.val, + srng->high_wm.timestamp, + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_BELOW_50_PERCENT], + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_50_to_60], + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_60_to_70], + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_70_to_80], + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_80_to_90], + srng->high_wm.bins[HAL_SRNG_HIGH_WM_BIN_90_to_100]); +} +#else +/** + * hal_srng_clear_ring_usage_wm_locked() - Clear SRNG usage watermark stats + * @hal_soc_hdl: HAL soc handle + * @hal_ring_hdl: SRNG handle + * + * This function tries to acquire SRNG lock, and hence should not be called + * from a context which has already acquired the SRNG lock. + * + * Return: None + */ +static inline +void hal_srng_clear_ring_usage_wm_locked(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ +} + +/** + * hal_srng_update_ring_usage_wm_no_lock() - Update the SRNG usage wm stats + * @hal_soc_hdl: HAL soc handle + * @hal_ring_hdl: SRNG handle + * + * This function should be called with the SRNG lock held. + * + * Return: None + */ +static inline +void hal_srng_update_ring_usage_wm_no_lock(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ +} + +static inline +int hal_dump_srng_high_wm_stats(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl, + char *buf, int buf_len, int pos) +{ + return 0; +} +#endif + /** * hal_srng_access_end_unlocked - End ring access (unlocked) - update cached * ring head/tail pointers to HW. diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index bbf954bc69..bbba190ffd 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -502,6 +502,41 @@ struct hal_offload_info { uint32_t flow_id; }; +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING +/** + * enum hal_srng_high_wm_bin - BIN for SRNG high watermark + * @HAL_SRNG_HIGH_WM_BIN_BELOW_50_PERCENT: <50% SRNG entries used + * @HAL_SRNG_HIGH_WM_BIN_50_to_60: 50-60% SRNG entries used + * @HAL_SRNG_HIGH_WM_BIN_60_to_70: 60-70% SRNG entries used + * @HAL_SRNG_HIGH_WM_BIN_70_to_80: 70-80% SRNG entries used + * @HAL_SRNG_HIGH_WM_BIN_80_to_90: 80-90% SRNG entries used + * @HAL_SRNG_HIGH_WM_BIN_90_to_100: 90-100% SRNG entries used + */ +enum hal_srng_high_wm_bin { + HAL_SRNG_HIGH_WM_BIN_BELOW_50_PERCENT, + HAL_SRNG_HIGH_WM_BIN_50_to_60, + HAL_SRNG_HIGH_WM_BIN_60_to_70, + HAL_SRNG_HIGH_WM_BIN_70_to_80, + HAL_SRNG_HIGH_WM_BIN_80_to_90, + HAL_SRNG_HIGH_WM_BIN_90_to_100, + HAL_SRNG_HIGH_WM_BIN_MAX, +}; + +/** + * struct hal_srng_high_wm_info - SRNG usage high watermark info + * @val: highest number of entries used in SRNG + * @timestamp: Timestamp when the max num entries were in used for a SRNG + * @bin_thresh: threshold for each bins + * @bins: Bins for srng usage + */ +struct hal_srng_high_wm_info { + uint32_t val; + uint64_t timestamp; + uint32_t bin_thresh[HAL_SRNG_HIGH_WM_BIN_MAX]; + uint32_t bins[HAL_SRNG_HIGH_WM_BIN_MAX]; +}; +#endif + /* Common SRNG ring structure for source and destination rings */ struct hal_srng { /* Unique SRNG ring ID */ @@ -650,6 +685,9 @@ struct hal_srng { /* srng specific delayed write stats */ struct hal_reg_write_srng_stats wstats; #endif +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING + struct hal_srng_high_wm_info high_wm; +#endif }; /* HW SRNG configuration table */ diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 3373829f79..477b372a8a 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -1485,6 +1485,37 @@ void hal_srng_last_desc_cleared_init(struct hal_srng *srng) } #endif /* CLEAR_SW2TCL_CONSUMED_DESC */ +#ifdef WLAN_DP_SRNG_USAGE_WM_TRACKING +static inline void hal_srng_update_high_wm_thresholds(struct hal_srng *srng) +{ + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_90_to_100] = + ((srng->num_entries * 90) / 100); + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_80_to_90] = + ((srng->num_entries * 80) / 100); + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_70_to_80] = + ((srng->num_entries * 70) / 100); + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_60_to_70] = + ((srng->num_entries * 60) / 100); + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_50_to_60] = + ((srng->num_entries * 50) / 100); + /* Below 50% threshold is not needed */ + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_BELOW_50_PERCENT] = 0; + + hal_info("ring_id: %u, wm_thresh- <50:%u, 50-60:%u, 60-70:%u, 70-80:%u, 80-90:%u, 90-100:%u", + srng->ring_id, + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_BELOW_50_PERCENT], + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_50_to_60], + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_60_to_70], + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_70_to_80], + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_80_to_90], + srng->high_wm.bin_thresh[HAL_SRNG_HIGH_WM_BIN_90_to_100]); +} +#else +static inline void hal_srng_update_high_wm_thresholds(struct hal_srng *srng) +{ +} +#endif + /** * hal_srng_setup - Initialize HW SRNG ring. * @hal_soc: Opaque HAL SOC handle @@ -1547,6 +1578,7 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, srng->prefetch_timer = ring_params->prefetch_timer; srng->hal_soc = hal_soc; hal_srng_set_msi2_params(srng, ring_params); + hal_srng_update_high_wm_thresholds(srng); for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++) { srng->hwreg_base[i] = dev_base_addr + ring_config->reg_start[i]