Explorar o código

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
Rakesh Pillai %!s(int64=3) %!d(string=hai) anos
pai
achega
9ba8236444

+ 4 - 0
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,
 };
 

+ 2 - 0
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.

+ 25 - 0
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

+ 32 - 2
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:

+ 30 - 0
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)
 {

+ 131 - 0
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.

+ 38 - 0
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 */

+ 32 - 0
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]