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]