Ver Fonte

qcacmn: Add dp functionality to support stats sysfs

Add dp functionality to collect stats for sysfs buffer.
Add both host and fw stats.

Change-Id: I64f84804d36cccec9d701925d96cc7ee96943b7a
CRs-Fixed: 3035864
sandhu há 3 anos atrás
pai
commit
18fe5c3f02

+ 1 - 1
dp/inc/cdp_txrx_cmn_struct.h

@@ -2411,7 +2411,7 @@ struct cdp_txrx_stats_req {
 	uint32_t	param3;
 	uint32_t	cookie_val;
 	uint8_t		mac_id;
-	char *peer_addr;
+	char		*peer_addr;
 };
 
 /**

+ 7 - 0
dp/inc/cdp_txrx_ops.h

@@ -580,6 +580,13 @@ struct cdp_cmn_ops {
 #endif /* QCA_SUPPORT_WDS_EXTENDED */
 	void (*txrx_drain)(ol_txrx_soc_handle soc);
 	int (*get_free_desc_poolsize)(struct cdp_soc_t *soc);
+#ifdef WLAN_SYSFS_DP_STATS
+	QDF_STATUS (*txrx_sysfs_fill_stats)(ol_txrx_soc_handle soc,
+					    char *buf, uint32_t buf_size);
+	QDF_STATUS (*txrx_sysfs_set_stat_type)(ol_txrx_soc_handle soc,
+					       uint32_t stat_type,
+					       uint32_t mac_id);
+#endif /* WLAN_SYSFS_DP_STATS */
 };
 
 struct cdp_ctrl_ops {

+ 69 - 1
dp/wifi3.0/dp_htt.c

@@ -1592,7 +1592,7 @@ dp_send_htt_stat_resp(struct htt_stats_context *htt_stats,
 #endif
 
 #ifdef HTT_STATS_DEBUGFS_SUPPORT
-/* dp_send_htt_stats_dbgfs_msg() - Function to send htt data to upper layer
+/* dp_send_htt_stats_dbgfs_msg() - Function to send htt data to upper layer.
  * @pdev: dp pdev handle
  * @msg_word: HTT msg
  * @msg_len: Length of HTT msg sent
@@ -1633,6 +1633,67 @@ dp_htt_stats_dbgfs_send_msg(struct dp_pdev *pdev, uint32_t *msg_word,
 }
 #endif /* HTT_STATS_DEBUGFS_SUPPORT */
 
+#ifdef WLAN_SYSFS_DP_STATS
+/* dp_htt_stats_sysfs_update_config() - Function to send htt data to upper layer.
+ * @pdev: dp pdev handle
+ *
+ * This function sets the process id and printing mode within the sysfs config
+ * struct. which enables DP_PRINT statements within this process to write to the
+ * console buffer provided by the user space.
+ *
+ * Return: None
+ */
+static inline void
+dp_htt_stats_sysfs_update_config(struct dp_pdev *pdev)
+{
+	struct dp_soc *soc = pdev->soc;
+
+	if (!soc) {
+		dp_htt_err("soc is null");
+		return;
+	}
+
+	if (!soc->sysfs_config) {
+		dp_htt_err("soc->sysfs_config is NULL");
+		return;
+	}
+
+	/* set sysfs config parameters */
+	soc->sysfs_config->process_id = qdf_get_current_pid();
+	soc->sysfs_config->printing_mode = PRINTING_MODE_ENABLED;
+}
+
+/*
+ * dp_htt_stats_sysfs_set_event() - Set sysfs stats event.
+ * @soc: soc handle.
+ * @msg_word: Pointer to htt msg word.
+ *
+ * @return: void
+ */
+static inline void
+dp_htt_stats_sysfs_set_event(struct dp_soc *soc, uint32_t *msg_word)
+{
+	int done = 0;
+
+	done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*(msg_word + 3));
+	if (done) {
+		if (qdf_event_set(&soc->sysfs_config->sysfs_txrx_fw_request_done))
+			dp_htt_err("%pK:event compl Fail to set event ",
+				   soc);
+	}
+}
+#else /* WLAN_SYSFS_DP_STATS */
+static inline void
+dp_htt_stats_sysfs_update_config(struct dp_pdev *pdev)
+{
+}
+
+static inline void
+dp_htt_stats_sysfs_set_event(struct dp_soc *dp_soc, uint32_t *msg_word)
+{
+}
+#endif /* WLAN_SYSFS_DP_STATS */
+
 /**
  * dp_process_htt_stat_msg(): Process the list of buffers of HTT EXT stats
  * @htt_stats: htt stats info
@@ -1697,6 +1758,9 @@ static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats,
 			continue;
 		}
 
+		if (!cookie_val && (cookie_msb & DBG_SYSFS_STATS_COOKIE))
+			dp_htt_stats_sysfs_update_config(pdev);
+
 		if (cookie_msb & DBG_STATS_COOKIE_DP_STATS)
 			copy_stats = true;
 
@@ -1800,6 +1864,10 @@ static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats,
 			htt_stats->msg_len -= DP_EXT_MSG_LENGTH;
 		}
 
+		/* indicate event completion in case the event is done */
+		if (!cookie_val && (cookie_msb & DBG_SYSFS_STATS_COOKIE))
+			dp_htt_stats_sysfs_set_event(soc, msg_word);
+
 		qdf_nbuf_free(htt_msg);
 	}
 	return;

+ 62 - 15
dp/wifi3.0/dp_internal.h

@@ -57,10 +57,13 @@ struct htt_dbgfs_cfg {
 #define DBG_STATS_COOKIE_DEFAULT 0x0
 
 /* Reserve for DP Stats: 3rd bit */
-#define DBG_STATS_COOKIE_DP_STATS 0x8
+#define DBG_STATS_COOKIE_DP_STATS BIT(3)
 
 /* Reserve for HTT Stats debugfs support: 4th bit */
-#define DBG_STATS_COOKIE_HTT_DBGFS 0x10
+#define DBG_STATS_COOKIE_HTT_DBGFS BIT(4)
+
+/*Reserve for HTT Stats debugfs support: 5th bit */
+#define DBG_SYSFS_STATS_COOKIE BIT(5)
 
 /**
  * Bitmap of HTT PPDU TLV types for Default mode
@@ -612,6 +615,19 @@ void dp_monitor_pdev_reset_scan_spcl_vap_stats_enable(struct dp_pdev *pdev,
 }
 #endif
 
+/**
+ * cdp_soc_t_to_dp_soc() - typecast cdp_soc_t to
+ * dp soc handle
+ * @psoc: CDP psoc handle
+ *
+ * Return: struct dp_soc pointer
+ */
+static inline
+struct dp_soc *cdp_soc_t_to_dp_soc(struct cdp_soc_t *psoc)
+{
+	return (struct dp_soc *)psoc;
+}
+
 #define DP_MAX_TIMER_EXEC_TIME_TICKS \
 		(QDF_LOG_TIMESTAMP_CYCLES_PER_10_US * 100 * 20)
 
@@ -666,6 +682,48 @@ while (0)
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_##LVL,       \
 		fmt, ## args)
 
+#ifdef WLAN_SYSFS_DP_STATS
+static
+inline void DP_PRINT_STATS(const char *fmt, ...)
+{
+	void *soc_void = NULL;
+	va_list val;
+	uint16_t buf_written = 0;
+	uint16_t curr_len = 0;
+	uint16_t max_len = 0;
+	struct dp_soc *soc = NULL;
+
+	soc_void = cds_get_context(QDF_MODULE_ID_SOC);
+	soc = cdp_soc_t_to_dp_soc(soc_void);
+	va_start(val, fmt);
+	QDF_VTRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, (char *)fmt, val);
+	/* writing to the buffer */
+	if (soc->sysfs_config && soc->sysfs_config->printing_mode == PRINTING_MODE_ENABLED) {
+		if (soc->sysfs_config->process_id == qdf_get_current_pid()) {
+			curr_len = soc->sysfs_config->curr_buffer_length;
+			max_len = soc->sysfs_config->max_buffer_length;
+			if ((max_len - curr_len) <= 1)
+				return;
+
+			qdf_spinlock_acquire(&soc->sysfs_config->sysfs_write_user_buffer);
+			if (soc->sysfs_config->buf) {
+				buf_written = vscnprintf(soc->sysfs_config->buf + curr_len,
+							 max_len - curr_len, fmt, val);
+				curr_len += buf_written;
+				if ((max_len - curr_len) <= 1)
+					return;
+
+				buf_written += scnprintf(soc->sysfs_config->buf + curr_len,
+							 max_len - curr_len, "\n");
+				soc->sysfs_config->curr_buffer_length +=  buf_written;
+			}
+			qdf_spinlock_release(&soc->sysfs_config->sysfs_write_user_buffer);
+		}
+	}
+	va_end(val);
+}
+
+#else /* WLAN_SYSFS_DP_STATS */
 #ifdef DP_PRINT_NO_CONSOLE
 /* Stat prints should not go to console or kernel logs.*/
 #define DP_PRINT_STATS(fmt, args ...)\
@@ -676,6 +734,8 @@ while (0)
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,\
 		  fmt, ## args)
 #endif
+#endif /* WLAN_SYSFS_DP_STATS */
+
 #define DP_STATS_INIT(_handle) \
 	qdf_mem_zero(&((_handle)->stats), sizeof((_handle)->stats))
 
@@ -2479,19 +2539,6 @@ struct cdp_soc_t *dp_soc_to_cdp_soc_t(struct dp_soc *psoc)
 	return (struct cdp_soc_t *)psoc;
 }
 
-/**
- * cdp_soc_t_to_dp_soc() - typecast cdp_soc_t to
- * dp soc handle
- * @psoc: CDP psoc handle
- *
- * Return: struct dp_soc pointer
- */
-static inline
-struct dp_soc *cdp_soc_t_to_dp_soc(struct cdp_soc_t *psoc)
-{
-	return (struct dp_soc *)psoc;
-}
-
 #if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA)
 /**
  * dp_rx_flow_update_fse_stats() - Update a flow's statistics

+ 297 - 13
dp/wifi3.0/dp_main.c

@@ -105,6 +105,11 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc)
 #define SET_PEER_REF_CNT_ONE(_peer)
 #endif
 
+#ifdef WLAN_SYSFS_DP_STATS
+/* sysfs event wait time for firmware stat request unit millseconds */
+#define WLAN_SYSFS_STAT_REQ_WAIT_MS 3000
+#endif
+
 QDF_COMPILE_TIME_ASSERT(max_rx_rings_check,
 			MAX_REO_DEST_RINGS == CDP_MAX_RX_RINGS);
 
@@ -159,6 +164,9 @@ QDF_COMPILE_TIME_ASSERT(wlan_cfg_num_int_ctxs,
 			WLAN_CFG_INT_NUM_CONTEXTS_MAX >=
 			WLAN_CFG_INT_NUM_CONTEXTS);
 
+static QDF_STATUS dp_sysfs_deinitialize_stats(struct dp_soc *soc_hdl);
+static QDF_STATUS dp_sysfs_initialize_stats(struct dp_soc *soc_hdl);
+
 static void dp_pdev_srng_deinit(struct dp_pdev *pdev);
 static QDF_STATUS dp_pdev_srng_init(struct dp_pdev *pdev);
 static void dp_pdev_srng_free(struct dp_pdev *pdev);
@@ -5350,6 +5358,7 @@ static void dp_soc_detach(struct cdp_soc_t *txrx_soc)
 
 	soc->arch_ops.txrx_soc_detach(soc);
 
+	dp_sysfs_deinitialize_stats(soc);
 	dp_soc_swlm_detach(soc);
 	dp_soc_tx_desc_sw_pools_free(soc);
 	dp_soc_srng_free(soc);
@@ -9436,25 +9445,91 @@ dp_set_pdev_dscp_tid_map_wifi3(struct cdp_soc_t *soc_handle,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_SYSFS_DP_STATS
+/*
+ * dp_sysfs_event_trigger(): Trigger event to wait for firmware
+ * stats request response.
+ * @soc: soc handle
+ * @cookie_val: cookie value
+ *
+ * @Return: QDF_STATUS
+ */
+static QDF_STATUS
+dp_sysfs_event_trigger(struct dp_soc *soc, uint32_t cookie_val)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	/* wait for firmware response for sysfs stats request */
+	if (cookie_val == DBG_SYSFS_STATS_COOKIE) {
+		if (!soc) {
+			dp_cdp_err("soc is NULL");
+			return QDF_STATUS_E_FAILURE;
+		}
+		/* wait for event completion */
+		status = qdf_wait_single_event(&soc->sysfs_config->sysfs_txrx_fw_request_done,
+					       WLAN_SYSFS_STAT_REQ_WAIT_MS);
+		if (status == QDF_STATUS_SUCCESS)
+			dp_cdp_info("sysfs_txrx_fw_request_done event completed");
+		else if (status == QDF_STATUS_E_TIMEOUT)
+			dp_cdp_warn("sysfs_txrx_fw_request_done event expired");
+		else
+			dp_cdp_warn("sysfs_txrx_fw_request_done event erro code %d", status);
+	}
+
+	return status;
+}
+#else /* WLAN_SYSFS_DP_STATS */
+/*
+ * dp_sysfs_event_trigger(): Trigger event to wait for firmware
+ * stats request response.
+ * @soc: soc handle
+ * @cookie_val: cookie value
+ *
+ * @Return: QDF_STATUS
+ */
+static QDF_STATUS
+dp_sysfs_event_trigger(struct dp_soc *soc, uint32_t cookie_val)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_SYSFS_DP_STATS */
+
 /**
- * dp_fw_stats_process(): Process TxRX FW stats request
+ * dp_fw_stats_process(): Process TXRX FW stats request.
  * @vdev_handle: DP VDEV handle
  * @req: stats request
  *
- * return: int
+ * return: QDF_STATUS
  */
-static int dp_fw_stats_process(struct dp_vdev *vdev,
-			       struct cdp_txrx_stats_req *req)
+static QDF_STATUS
+dp_fw_stats_process(struct dp_vdev *vdev,
+		    struct cdp_txrx_stats_req *req)
 {
 	struct dp_pdev *pdev = NULL;
+	struct dp_soc *soc = NULL;
 	uint32_t stats = req->stats;
 	uint8_t mac_id = req->mac_id;
+	uint32_t cookie_val = DBG_STATS_COOKIE_DEFAULT;
 
 	if (!vdev) {
 		DP_TRACE(NONE, "VDEV not found");
-		return 1;
+		return QDF_STATUS_E_FAILURE;
 	}
+
 	pdev = vdev->pdev;
+	if (!pdev) {
+		DP_TRACE(NONE, "PDEV not found");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	soc = pdev->soc;
+	if (!soc) {
+		DP_TRACE(NONE, "soc not found");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* In case request is from host sysfs for displaying stats on console */
+	if (req->cookie_val == DBG_SYSFS_STATS_COOKIE)
+		cookie_val = DBG_SYSFS_STATS_COOKIE;
 
 	/*
 	 * For HTT_DBG_EXT_STATS_RESET command, FW need to config
@@ -9476,16 +9551,20 @@ static int dp_fw_stats_process(struct dp_vdev *vdev,
 	}
 
 	if (req->stats == (uint8_t)HTT_DBG_EXT_STATS_PDEV_RX_RATE_EXT) {
-		return dp_h2t_ext_stats_msg_send(pdev,
-				HTT_DBG_EXT_STATS_PDEV_RX_RATE_EXT,
-				req->param0, req->param1, req->param2,
-				req->param3, 0, DBG_STATS_COOKIE_DEFAULT,
-				mac_id);
+		dp_h2t_ext_stats_msg_send(pdev,
+					  HTT_DBG_EXT_STATS_PDEV_RX_RATE_EXT,
+					  req->param0, req->param1, req->param2,
+					  req->param3, 0, cookie_val,
+					  mac_id);
 	} else {
-		return dp_h2t_ext_stats_msg_send(pdev, stats, req->param0,
-				req->param1, req->param2, req->param3,
-				0, DBG_STATS_COOKIE_DEFAULT, mac_id);
+		dp_h2t_ext_stats_msg_send(pdev, stats, req->param0,
+					  req->param1, req->param2, req->param3,
+					  0, cookie_val, mac_id);
 	}
+
+	dp_sysfs_event_trigger(soc, cookie_val);
+
+	return QDF_STATUS_SUCCESS;
 }
 
 /**
@@ -9628,6 +9707,202 @@ static QDF_STATUS dp_txrx_dump_stats(struct cdp_soc_t *psoc, uint16_t value,
 
 }
 
+#ifdef WLAN_SYSFS_DP_STATS
+static
+void dp_sysfs_get_stat_type(struct dp_soc *soc, uint32_t *mac_id,
+			    uint32_t *stat_type)
+{
+	qdf_spinlock_acquire(&soc->sysfs_config->rw_stats_lock);
+	*stat_type = soc->sysfs_config->stat_type_requested;
+	*mac_id   = soc->sysfs_config->mac_id;
+
+	qdf_spinlock_release(&soc->sysfs_config->rw_stats_lock);
+}
+
+static
+void dp_sysfs_update_config_buf_params(struct dp_soc *soc,
+				       uint32_t curr_len,
+				       uint32_t max_buf_len,
+				       char *buf)
+{
+	qdf_spinlock_acquire(&soc->sysfs_config->sysfs_write_user_buffer);
+	/* set sysfs_config parameters */
+	soc->sysfs_config->buf = buf;
+	soc->sysfs_config->curr_buffer_length = curr_len;
+	soc->sysfs_config->max_buffer_length = max_buf_len;
+	qdf_spinlock_release(&soc->sysfs_config->sysfs_write_user_buffer);
+}
+
+static
+QDF_STATUS dp_sysfs_fill_stats(ol_txrx_soc_handle soc_hdl,
+			       char *buf, uint32_t buf_size)
+{
+	uint32_t mac_id = 0;
+	uint32_t stat_type = 0;
+	uint32_t fw_stats = 0;
+	uint32_t host_stats = 0;
+	enum cdp_stats stats;
+	struct cdp_txrx_stats_req req;
+	struct dp_soc *soc = NULL;
+
+	if (!soc_hdl) {
+		dp_cdp_err("%pK: soc_hdl is NULL", soc_hdl);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	soc = cdp_soc_t_to_dp_soc(soc_hdl);
+
+	if (!soc) {
+		dp_cdp_err("%pK: soc is NULL", soc);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	dp_sysfs_get_stat_type(soc, &mac_id, &stat_type);
+
+	stats = stat_type;
+	if (stats >= CDP_TXRX_MAX_STATS) {
+		dp_cdp_info("sysfs stat type requested is invalid");
+		return QDF_STATUS_E_INVAL;
+	}
+	/*
+	 * DP_CURR_FW_STATS_AVAIL: no of FW stats currently available
+	 *			has to be updated if new FW HTT stats added
+	 */
+	if (stats > CDP_TXRX_MAX_STATS)
+		stats = stats + DP_CURR_FW_STATS_AVAIL - DP_HTT_DBG_EXT_STATS_MAX;
+
+	/* build request */
+	fw_stats = dp_stats_mapping_table[stats][STATS_FW];
+	host_stats = dp_stats_mapping_table[stats][STATS_HOST];
+
+	req.stats = stat_type;
+	req.mac_id = mac_id;
+	/* request stats to be printed */
+	qdf_mutex_acquire(&soc->sysfs_config->sysfs_read_lock);
+
+	if (fw_stats != TXRX_FW_STATS_INVALID) {
+		/* update request with FW stats type */
+		req.cookie_val = DBG_SYSFS_STATS_COOKIE;
+	} else if ((host_stats != TXRX_HOST_STATS_INVALID) &&
+			(host_stats <= TXRX_HOST_STATS_MAX)) {
+		req.cookie_val = DBG_STATS_COOKIE_DEFAULT;
+		soc->sysfs_config->process_id = qdf_get_current_pid();
+		soc->sysfs_config->printing_mode = PRINTING_MODE_ENABLED;
+	}
+
+	dp_sysfs_update_config_buf_params(soc, 0, buf_size, buf);
+
+	dp_txrx_stats_request(soc_hdl, mac_id, &req);
+	soc->sysfs_config->process_id = 0;
+	soc->sysfs_config->printing_mode = PRINTING_MODE_DISABLED;
+
+	dp_sysfs_update_config_buf_params(soc, 0, 0, NULL);
+
+	qdf_mutex_release(&soc->sysfs_config->sysfs_read_lock);
+	return QDF_STATUS_SUCCESS;
+}
+
+static
+QDF_STATUS dp_sysfs_set_stat_type(ol_txrx_soc_handle soc_hdl,
+				  uint32_t stat_type, uint32_t mac_id)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+
+	if (!soc_hdl) {
+		dp_cdp_err("%pK: soc is NULL", soc);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	qdf_spinlock_acquire(&soc->sysfs_config->rw_stats_lock);
+
+	soc->sysfs_config->stat_type_requested = stat_type;
+	soc->sysfs_config->mac_id = mac_id;
+
+	qdf_spinlock_release(&soc->sysfs_config->rw_stats_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static
+QDF_STATUS dp_sysfs_initialize_stats(struct dp_soc *soc_hdl)
+{
+	struct dp_soc *soc;
+	QDF_STATUS status;
+
+	if (!soc_hdl) {
+		dp_cdp_err("%pK: soc_hdl is NULL", soc_hdl);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	soc = soc_hdl;
+
+	soc->sysfs_config = qdf_mem_malloc(sizeof(struct sysfs_stats_config));
+	if (!soc->sysfs_config) {
+		dp_cdp_err("failed to allocate memory for sysfs_config no memory");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	status = qdf_event_create(&soc->sysfs_config->sysfs_txrx_fw_request_done);
+	/* create event for fw stats request from sysfs */
+	if (status != QDF_STATUS_SUCCESS) {
+		dp_cdp_err("failed to create event sysfs_txrx_fw_request_done");
+		qdf_mem_free(soc->sysfs_config);
+		soc->sysfs_config = NULL;
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_spinlock_create(&soc->sysfs_config->rw_stats_lock);
+	qdf_mutex_create(&soc->sysfs_config->sysfs_read_lock);
+	qdf_spinlock_create(&soc->sysfs_config->sysfs_write_user_buffer);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static
+QDF_STATUS dp_sysfs_deinitialize_stats(struct dp_soc *soc_hdl)
+{
+	struct dp_soc *soc;
+	QDF_STATUS status;
+
+	if (!soc_hdl) {
+		dp_cdp_err("%pK: soc_hdl is NULL", soc_hdl);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	soc = soc_hdl;
+	if (!soc->sysfs_config) {
+		dp_cdp_err("soc->sysfs_config is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = qdf_event_destroy(&soc->sysfs_config->sysfs_txrx_fw_request_done);
+	if (status != QDF_STATUS_SUCCESS)
+		dp_cdp_err("Failed to detroy event sysfs_txrx_fw_request_done ");
+
+	qdf_mutex_destroy(&soc->sysfs_config->sysfs_read_lock);
+	qdf_spinlock_destroy(&soc->sysfs_config->rw_stats_lock);
+	qdf_spinlock_destroy(&soc->sysfs_config->sysfs_write_user_buffer);
+
+	qdf_mem_free(soc->sysfs_config);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+#else /* WLAN_SYSFS_DP_STATS */
+
+static
+QDF_STATUS dp_sysfs_deinitialize_stats(struct dp_soc *soc_hdl)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static
+QDF_STATUS dp_sysfs_initialize_stats(struct dp_soc *soc_hdl)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_SYSFS_DP_STATS */
+
 /**
  * dp_txrx_clear_dump_stats() - clear dumpStats
  * @soc- soc handle
@@ -10788,6 +11063,10 @@ static struct cdp_cmn_ops dp_ops_cmn = {
 #if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE)
 	.txrx_drain = dp_drain_txrx,
 #endif
+#ifdef WLAN_SYSFS_DP_STATS
+	.txrx_sysfs_fill_stats = dp_sysfs_fill_stats,
+	.txrx_sysfs_set_stat_type = dp_sysfs_set_stat_type,
+#endif /* WLAN_SYSFS_DP_STATS */
 };
 
 static struct cdp_ctrl_ops dp_ops_ctrl = {
@@ -11773,6 +12052,11 @@ dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
 		}
 	}
 
+	if (dp_sysfs_initialize_stats(soc) != QDF_STATUS_SUCCESS) {
+		dp_err("failed to initialize dp stats sysfs file");
+		dp_sysfs_deinitialize_stats(soc);
+	}
+
 	dp_soc_swlm_attach(soc);
 	dp_soc_set_interrupt_mode(soc);
 	dp_soc_set_def_pdev(soc);

+ 41 - 1
dp/wifi3.0/dp_types.h

@@ -1664,6 +1664,43 @@ struct dp_soc_features {
 	uint8_t pn_in_reo_dest;
 };
 
+enum sysfs_printing_mode {
+	PRINTING_MODE_DISABLED = 0,
+	PRINTING_MODE_ENABLED
+};
+
+#ifdef WLAN_SYSFS_DP_STATS
+/**
+ * struct sysfs_stats_config: Data structure holding stats sysfs config.
+ * @rw_stats_lock: Lock to read and write to stat_type and pdev_id.
+ * @sysfs_read_lock: Lock held while another stat req is being executed.
+ * @sysfs_write_user_buffer: Lock to change buff len, max buf len
+ * and *buf.
+ * @sysfs_txrx_fw_request_done: Event to wait for firmware response.
+ * @stat_type_requested: stat type requested.
+ * @mac_id: mac id for which stat type are requested.
+ * @printing_mode: Should a print go through.
+ * @process_id: Process allowed to write to buffer.
+ * @curr_buffer_length: Curr length of buffer written
+ * @max_buffer_length: Max buffer length.
+ * @buf: Sysfs buffer.
+ */
+struct sysfs_stats_config {
+	/* lock held to read stats */
+	qdf_spinlock_t rw_stats_lock;
+	qdf_mutex_t sysfs_read_lock;
+	qdf_spinlock_t sysfs_write_user_buffer;
+	qdf_event_t sysfs_txrx_fw_request_done;
+	uint32_t stat_type_requested;
+	uint32_t mac_id;
+	enum sysfs_printing_mode printing_mode;
+	int process_id;
+	uint16_t curr_buffer_length;
+	uint16_t max_buffer_length;
+	char *buf;
+};
+#endif
+
 /* SOC level structure for data path */
 struct dp_soc {
 	/**
@@ -1896,7 +1933,10 @@ struct dp_soc {
 
 	/* SoC level data path statistics */
 	struct dp_soc_stats stats;
-
+#ifdef WLAN_SYSFS_DP_STATS
+	/* sysfs config for DP stats */
+	struct sysfs_stats_config *sysfs_config;
+#endif
 	/* timestamp to keep track of msdu buffers received on reo err ring */
 	uint64_t rx_route_err_start_pkt_ts;