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
This commit is contained in:
Rakesh Pillai
2022-07-01 07:16:57 -07:00
committed by Madan Koyyalamudi
parent 162ab8974a
commit 9ba8236444
8 changed files with 294 additions and 2 deletions

View File

@@ -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,
};

View File

@@ -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.

View File

@@ -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

View File

@@ -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:

View File

@@ -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)
{

View File

@@ -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.

View File

@@ -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 */

View File

@@ -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]