qcacmn: Add support to process Tx completion status from WBM descriptor

Add HAL API to parse Tx completion statistics from WBM descriptor and
populate HAL Structure and a DP API to print the statistics per packet

CRs-Fixed: 1088985
Change-Id: Ic6e918aabdbd7743d8f640e0451070dc229c6f0d
diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c
index 51a1372..54b0e28 100644
--- a/dp/wifi3.0/dp_tx.c
+++ b/dp/wifi3.0/dp_tx.c
@@ -310,9 +310,9 @@
 	tx_desc->vdev = vdev;
 	tx_desc->msdu_ext_desc = NULL;
 
-	if (qdf_nbuf_map_nbytes_single(soc->osdev, nbuf,
-				QDF_DMA_TO_DEVICE, qdf_nbuf_len(nbuf)
-				!= QDF_STATUS_SUCCESS)) {
+	if (qdf_unlikely(QDF_STATUS_SUCCESS !=
+				qdf_nbuf_map_nbytes_single(soc->osdev, nbuf,
+				QDF_DMA_TO_DEVICE, qdf_nbuf_len(nbuf)))) {
 		/* Handle failure */
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				"qdf_nbuf_map_nbytes_single failed\n");
@@ -716,7 +716,7 @@
 				msdu_info->u.tso_info.curr_seg =
 					msdu_info->u.tso_info.curr_seg->next;
 				/* Check with MCL if this is needed */
-				/* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; */
+			/* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; */
 			}
 		}
 
@@ -829,9 +829,9 @@
 	struct dp_vdev *vdev = (struct dp_vdev *) vap_dev;
 
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
-			"Entering %s , skb %0x:%0x:%0x:%0x:%0x:%0x\n",
+			"%s , skb %0x:%0x:%0x:%0x:%0x:%0x\n",
 			__func__, nbuf->data[0], nbuf->data[1], nbuf->data[2],
-			nbuf->data[1], nbuf->data[2], nbuf->data[3]);
+			nbuf->data[3], nbuf->data[4], nbuf->data[5]);
 
 	/*
 	 * Get HW Queue to use for this frame.
@@ -1050,6 +1050,48 @@
 }
 
 /**
+ * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info
+ * @tx_desc: software descriptor head pointer
+ *
+ *
+ * Return: none
+ */
+static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc)
+{
+	struct hal_tx_completion_status ts;
+	qdf_mem_zero(&ts, sizeof(struct hal_tx_completion_status));
+	hal_tx_comp_get_status(&tx_desc->comp, &ts);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+				"--------------------\n"
+				"Tx Completion Stats:\n"
+				"--------------------\n"
+				"ack_frame_rssi = %d\n"
+				"first_msdu = %d\n"
+				"last_msdu = %d\n"
+				"msdu_part_of_amsdu = %d\n"
+				"bw = %d\n"
+				"pkt_type = %d\n"
+				"stbc = %d\n"
+				"ldpc = %d\n"
+				"sgi = %d\n"
+				"mcs = %d\n"
+				"ofdma = %d\n"
+				"tones_in_ru = %d\n"
+				"tsf = %d\n"
+				"ppdu_id = %d\n"
+				"transmit_cnt = %d\n"
+				"tid = %d\n"
+				"peer_id = %d\n",
+				ts.ack_frame_rssi, ts.first_msdu, ts.last_msdu,
+				ts.msdu_part_of_amsdu,	ts.bw,	ts.pkt_type,
+				ts.stbc, ts.ldpc, ts.sgi,
+				ts.mcs, ts.ofdma, ts.tones_in_ru,
+				ts.tsf, ts.ppdu_id, ts.transmit_cnt, ts.tid,
+				ts.peer_id);
+
+}
+
+/**
  * dp_tx_comp_process_desc() - Tx complete software descriptor handler
  * @soc: core txrx main context
  * @comp_head: software descriptor head pointer
@@ -1455,6 +1497,12 @@
 		}
 	}
 
+	/*
+	 * Keep the processing of completion stats disabled by default.
+	 * todo - Add a runtime config option to enable this.
+	 */
+	soc->process_tx_status = 0;
+
 	/* Initialize Default DSCP-TID mapping table in TCL */
 	hal_tx_set_dscp_tid_map(soc->hal_soc, default_dscp_tid_map,
 			HAL_TX_DSCP_TID_MAP_TABLE_DEFAULT);
diff --git a/dp/wifi3.0/dp_tx.h b/dp/wifi3.0/dp_tx.h
index 50dd767..ad6b8ad 100644
--- a/dp/wifi3.0/dp_tx.h
+++ b/dp/wifi3.0/dp_tx.h
@@ -178,10 +178,6 @@
 {
 	return;
 }
-static inline void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc)
-{
-	return;
-}
 static inline QDF_STATUS dp_tx_flow_control(struct dp_vdev *vdev)
 {
 	return  QDF_STATUS_SUCCESS;
diff --git a/hal/wifi3.0/hal_tx.h b/hal/wifi3.0/hal_tx.h
index 2ba908d..23d2a59 100644
--- a/hal/wifi3.0/hal_tx.h
+++ b/hal/wifi3.0/hal_tx.h
@@ -23,6 +23,9 @@
   Include files
   ---------------------------------------------------------------------------*/
 #include "hal_api.h"
+#ifdef CONFIG_WIN
+#include "wcss_version.h"
+#endif
 
 /*---------------------------------------------------------------------------
   Preprocessor definitions and constants
@@ -48,6 +51,19 @@
 	((value << (block ## _ ## field ## _LSB)) & \
 	 (block ## _ ## field ## _MASK))
 
+#define HAL_TX_MS(block, field, value) \
+	(((value) & (block ## _ ## field ## _MASK)) >> \
+	 (block ## _ ## field ## _LSB))
+
+#define HAL_TX_DESC_GET(desc, block, field) \
+	HAL_TX_MS(block, field, HAL_SET_FLD(desc, block, field))
+
+#define HAL_TX_DESC_SUBBLOCK_GET(desc, block, sub, field) \
+	HAL_TX_MS(sub, field, HAL_SET_FLD(desc, block, sub))
+
+#define HAL_TX_BUF_TYPE_BUFFER 0
+#define HAL_TX_BUF_TYPE_EXT_DESC 1
+
 #define HAL_TX_DESC_LEN_DWORDS (NUM_OF_DWORDS_TCL_DATA_CMD)
 #define HAL_TX_DESC_LEN_BYTES  (NUM_OF_DWORDS_TCL_DATA_CMD * 4)
 #define HAL_TX_EXTENSION_DESC_LEN_DWORDS (NUM_OF_DWORDS_TX_MSDU_EXTENSION)
@@ -801,6 +817,79 @@
 }
 
 /**
+ * hal_tx_comp_get_status() - TQM Release reason
+ * @hal_desc: completion ring Tx status
+ *
+ * This function will parse the WBM completion descriptor and populate in
+ * HAL structure
+ *
+ * Return: none
+ */
+#if defined(WCSS_VERSION) && (WCSS_VERSION > 81)
+static inline void hal_tx_comp_get_status(void *desc,
+		struct hal_tx_completion_status *ts)
+{
+
+	uint8_t rate_stats_valid = 0;
+	uint32_t rate_stats = 0;
+
+	ts->ppdu_id = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_3,
+			TQM_STATUS_NUMBER);
+	ts->ack_frame_rssi = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4,
+			ACK_FRAME_RSSI);
+	ts->first_msdu = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4, FIRST_MSDU);
+	ts->last_msdu = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4, LAST_MSDU);
+	ts->msdu_part_of_amsdu = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4,
+			MSDU_PART_OF_AMSDU);
+
+	ts->peer_id = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_7, SW_PEER_ID);
+	ts->tid = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_7, TID);
+
+	rate_stats = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_6,
+			TX_RATE_STATS_INFO_TX_RATE_STATS);
+
+	rate_stats_valid = HAL_TX_MS(TX_RATE_STATS_INFO_0,
+			TX_RATE_STATS_INFO_VALID, rate_stats);
+
+	if (rate_stats_valid) {
+		ts->bw = HAL_TX_MS(TX_RATE_STATS_INFO_0, TRANSMIT_BW,
+				rate_stats);
+		ts->pkt_type = HAL_TX_MS(TX_RATE_STATS_INFO_0,
+				TRANSMIT_PKT_TYPE, rate_stats);
+		ts->stbc = HAL_TX_MS(TX_RATE_STATS_INFO_0,
+				TRANSMIT_STBC, rate_stats);
+		ts->ldpc = HAL_TX_MS(TX_RATE_STATS_INFO_0, TRANSMIT_LDPC,
+				rate_stats);
+		ts->sgi = HAL_TX_MS(TX_RATE_STATS_INFO_0, TRANSMIT_SGI,
+				rate_stats);
+		ts->mcs = HAL_TX_MS(TX_RATE_STATS_INFO_0, TRANSMIT_MCS,
+				rate_stats);
+		ts->ofdma = HAL_TX_MS(TX_RATE_STATS_INFO_0, OFDMA_TRANSMISSION,
+				rate_stats);
+		ts->tones_in_ru = HAL_TX_MS(TX_RATE_STATS_INFO_0, TONES_IN_RU,
+				rate_stats);
+	}
+
+	ts->tsf = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_6,
+			TX_RATE_STATS_INFO_TX_RATE_STATS);
+}
+#else
+static inline void hal_tx_comp_get_status(void *desc,
+		struct hal_tx_completion_status *ts)
+{
+
+	ts->ppdu_id = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_3,
+			TQM_STATUS_NUMBER);
+	ts->ack_frame_rssi = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4,
+			ACK_FRAME_RSSI);
+	ts->first_msdu = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4, FIRST_MSDU);
+	ts->last_msdu = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4, LAST_MSDU);
+	ts->msdu_part_of_amsdu = HAL_TX_DESC_GET(desc, WBM_RELEASE_RING_4,
+			MSDU_PART_OF_AMSDU);
+}
+#endif
+
+/**
  * hal_tx_comp_desc_sync() - collect hardware descriptor contents
  * @hal_desc: hardware descriptor pointer
  * @comp: software descriptor pointer