Browse Source

qcacmn: Add TxRx Statistics for Lithium datapath

Statistics can be displayed by issuing following commands

iwpriv ath0 txrx_fw_stats 3 /*Rx Rate Info*/
iwpriv ath0 txrx_fw_stats 6 /*Tx Rate Info*/
iwpriv ath0 txrx_fw_stats 8 /* print Tx stats */
iwpriv ath0 txrx_fw_stats 27 /*print Rx stats */

To reset the stats:
iwpriv ath0 txrx_fw_stats 9 /* clear all stats */

Change-Id: If4be2549f43403e71ef092c23b1cf14b35a2e5d4
CRs-Fixed: 1114641
Ishank Jain 8 years ago
parent
commit
bc2d91f8f3

+ 16 - 0
dp/inc/cdp_txrx_cmn_struct.h

@@ -73,6 +73,21 @@ enum htt_cmn_dbg_stats_type {
     HTT_DBG_CMN_NUM_STATS
 };
 
+/*
+ * cdp_host_txrx_stats: Different types of host stats
+ * @TXRX_RX_RATE_STATS: Rx rate info
+ * @TXRX_TX_RATE_STATS: Tx rate info
+ * @TXRX_TX_HOST_STATS: Print Tx stats
+ * @TXRX_RX_HOST_STATS: Print host Rx stats
+ * @TXRX_CLEAR_STATS: clear all host stats
+ */
+enum cdp_host_txrx_stats {
+	TXRX_RX_RATE_STATS  = 0,
+	TXRX_TX_RATE_STATS  = 1,
+	TXRX_TX_HOST_STATS  = 2,
+	TXRX_RX_HOST_STATS  = 3,
+	TXRX_CLEAR_STATS    = 4,
+};
 
 /**
  * @brief General specification of the tx frame contents
@@ -384,6 +399,7 @@ struct cdp_soc_t {
 #define TXRX_FW_MAC_PREFETCH_MGR_STATS           23
 #define TXRX_FW_STATS_DURATION_INFO              24
 #define TXRX_FW_STATS_DURATION_INFO_RESET        25
+#define TXRX_FW_STATS_HOST_RX_STATS              27
 
 #define PER_RADIO_FW_STATS_REQUEST 0
 #define PER_VDEV_FW_STATS_REQUEST 1

+ 11 - 12
dp/inc/cdp_txrx_host_stats.h

@@ -37,24 +37,24 @@
 /* Need to rename the function to reflect the functionality "show" / "display"
  * WIN -- to figure out whether to change OSIF to converge (not an immediate AI)
  * */
+/**
+ * cdp_host_stats_get: cdp call to get host stats
+ * @soc: SOC handle
+ * @req: Requirement type
+ * @type: Host stat type
+ *
+ * return: 0 for Success, Failure returns error message
+ */
 static inline int cdp_host_stats_get(ol_txrx_soc_handle soc,
 	struct cdp_vdev *vdev,
-	struct ol_txrx_stats_req *req)
+	struct ol_txrx_stats_req *req, enum cdp_host_txrx_stats type)
 {
 	if (soc->ops->host_stats_ops->txrx_host_stats_get)
-		return soc->ops->host_stats_ops->txrx_host_stats_get(vdev, req);
+		return soc->ops->host_stats_ops->txrx_host_stats_get(vdev, req,
+				type);
 	return 0;
 }
 
-
-static inline void
-cdp_host_stats_clr(ol_txrx_soc_handle soc, struct cdp_vdev *vdev)
-{
-	if (soc->ops->host_stats_ops->txrx_host_stats_clr)
-		return soc->ops->host_stats_ops->txrx_host_stats_clr(vdev);
-	return;
-}
-
 static inline void
 cdp_host_ce_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev)
 {
@@ -213,7 +213,6 @@ cdp_reset_lro_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev)
 	return;
 }
 
-
 /**
  * @brief Parse the stats header and get the payload from the message.
  *

+ 2 - 3
dp/inc/cdp_txrx_ops.h

@@ -404,9 +404,8 @@ struct cdp_mon_ops {
 
 struct cdp_host_stats_ops {
 	int (*txrx_host_stats_get)(struct cdp_vdev *vdev,
-			struct ol_txrx_stats_req *req);
-
-	void (*txrx_host_stats_clr)(struct cdp_vdev *vdev);
+			struct ol_txrx_stats_req *req,
+			enum cdp_host_txrx_stats type);
 
 	void (*txrx_host_ce_stats)(struct cdp_vdev *vdev);
 

+ 55 - 0
dp/wifi3.0/dp_internal.h

@@ -53,6 +53,52 @@ while (0)
 #define DP_PRINT(level, fmt, ...)
 #endif /* DP_PRINT_ENABLE */
 
+#define DP_TRACE(LVL, fmt, args ...)                             \
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_##LVL,       \
+		"%s:%d: "fmt, __func__, __LINE__, ## args)
+
+#define DP_STATS_INIT(_handle) \
+	qdf_mem_set(&((_handle)->stats), sizeof((_handle)->stats), 0x0)
+
+#define DP_STATS_CLR(_handle) \
+	qdf_mem_set(&((_handle)->stats), sizeof((_handle)->stats), 0x0)
+
+#ifndef DISABLE_DP_STATS
+#define DP_STATS_INC(_handle, _field, _delta) \
+{ \
+	_handle->stats._field += _delta; \
+}
+
+#define DP_STATS_INCC(_handle, _field, _delta, _cond) \
+{ \
+	if (_cond) { \
+		_handle->stats._field += _delta; \
+	} \
+}
+
+#define DP_STATS_DEC(_handle, _field, _delta) \
+{ \
+	_handle->stats._field -= _delta; \
+}
+
+#define DP_STATS_UPD(_handle, _field, _delta) \
+{ \
+	_handle->stats._field = _delta \
+}
+
+#define DP_STATS_INC_PKT(_handle, _field, _count, _bytes) \
+{ \
+	DP_STATS_INC(_handle, _field.num, _count); \
+	DP_STATS_INC(_handle, _field.bytes, _bytes) \
+}
+#else
+#define DP_STATS_INC(_handle, _field, _delta)
+#define DP_STATS_INCC(_handle, _field, _delta, _cond)
+#define DP_STATS_DEC(_handle, _field, _delta)
+#define DP_STATS_UPD(_handle, _field, _delta)
+#define DP_STATS_INC_PKT(_handle, _field, _count, _bytes)
+#endif
+
 extern int dp_peer_find_attach(struct dp_soc *soc);
 extern void dp_peer_find_detach(struct dp_soc *soc);
 extern void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer);
@@ -105,4 +151,13 @@ extern QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc,
 	void (*callback_fn), void *data);
 
 extern void dp_reo_status_ring_handler(struct dp_soc *soc);
+int dp_print_host_stats(struct cdp_vdev *vdev_handle,
+		struct ol_txrx_stats_req *req, enum cdp_host_txrx_stats type);
+void dp_print_pdev_tx_stats(struct dp_pdev *pdev);
+void dp_print_pdev_rx_stats(struct dp_pdev *pdev);
+void dp_print_soc_tx_stats(struct dp_soc *soc);
+void dp_print_soc_rx_stats(struct dp_soc *soc);
+void dp_txrx_host_stats_clr(struct dp_vdev *vdev);
+void dp_print_rx_rates(struct dp_vdev *vdev);
+void dp_print_tx_rates(struct dp_vdev *vdev);
 #endif /* #ifndef _DP_INTERNAL_H_ */

+ 401 - 0
dp/wifi3.0/dp_main.c

@@ -30,8 +30,13 @@
 #include "dp_rx.h"
 #include <cdp_txrx_handle.h>
 #include <wlan_cfg.h>
+#include "cdp_txrx_cmn_struct.h"
 
 #define DP_INTR_POLL_TIMER_MS	100
+#define DP_MCS_LENGTH (6*MAX_MCS)
+#define DP_NSS_LENGTH (6*SS_COUNT)
+#define DP_RXDMA_ERR_LENGTH (6*MAX_RXDMA_ERRORS)
+#define DP_REO_ERR_LENGTH (6*HAL_REO_ERR_QUEUE_DESC_BLOCKED_SET)
 /**
  * dp_setup_srng - Internal function to setup SRNG rings used by data path
  */
@@ -1035,6 +1040,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 				FL("dp_rx_pdev_attach failed "));
 			goto fail0;
 	}
+	DP_STATS_INIT(pdev);
 
 #ifndef CONFIG_WIN
 	/* MCL */
@@ -1318,6 +1324,7 @@ static int dp_soc_attach_target_wifi3(struct cdp_soc_t *cdp_soc)
 
 	dp_rxdma_ring_config(soc);
 
+	DP_STATS_INIT(soc);
 	return 0;
 }
 
@@ -1901,6 +1908,7 @@ static struct cdp_mon_ops dp_ops_mon = {
 };
 
 static struct cdp_host_stats_ops dp_ops_host_stats = {
+	.txrx_host_stats_get = dp_print_host_stats,
 	/* TODO */
 };
 
@@ -2098,3 +2106,396 @@ fail1:
 fail0:
 	return NULL;
 }
+
+/*
+ * dp_print_host_stats()- Function to print the stats aggregated at host
+ * @vdev_handle: DP_VDEV handle
+ * @req: ol_txrx_stats_req
+ * @type: host stats type
+ *
+ * Available Stat types
+ * TXRX_RX_RATE_STATS: Print Rx Rate Info
+ * TXRX_TX_RATE_STATS: Print Tx Rate Info
+ * TXRX_TX_HOST_STATS: Print Tx Stats
+ * TXRX_RX_HOST_STATS: Print Rx Stats
+ * TXRX_CLEAR_STATS:   Clear the stats
+ *
+ * Return: 0 on success
+ */
+int
+dp_print_host_stats(struct cdp_vdev *vdev_handle, struct ol_txrx_stats_req *req,
+		enum cdp_host_txrx_stats type)
+{
+	struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle;
+	struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
+
+	switch (type) {
+	case TXRX_RX_RATE_STATS:
+		dp_print_rx_rates(vdev);
+		break;
+	case TXRX_TX_RATE_STATS:
+		dp_print_tx_rates(vdev);
+		break;
+	case TXRX_TX_HOST_STATS:
+		dp_print_pdev_tx_stats(pdev);
+		dp_print_soc_tx_stats(pdev->soc);
+		break;
+	case TXRX_RX_HOST_STATS:
+		dp_print_pdev_rx_stats(pdev);
+		dp_print_soc_rx_stats(pdev->soc);
+		break;
+	case TXRX_CLEAR_STATS:
+		dp_txrx_host_stats_clr(vdev);
+		break;
+	default:
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+				"Wrong Input For TxRx Host Stats");
+		break;
+	}
+	return 0;
+}
+
+/*
+ * dp_print_pdev_tx_stats(): Print Pdev level TX stats
+ * @pdev: DP_PDEV Handle
+ *
+ * Return:void
+ */
+void
+dp_print_pdev_tx_stats(struct dp_pdev *pdev)
+{
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"\n WLAN Tx Stats\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Received From Stack\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets Received: %d ",
+			pdev->stats.tx.rcvd.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent: %d ",
+			pdev->stats.tx.rcvd.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Processed\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Msdu Processed: %d ", pdev->stats.tx.processed.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Processed: %d ",
+			pdev->stats.tx.processed.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Completions\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Msdu Sent: %d ", pdev->stats.tx.comp.comp_pkt.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent: %d ",
+			pdev->stats.tx.comp.comp_pkt.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Freed\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Msdus Freed: %d ", pdev->stats.tx.freed.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Freed: %d ", pdev->stats.tx.freed.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets Dropped: %d ",
+			pdev->stats.tx.dropped.dropped_pkt.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Dropped: %d ",
+			pdev->stats.tx.dropped.dropped_pkt.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dma_map_error: %d ",
+			pdev->stats.tx.dropped.dma_map_error);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Ring Full: %d ", pdev->stats.tx.dropped.ring_full);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Fw Discard: %d ",
+			pdev->stats.tx.dropped.fw_discard);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Fw Discard Retired: %d ",
+			pdev->stats.tx.dropped.fw_discard_retired);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Firmware Discard Untransmitted: %d ",
+			pdev->stats.tx.dropped.firmware_discard_untransmitted);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Mpdu Age Out: %d ",
+			pdev->stats.tx.dropped.mpdu_age_out);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Firmware Discard Reason1: %d ",
+			pdev->stats.tx.dropped.firmware_discard_reason1);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Firmware Discard Reason2: %d ",
+			pdev->stats.tx.dropped.firmware_discard_reason2);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Firmware Discard Reason3: %d ",
+			pdev->stats.tx.dropped.firmware_discard_reason3);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Scatter Gather\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets: %d ", pdev->stats.tx.sg.sg_pkt.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Bytes: %d ", pdev->stats.tx.sg.sg_pkt.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped By Host: %d ",
+			pdev->stats.tx.sg.dropped_host);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped By Target: %d ",
+			pdev->stats.tx.sg.dropped_target);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Tso\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Number of Segments: %d ",
+			pdev->stats.tx.tso.num_seg);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Number Packets: %d ",
+			pdev->stats.tx.tso.tso_pkt.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Bytes: %d ",
+			pdev->stats.tx.tso.tso_pkt.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped By Host: %d ",
+			pdev->stats.tx.tso.dropped_host);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Mcast Enhancement\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped: Map Errors: %d ",
+			pdev->stats.tx.mcast_en.dropped_map_error);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped: Self Mac: %d ",
+			pdev->stats.tx.mcast_en.dropped_self_mac);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped: Send Fail: %d ",
+			pdev->stats.tx.mcast_en.dropped_send_fail);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Unicast sent: %d ",
+			pdev->stats.tx.mcast_en.ucast);
+}
+
+/*
+ * dp_print_pdev_rx_stats(): Print Pdev level RX stats
+ * @pdev: DP_PDEV Handle
+ *
+ * Return: void
+ */
+void
+dp_print_pdev_rx_stats(struct dp_pdev *pdev)
+{
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"\n WLAN Rx Stats\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Received From HW (Reo Dest Ring)\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets Received: %d ",
+			pdev->stats.rx.rcvd_reo.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent: %d ", pdev->stats.rx.rcvd_reo.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Replenished\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets Replenished: %d ",
+			pdev->stats.rx.replenished.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent: %d ", pdev->stats.rx.replenished.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Buffers Added To Freelist: %d ",
+			pdev->stats.rx.buf_freelist);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Dropped\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets With No Peer: %d ",
+			pdev->stats.rx.dropped.no_peer.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent With No Peer: %d ",
+			pdev->stats.rx.dropped.no_peer.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Total Packets With Msdu Not Done: %d ",
+			pdev->stats.rx.dropped.msdu_not_done.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent With Msdu Not Done: %d ",
+			pdev->stats.rx.dropped.msdu_not_done.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Sent To Stack\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Packets Sent To Stack: %d ",
+			pdev->stats.rx.to_stack.num);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Bytes Sent To Stack: %d ",
+			pdev->stats.rx.to_stack.bytes);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Errors\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Rxdma Ring Unititalized: %d",
+			pdev->stats.rx.err.rxdma_unitialized);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Desc Alloc Failed: %d",
+			pdev->stats.rx.err.desc_alloc_fail);
+}
+
+/*
+ * dp_print_soc_tx_stats(): Print SOC level  stats
+ * @soc DP_SOC Handle
+ *
+ * Return: void
+ */
+void
+dp_print_soc_tx_stats(struct dp_soc *soc)
+{
+
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"\n SOC Tx Stats\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Tx Descriptors In Use: %d ",
+			soc->stats.tx.desc_in_use);
+}
+
+
+/*
+ * dp_print_soc_rx_stats: Print SOC level Rx stats
+ * @soc: DP_SOC Handle
+ *
+ * Return:void
+ */
+void
+dp_print_soc_rx_stats(struct dp_soc *soc)
+{
+	uint32_t i;
+	char reo_error[DP_REO_ERR_LENGTH];
+	char rxdma_error[DP_RXDMA_ERR_LENGTH];
+	uint8_t index = 0;
+
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"\n SOC Rx Stats\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Errors\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Invalid RBM: %d ", soc->stats.rx.err.invalid_rbm);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Invalid Vdev: %d ", soc->stats.rx.err.invalid_vdev);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Invalid Pdev: %d ", soc->stats.rx.err.invalid_pdev);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" HAL Ring Access Fail: %d ",
+			soc->stats.rx.err.hal_ring_access_fail);
+	for (i = 0; i < MAX_RXDMA_ERRORS; i++) {
+		index += qdf_snprint(&rxdma_error[index],
+				DP_RXDMA_ERR_LENGTH - index,
+				" %d,", soc->stats.rx.err.rxdma_error[i]);
+	}
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" RXDMA Error (0-31):%s", rxdma_error);
+	index = 0;
+	for (i = 0; i <= HAL_REO_ERR_QUEUE_DESC_BLOCKED_SET; i++) {
+		index += qdf_snprint(&reo_error[index],
+				DP_REO_ERR_LENGTH - index,
+				" %d,", soc->stats.rx.err.reo_error[i]);
+	}
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" REO Error(0-14):%s", reo_error);
+}
+
+/*
+ * dp_txrx_host_stats_clr(): Reinitialize the txrx stats
+ * @vdev: DP_VDEV handle
+ *
+ * Return:void
+ */
+void
+dp_txrx_host_stats_clr(struct dp_vdev *vdev)
+{
+	DP_STATS_CLR(vdev->pdev);
+	DP_STATS_CLR(vdev->pdev->soc);
+}
+
+/*
+ * dp_print_rx_rates(): Print Rx rate stats
+ * @vdev: DP_VDEV handle
+ *
+ * Return:void
+ */
+void
+dp_print_rx_rates(struct dp_vdev *vdev)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
+	uint8_t i;
+	uint8_t index = 0;
+	char mcs[DP_MCS_LENGTH];
+	char nss[DP_NSS_LENGTH];
+
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"\n Rx Rate Info\n");
+	for (i = 0; i < MAX_MCS; i++) {
+		index += qdf_snprint(&mcs[index], DP_MCS_LENGTH - index,
+				" %d,", pdev->stats.rx.mcs_count[i]);
+	}
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" MCS(0-11):%s", mcs);
+	index = 0;
+	for (i = 0; i < SS_COUNT; i++) {
+		index += qdf_snprint(&nss[index], DP_NSS_LENGTH - index,
+				" %d,", pdev->stats.rx.nss[i]);
+	}
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" NSS(0-7):%s", nss);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"SGI: 0.8us:%d, 0.4us:%d, 1.6us:%d, 3.2us:%d,",
+			pdev->stats.rx.sgi_count[0],
+			pdev->stats.rx.sgi_count[1],
+			pdev->stats.rx.sgi_count[2],
+			pdev->stats.rx.sgi_count[3]);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"BW Counts: 20MHZ %d, 40MHZ %d, 80MHZ %d, 160MHZ %d",
+			pdev->stats.rx.bw[0], pdev->stats.rx.bw[1],
+			pdev->stats.rx.bw[2], pdev->stats.rx.bw[3]);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"Reception Type:"
+			" SU:%d,"
+			" MU_MIMO:%d,"
+			" MU_OFDMA:%d,"
+			" MU_OFDMA_MIMO:%d",
+			pdev->stats.rx.reception_type[0],
+			pdev->stats.rx.reception_type[1],
+			pdev->stats.rx.reception_type[2],
+			pdev->stats.rx.reception_type[3]);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Aggregation\n");
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Number of Msdu's Part of Ampdu: %d ",
+			pdev->stats.rx.ampdu_cnt);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Number of Msdu's With No Mpdu Level Aggregation : %d",
+			pdev->stats.rx.non_ampdu_cnt);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Number of Msdu's Part of Amsdu: %d",
+			pdev->stats.rx.amsdu_cnt);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" Number of Msdu's With No Msdu Level Aggregation: %d",
+			pdev->stats.rx.non_amsdu_cnt);
+}
+
+/*
+ * dp_print_tx_rates(): Print tx rates
+ * @vdev: DP_VDEV handle
+ *
+ * Return:void
+ */
+void
+dp_print_tx_rates(struct dp_vdev *vdev)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
+	uint8_t i;
+	char mcs[DP_MCS_LENGTH];
+	uint8_t index = 0;
+
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			"\n Tx Rate Info\n");
+
+	for (i = 0; i < MAX_MCS; i++) {
+		index += qdf_snprint(&mcs[index], DP_MCS_LENGTH - index,
+				" %d ", pdev->stats.tx.comp.mcs_count[i]);
+	}
+
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" MCS(0-11):%s", mcs);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_NONE,
+			" MCS Invalid: %d ",
+			pdev->stats.tx.comp.mcs_count[MAX_MCS]);
+}

+ 45 - 2
dp/wifi3.0/dp_rx.c

@@ -26,6 +26,7 @@
 #ifdef MESH_MODE_SUPPORT
 #include "if_meta_hdr.h"
 #endif
+#include "dp_internal.h"
 
 /*
  * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
@@ -63,6 +64,7 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
 	if (!rxdma_srng) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			"rxdma srng not initialized");
+		DP_STATS_INC(dp_pdev, rx.err.rxdma_unitialized, 1);
 		return QDF_STATUS_E_FAILURE;
 	}
 
@@ -81,6 +83,8 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
 		if (!num_alloc_desc) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				"no free rx_descs in freelist");
+			DP_STATS_INC(dp_pdev, rx.err.desc_alloc_fail,
+					num_alloc_desc);
 			return QDF_STATUS_E_NOMEM;
 		}
 
@@ -138,6 +142,8 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
 		next = (*desc_list)->next;
 
 		(*desc_list)->rx_desc.nbuf = rx_netbuf;
+		DP_STATS_INC_PKT(dp_pdev, rx.replenished, 1,
+				qdf_nbuf_len(rx_netbuf));
 		hal_rxdma_buff_addr_info_set(rxdma_ring_entry, paddr,
 						(*desc_list)->rx_desc.cookie,
 						owner);
@@ -151,6 +157,7 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
 		"successfully replenished %d buffers", num_req_buffers);
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		"%d rx desc added back to free list", num_desc_to_free);
+	DP_STATS_INC(dp_pdev, rx.buf_freelist, num_desc_to_free);
 
 	/*
 	 * add any available free desc back to the free list
@@ -392,17 +399,18 @@ dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 	struct dp_peer *peer = NULL;
 	struct dp_vdev *vdev = NULL;
 	struct dp_vdev *vdev_list[WLAN_UMAC_PSOC_MAX_VDEVS] = { NULL };
+	uint32_t pkt_len;
 	struct hal_rx_mpdu_desc_info mpdu_desc_info;
 	struct hal_rx_msdu_desc_info msdu_desc_info;
 	enum hal_reo_error_status error;
-	uint32_t pkt_len;
 	static uint32_t peer_mdata;
 	uint8_t *rx_tlv_hdr;
 	uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 };
-	uint32_t sgi, rate_mcs, tid;
+	uint32_t sgi, rate_mcs, tid, nss, bw, reception_type;
 	uint64_t vdev_map = 0;
 	uint8_t mac_id;
 	uint16_t i, vdev_cnt = 0;
+	uint32_t ampdu_flag, amsdu_flag;
 
 	/* Debug -- Remove later */
 	qdf_assert(soc && hal_ring);
@@ -469,6 +477,7 @@ dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 
 			/* Drop & free packet */
 			qdf_nbuf_free(rx_desc->nbuf);
+			/* Statistics */
 			goto fail;
 		}
 
@@ -503,6 +512,25 @@ dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
 		if (msdu_desc_info.msdu_flags & HAL_MSDU_F_LAST_MSDU_IN_MPDU)
 			qdf_nbuf_set_chfrag_end(rx_desc->nbuf, 1);
 
+		DP_STATS_INC_PKT(vdev->pdev, rx.rcvd_reo, 1,
+				qdf_nbuf_len(rx_desc->nbuf));
+
+		ampdu_flag = (mpdu_desc_info.mpdu_flags &
+				HAL_MPDU_F_AMPDU_FLAG);
+		DP_STATS_INCC(vdev->pdev, rx.ampdu_cnt, 1, ampdu_flag);
+		DP_STATS_INCC(vdev->pdev, rx.non_ampdu_cnt, 1, !(ampdu_flag));
+
+		hal_rx_msdu_desc_info_get(ring_desc, &msdu_desc_info);
+		amsdu_flag = ((msdu_desc_info.msdu_flags &
+				HAL_MSDU_F_FIRST_MSDU_IN_MPDU) &&
+				(msdu_desc_info.msdu_flags &
+					HAL_MSDU_F_LAST_MSDU_IN_MPDU));
+
+		DP_STATS_INCC(vdev->pdev, rx.non_amsdu_cnt, 1,
+				amsdu_flag);
+		DP_STATS_INCC(vdev->pdev, rx.amsdu_cnt, 1,
+				!(amsdu_flag));
+
 		qdf_nbuf_queue_add(&vdev->rxq, rx_desc->nbuf);
 fail:
 		dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
@@ -591,6 +619,20 @@ done:
 				"%s: %d, SGI: %d, rate_mcs: %d, tid: %d",
 				__func__, __LINE__, sgi, rate_mcs, tid);
 
+			bw = hal_rx_msdu_start_bw_get(rx_tlv_hdr);
+			reception_type = hal_rx_msdu_start_reception_type_get(
+					rx_tlv_hdr);
+			nss = hal_rx_msdu_start_nss_get(rx_tlv_hdr);
+
+			DP_STATS_INC(vdev->pdev, rx.bw[bw], 1);
+			DP_STATS_INC(vdev->pdev,
+					rx.reception_type[reception_type], 1);
+			DP_STATS_INCC(vdev->pdev, rx.nss[nss], 1,
+					((reception_type ==
+					  RECEPTION_TYPE_MU_MIMO) ||
+					 (reception_type ==
+					  RECEPTION_TYPE_MU_OFDMA_MIMO)));
+
 			/*
 			 * HW structures call this L3 header padding --
 			 * even though this is actually the offset from
@@ -647,6 +689,7 @@ done:
 			DP_RX_LIST_APPEND(deliver_list_head,
 						deliver_list_tail,
 						nbuf);
+			DP_STATS_INC(vdev->pdev, rx.to_stack.num, 1);
 		}
 
 		if (qdf_unlikely(vdev->rx_decap_type == htt_pkt_type_raw))

+ 3 - 0
dp/wifi3.0/dp_rx_err.c

@@ -375,9 +375,11 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 
 		qdf_nbuf_set_next(nbuf, NULL);
 		vdev->osif_rx(vdev->osif_vdev, nbuf);
+		DP_STATS_INC(vdev->pdev, rx.to_stack.num, 1);
 	} else {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("INVALID vdev %p OR osif_rx"), vdev);
+		DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
 	}
 
 fail:
@@ -421,6 +423,7 @@ dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc)
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("HAL RING Access For WBM Release SRNG Failed - %p"),
 			wbm_rel_srng);
+		DP_STATS_INC(soc, rx.err.hal_ring_access_fail, 1);
 		goto done;
 	}
 	src_srng_desc = hal_srng_src_get_next(hal_soc, wbm_rel_srng);

+ 45 - 9
dp/wifi3.0/dp_tx.c

@@ -120,6 +120,8 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id)
 	qdf_assert(pdev);
 
 	soc = pdev->soc;
+
+	DP_STATS_INC(pdev, tx.freed.num, 1);
 	if (tx_desc->flags & DP_TX_DESC_FLAG_FRAG)
 		dp_tx_ext_desc_free(soc, tx_desc->msdu_ext_desc, desc_pool_id);
 
@@ -351,6 +353,8 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev,
 	return tx_desc;
 
 failure:
+	DP_STATS_INC_PKT(pdev, tx.dropped.dropped_pkt, 1,
+			qdf_nbuf_len(nbuf));
 	dp_tx_desc_release(tx_desc, desc_pool_id);
 	return NULL;
 }
@@ -426,6 +430,8 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev,
 
 	return tx_desc;
 failure:
+	DP_STATS_INC_PKT(pdev, tx.dropped.dropped_pkt, 1,
+			qdf_nbuf_len(nbuf));
 	dp_tx_desc_release(tx_desc, desc_pool_id);
 	return NULL;
 }
@@ -502,6 +508,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
 	void *hal_tx_desc, *hal_tx_desc_cached;
 	qdf_dma_addr_t dma_addr;
 	uint8_t cached_desc[HAL_TX_DESC_LEN_BYTES];
+	struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
 
 	/* Return Buffer Manager ID */
 	uint8_t bm_id = ring_id;
@@ -571,7 +578,9 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
 	if (!hal_tx_desc) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s TCL ring full ring_id:%d\n", __func__, ring_id);
-		DP_STATS_ADD(soc, tx.tcl_ring_full[ring_id], 1);
+		DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
+		DP_STATS_INC_PKT(pdev, tx.dropped.dropped_pkt, 1,
+				length);
 		hal_srng_access_end(soc->hal_soc,
 				soc->tcl_data_ring[ring_id].hal_srng);
 		return QDF_STATUS_E_RESOURCES;
@@ -580,6 +589,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
 	tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX;
 
 	hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc);
+	DP_STATS_INC_PKT(pdev, tx.processed, 1, length);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -656,6 +666,8 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	return NULL;
 
 fail_return:
+	DP_STATS_INC_PKT(pdev, tx.dropped.dropped_pkt, 1,
+			qdf_nbuf_len(nbuf));
 	return nbuf;
 }
 
@@ -727,6 +739,9 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 				  "%s Tx_hw_enqueue Fail tx_desc %p queue %d\n",
 				  __func__, tx_desc, tx_q->ring_id);
 
+			DP_STATS_INC_PKT(pdev,
+					tx.dropped.dropped_pkt, 1,
+					qdf_nbuf_len(tx_desc->nbuf));
 			dp_tx_desc_release(tx_desc, tx_q->desc_pool_id);
 			goto done;
 		}
@@ -946,6 +961,7 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 	 * (TID override disabled)
 	 */
 	msdu_info.tid = HTT_TX_EXT_TID_INVALID;
+	DP_STATS_INC_PKT(vdev->pdev, tx.rcvd, 1, qdf_nbuf_len(nbuf));
 
 	if (qdf_unlikely(vdev->mesh_vdev))
 		dp_tx_extract_mesh_meta_data(vdev, nbuf, &msdu_info);
@@ -991,7 +1007,8 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 		/* dp_tx_prepare_tso(vdev, nbuf, &seg_info, &msdu_info); */
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s TSO frame %p\n", __func__, vdev);
-		DP_STATS_MSDU_INCR(soc, tx.tso.tso_pkts, nbuf);
+		DP_STATS_INC_PKT(vdev->pdev, tx.tso.tso_pkt, 1,
+				qdf_nbuf_len(nbuf));
 
 		goto send_multiple;
 	}
@@ -1001,9 +1018,10 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 		nbuf = dp_tx_prepare_sg(vdev, nbuf, &seg_info, &msdu_info);
 
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
-			  "%s non-TSO SG frame %p\n", __func__, vdev);
+			 "%s non-TSO SG frame %p\n", __func__, vdev);
 
-		DP_STATS_MSDU_INCR(soc, tx.sg.sg_pkts, nbuf);
+		DP_STATS_INC_PKT(vdev->pdev, tx.sg.sg_pkt, 1,
+				qdf_nbuf_len(nbuf));
 
 		goto send_multiple;
 	}
@@ -1016,7 +1034,9 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 				  "%s Mcast frm for ME %p\n", __func__, vdev);
 
-			DP_STATS_MSDU_INCR(soc, tx.mcast.pkts, nbuf);
+			DP_STATS_INC_PKT(vdev->pdev,
+					tx.mcast_en.mcast_pkt, 1,
+					qdf_nbuf_len(nbuf));
 
 			goto send_multiple;
 		}
@@ -1031,7 +1051,9 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s Raw frame %p\n", __func__, vdev);
 
-		DP_STATS_MSDU_INCR(soc, tx.raw.pkts, nbuf);
+		DP_STATS_INC_PKT(vdev->pdev,
+				tx.raw_pkt, 1,
+				qdf_nbuf_len(nbuf));
 
 		goto send_multiple;
 
@@ -1076,7 +1098,8 @@ void dp_tx_reinject_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
 			"%s Tx reinject path\n", __func__);
 
-	DP_STATS_MSDU_INCR(soc, tx.reinject.pkts, tx_desc->nbuf);
+	DP_STATS_INC_PKT(vdev->pdev, tx.reinject_pkts, 1,
+			qdf_nbuf_len(tx_desc->nbuf));
 
 	if (qdf_unlikely(vdev->mesh_vdev)) {
 		DP_TX_FREE_SINGLE_BUF(vdev->pdev->soc, tx_desc->nbuf);
@@ -1110,7 +1133,8 @@ static void dp_tx_inspect_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 
 	soc = pdev->soc;
 
-	DP_STATS_MSDU_INCR(soc, tx.inspect.pkts, tx_desc->nbuf);
+	DP_STATS_INC_PKT(pdev, tx.inspect_pkts, 1,
+			qdf_nbuf_len(tx_desc->nbuf));
 
 	DP_TX_FREE_SINGLE_BUF(soc, tx_desc->nbuf);
 }
@@ -1150,8 +1174,9 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status)
 	case HTT_TX_FW2WBM_TX_STATUS_TTL:
 	{
 		qdf_atomic_dec(&pdev->num_tx_exception);
+		DP_STATS_INC_PKT(pdev, tx.dropped.dropped_pkt,
+				1, qdf_nbuf_len(tx_desc->nbuf));
 		DP_TX_FREE_SINGLE_BUF(soc, tx_desc->nbuf);
-		DP_STATS_MSDU_INCR(soc, tx.dropped.pkts, tx_desc->nbuf);
 		break;
 	}
 	case HTT_TX_FW2WBM_TX_STATUS_REINJECT:
@@ -1266,11 +1291,15 @@ static void dp_tx_comp_process_desc(struct dp_soc *soc,
 {
 	struct dp_tx_desc_s *desc;
 	struct dp_tx_desc_s *next;
+	struct hal_tx_completion_status ts = {0};
+	uint32_t length;
 
 	desc = comp_head;
 
 	while (desc) {
 
+		hal_tx_comp_get_status(&desc->comp, &ts);
+		length = qdf_nbuf_len(desc->nbuf);
 		/* Error Handling */
 		if (hal_tx_comp_get_buffer_source(&desc->comp) ==
 				HAL_TX_COMP_RELEASE_SOURCE_FW) {
@@ -1307,6 +1336,13 @@ static void dp_tx_comp_process_desc(struct dp_soc *soc,
 			DP_TX_FREE_DMA_TO_DEVICE(soc, desc->vdev, desc->nbuf);
 		}
 
+		DP_STATS_INC_PKT(desc->pdev, tx.comp.comp_pkt, 1,
+				length);
+		DP_STATS_INCC(desc->pdev, tx.comp.mcs_count[MAX_MCS], 1,
+				ts.mcs >= MAX_MCS);
+		DP_STATS_INCC(desc->pdev, tx.comp.mcs_count[ts.mcs], 1,
+				ts.mcs <= MAX_MCS);
+
 		next = desc->next;
 		dp_tx_desc_release(desc, desc->pool_id);
 		desc = next;

+ 0 - 3
dp/wifi3.0/dp_tx.h

@@ -22,9 +22,6 @@
 #include <qdf_nbuf.h>
 #include "dp_types.h"
 
-#define DP_STATS_ADD(x, y, z)
-#define DP_STATS_SUB(x, y, z)
-#define DP_STATS_MSDU_INCR(x, y, z)
 
 #define DP_TX_MAX_NUM_FRAGS 6
 

+ 4 - 2
dp/wifi3.0/dp_tx_desc.h

@@ -21,6 +21,7 @@
 
 #include "dp_types.h"
 #include "dp_tx.h"
+#include "dp_internal.h"
 
 /**
  * 21 bits cookie
@@ -74,7 +75,8 @@ static inline struct dp_tx_desc_s *dp_tx_desc_alloc(struct dp_soc *soc,
 			soc->tx_desc[desc_pool_id].freelist->next;
 		soc->tx_desc[desc_pool_id].num_allocated++;
 	}
-	DP_STATS_ADD(pdev, pub.tx.desc_in_use, 1);
+
+	DP_STATS_INC(soc, tx.desc_in_use, 1);
 	tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
 	TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock);
 
@@ -98,7 +100,7 @@ dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
 	tx_desc->flags = 0;
 	tx_desc->next = soc->tx_desc[desc_pool_id].freelist;
 	soc->tx_desc[desc_pool_id].freelist = tx_desc;
-	DP_STATS_SUB(pdev, pub.tx.desc_in_use, 1);
+	DP_STATS_DEC(soc, tx.desc_in_use, 1);
 
 	TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock);
 }

+ 146 - 6
dp/wifi3.0/dp_types.h

@@ -36,6 +36,16 @@
 #include <hal_tx.h>
 #include <hal_reo.h>
 #include "wlan_cfg.h"
+#include "hal_rx.h"
+
+#define MAX_TCL_RING 3
+#define MAX_MCS 12    /* MCS rate varies from 0-11 */
+#define SS_COUNT 8
+#define MAX_RXDMA_ERRORS 32
+#define SUPPORTED_BW 4
+#define SUPPORTED_RECEPTION_TYPES 4
+#define RECEPTION_TYPE_MU_MIMO 1
+#define RECEPTION_TYPE_MU_OFDMA_MIMO 3
 
 struct dp_soc_cmn;
 struct dp_pdev;
@@ -61,11 +71,6 @@ union dp_rx_desc_list_elem_t;
      (_a)[4] == 0xff &&                         \
      (_a)[5] == 0xff)
 
-
-#define DP_TRACE(LVL, fmt, args ...)                             \
-	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_##LVL,       \
-		"%s:%d: "fmt, __func__, __LINE__, ## args)
-
 /**
  * macros to convert hw mac id to sw mac id:
  * mac ids used by hardware start from a value of 1 while
@@ -263,6 +268,116 @@ struct reo_desc_list_node {
 	struct dp_rx_tid rx_tid;
 };
 
+/* TODO: Proper comments have been added in the subsequesnt gerrit */
+/* packet info */
+struct dp_pkt_info {
+	uint32_t num; /*no of packets*/
+	uint32_t bytes; /* total no of bytes */
+};
+
+/* per pdev tx stats*/
+struct dp_tx_pdev_stats {
+
+	struct dp_pkt_info rcvd; /*total packets received for transmission */
+	struct {
+		/* Pkt Info for which completions were received */
+		struct dp_pkt_info comp_pkt;
+		uint32_t mcs_count[MAX_MCS + 1]; /* MCS Count */
+	} comp; /* Tx completions received*/
+
+	struct dp_pkt_info freed; /* Tx packets freed*/
+
+	struct dp_pkt_info processed; /* Tx packets processed*/
+	struct dp_pkt_info outstanding; /* Tx packets remaining for processing*/
+
+	struct {
+		struct dp_pkt_info dropped_pkt; /* Total packets dropped */
+		uint32_t desc_total;  /* total descriptors dropped */
+		uint32_t dma_map_error; /* Dropped due to Dma Error */
+		uint32_t ring_full;    /* dropped due to ring full */
+		uint32_t fw_discard;   /* Discarded bu firmware */
+		uint32_t fw_discard_retired; /* fw_discard_retired */
+		/* firmware_discard_untransmitted */
+		uint32_t firmware_discard_untransmitted;
+		uint32_t mpdu_age_out; /* mpdu_age_out */
+		uint32_t firmware_discard_reason1; /*firmware_discard_reason1*/
+		uint32_t firmware_discard_reason2; /*firmware_discard_reason2*/
+		uint32_t firmware_discard_reason3; /*firmware_discard_reason3*/
+	} dropped; /* Packets dropped on the Tx side */
+
+	struct {
+		struct dp_pkt_info sg_pkt; /* total scatter gather packets */
+		uint32_t dropped_host; /* SG packets dropped by host */
+		uint32_t dropped_target; /* SG packets dropped by target */
+	} sg; /* Scatter Gather packet info */
+
+	struct {
+		uint32_t num_seg;  /* No of segments in TSO packets */
+		struct dp_pkt_info tso_pkt; /* total no of TSO packets */
+		uint32_t dropped_host; /* TSO packets dropped by host */
+		uint32_t dropped_target; /* TSO packets dropped by target */
+	} tso; /* TSO packets info */
+
+	struct {
+		/* total no of multicast conversion packets */
+		struct dp_pkt_info mcast_pkt;
+		/* packets dropped due to map error */
+		uint32_t dropped_map_error;
+		/* packets dropped due to self Mac address */
+		uint32_t dropped_self_mac;
+		/* Packets dropped due to send fail */
+		uint32_t dropped_send_fail;
+		/* total unicast packets transmitted */
+		uint32_t ucast;
+	} mcast_en; /* Multicast Enhancement packets info */
+
+	/* Total packets passed Reinject handler */
+	struct dp_pkt_info reinject_pkts;
+	/*  Total packets passed to inspect handler */
+	struct dp_pkt_info inspect_pkts;
+	/* Total Raw packets */
+	struct dp_pkt_info raw_pkt;
+};
+
+/* Per pdev RX stats */
+struct dp_rx_pdev_stats {
+	struct dp_pkt_info rcvd_reo; /* packets received on the reo ring */
+	struct {
+		/* packets dropped because of no peer */
+		struct dp_pkt_info no_peer;
+		/* packets dropped because nsdu_done bit not set */
+		struct dp_pkt_info msdu_not_done;
+	} dropped; /* packets dropped on rx */
+	struct dp_pkt_info replenished; /* total packets replnished */
+	struct dp_pkt_info to_stack;    /* total packets sent up the stack */
+	struct dp_pkt_info intra_bss;   /* Intra BSS packets received */
+	struct dp_pkt_info wds;         /* WDS packets received */
+	struct dp_pkt_info desc;
+	struct dp_pkt_info buff;
+	struct dp_pkt_info raw;         /* Raw Pakets received */
+	struct {
+		uint32_t rxdma_unitialized; /* rxdma_unitialized errors */
+		uint32_t desc_alloc_fail; /* desc alloc failed errors */
+	} err;                          /* Rx errors */
+	uint32_t buf_freelist;         /* buffers added back in freelist */
+	uint32_t mcs_count[MAX_MCS + 1]; /* packets in different MCS rates */
+	uint32_t sgi_count[MAX_MCS + 1]; /* SGI count */
+	/*  Number of MSDUs with no MPDU level aggregation */
+	uint32_t non_ampdu_cnt;
+	/* Number of MSDUs part of AMSPU */
+	uint32_t ampdu_cnt;
+	/* Number of MSDUs with no MSDU level aggregation */
+	uint32_t non_amsdu_cnt;
+	/* Number of MSDUs part of AMSDU*/
+	uint32_t amsdu_cnt;
+	/* Packet count in spatiel Streams */
+	uint32_t nss[SS_COUNT];
+	/* Packet count in different Bandwidths */
+	uint32_t bw[SUPPORTED_BW];
+	/* reception type os packets */
+	uint32_t reception_type[SUPPORTED_RECEPTION_TYPES];
+};
+
 /* SOC level structure for data path */
 struct dp_soc {
 	/* Common base structure - Should be the first member */
@@ -442,8 +557,31 @@ struct dp_soc {
 
 	/* SoC level data path statistics */
 	struct {
+		struct {
+			/* descriptors in each tcl ring */
+			uint32_t tcl_ring_full[MAX_TCL_RING];
+			/* Descriptors in use at soc */
+			uint32_t desc_in_use;
+		} tx;  /* SOC level TX stats */
+		struct {
+			struct {
+				/* Invalid RBM error count */
+				uint32_t invalid_rbm;
+				/* Invalid VDEV Error count */
+				uint32_t invalid_vdev;
+				/* Invalid PDEV error count */
+				uint32_t invalid_pdev;
+				/* HAL ring access Fail error count */
+				uint32_t hal_ring_access_fail;
+				/* RX DMA error count */
+				uint32_t rxdma_error[MAX_RXDMA_ERRORS];
+				/* REO Error count */
+				uint32_t reo_error[
+					HAL_REO_ERR_QUEUE_DESC_BLOCKED_SET+1];
+			} err; /* Rx eerors */
+		} rx;  /* SOC level RX stats */
 		/* TBD */
-	} stats;
+	} stats; /* TxRx SOC level stats */
 
 	/* Enable processing of Tx completion status words */
 	bool process_tx_status;
@@ -520,6 +658,8 @@ struct dp_pdev {
 
 	/* PDEV level data path statistics */
 	struct {
+		struct dp_tx_pdev_stats tx; /* per pdev tx stats */
+		struct dp_rx_pdev_stats rx; /* per pdev rx stats */
 		/* TBD */
 	} stats;
 

+ 52 - 0
dp/wifi3.0/hal_rx.h

@@ -687,6 +687,58 @@ hal_rx_msdu_start_msdu_len_get(uint8_t *buf)
 	return msdu_len;
 }
 
+#define HAL_RX_MSDU_START_BW_GET(_rx_msdu_start)     \
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\
+	RX_MSDU_START_5_RECEIVE_BANDWIDTH_OFFSET)), \
+	RX_MSDU_START_5_RECEIVE_BANDWIDTH_MASK,     \
+	RX_MSDU_START_5_RECEIVE_BANDWIDTH_LSB))
+
+/*
+ * hal_rx_msdu_start_bw_get(): API to get the Bandwidth
+ * Interval from rx_msdu_start
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(bw)
+ */
+static inline uint32_t
+hal_rx_msdu_start_bw_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_start *msdu_start =
+		&pkt_tlvs->msdu_start_tlv.rx_msdu_start;
+	uint32_t bw;
+
+	bw = HAL_RX_MSDU_START_BW_GET(msdu_start);
+
+	return bw;
+}
+
+#define HAL_RX_MSDU_START_RECEPTION_TYPE_GET(_rx_msdu_start) \
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),	\
+	RX_MSDU_START_5_RECEPTION_TYPE_OFFSET)),	\
+	RX_MSDU_START_5_RECEPTION_TYPE_MASK,		\
+	RX_MSDU_START_5_RECEPTION_TYPE_LSB))
+
+/*
+ * hal_rx_msdu_start_reception_type_get(): API to get the reception type
+ * Interval from rx_msdu_start
+ *
+ * @buf: pointer to the start of RX PKT TLV header
+ * Return: uint32_t(reception_type)
+ */
+static inline uint32_t
+hal_rx_msdu_start_reception_type_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_start *msdu_start =
+		&pkt_tlvs->msdu_start_tlv.rx_msdu_start;
+	uint32_t reception_type;
+
+	reception_type = HAL_RX_MSDU_START_RECEPTION_TYPE_GET(msdu_start);
+
+	return reception_type;
+}
+
 /*
  * Get qos_control_valid from RX_MPDU_START
  */