瀏覽代碼

qcacmn: tx monitor populate stats information

add tx monitor stats information.

Change-Id: Iffc55c2a4fa5351140daeffac3a50dd6867f6ea1
CRs-Fixed: 3230286
nobelj 3 年之前
父節點
當前提交
7d3197b9a5

+ 8 - 3
dp/wifi3.0/monitor/2.0/dp_mon_2.0.c

@@ -223,7 +223,8 @@ dp_mon_buffers_replenish(struct dp_soc *dp_soc,
 			 struct dp_mon_desc_pool *mon_desc_pool,
 			 uint32_t num_req_buffers,
 			 union dp_mon_desc_list_elem_t **desc_list,
-			 union dp_mon_desc_list_elem_t **tail)
+			 union dp_mon_desc_list_elem_t **tail,
+			 uint32_t *replenish_cnt_ref)
 {
 	uint32_t num_alloc_desc;
 	uint16_t num_desc_to_free = 0;
@@ -321,6 +322,8 @@ dp_mon_buffers_replenish(struct dp_soc *dp_soc,
 	}
 
 	hal_srng_access_end(dp_soc->hal_soc, mon_srng);
+	if (replenish_cnt_ref)
+		*replenish_cnt_ref += count;
 
 free_desc:
 	/*
@@ -812,7 +815,8 @@ QDF_STATUS dp_tx_mon_refill_buf_ring_2_0(struct dp_intr *int_ctx)
 	if (num_entries_avail)
 		dp_mon_buffers_replenish(soc, tx_mon_buf_ring,
 					 &mon_soc_be->tx_desc_mon,
-					 num_entries_avail, &desc_list, &tail);
+					 num_entries_avail, &desc_list, &tail,
+					 NULL);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -844,7 +848,8 @@ QDF_STATUS dp_rx_mon_refill_buf_ring_2_0(struct dp_intr *int_ctx)
 	if (num_entries_avail)
 		dp_mon_buffers_replenish(soc, rx_mon_buf_ring,
 					 &mon_soc_be->rx_desc_mon,
-					 num_entries_avail, &desc_list, &tail);
+					 num_entries_avail, &desc_list, &tail,
+					 NULL);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 3 - 1
dp/wifi3.0/monitor/2.0/dp_mon_2.0.h

@@ -264,6 +264,7 @@ void dp_mon_pool_frag_unmap_and_free(struct dp_soc *dp_soc,
  *	       or NULL during dp rx initialization or out of buffer
  *	       interrupt.
  * @tail: tail of descs list
+ * @relenish_cnt_ref: pointer to update replenish_cnt
  *
  * Return: return success or failure
  */
@@ -272,7 +273,8 @@ QDF_STATUS dp_mon_buffers_replenish(struct dp_soc *dp_soc,
 				struct dp_mon_desc_pool *mon_desc_pool,
 				uint32_t num_req_buffers,
 				union dp_mon_desc_list_elem_t **desc_list,
-				union dp_mon_desc_list_elem_t **tail);
+				union dp_mon_desc_list_elem_t **tail,
+				uint32_t *replenish_cnt_ref);
 
 /**
  * dp_mon_filter_show_tx_filter_be() - Show the set filters

+ 4 - 4
dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c

@@ -845,7 +845,7 @@ dp_rx_mon_flush_status_buf_queue(struct dp_pdev *pdev)
 		dp_mon_buffers_replenish(soc, &soc->rxdma_mon_buf_ring[0],
 					 rx_mon_desc_pool,
 					 work_done,
-					 &desc_list, &tail);
+					 &desc_list, &tail, NULL);
 	}
 }
 
@@ -878,7 +878,7 @@ dp_rx_mon_handle_flush_n_trucated_ppdu(struct dp_soc *soc,
 	dp_mon_buffers_replenish(soc, &soc->rxdma_mon_buf_ring[0],
 				 rx_mon_desc_pool,
 				 work_done,
-				 &desc_list, &tail);
+				 &desc_list, &tail, NULL);
 }
 
 uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
@@ -1296,7 +1296,7 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev)
 		dp_mon_buffers_replenish(soc, &soc->rxdma_mon_buf_ring[0],
 					 rx_mon_desc_pool,
 					 work_done,
-					 &desc_list, &tail);
+					 &desc_list, &tail, NULL);
 	}
 
 	ppdu_info->rx_status.tsft = ppdu_info->rx_status.tsft +
@@ -1589,7 +1589,7 @@ dp_rx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size)
 	return dp_mon_buffers_replenish(soc, mon_buf_ring,
 					rx_mon_desc_pool,
 					size,
-					&desc_list, &tail);
+					&desc_list, &tail, NULL);
 }
 
 #ifdef QCA_ENHANCED_STATS_SUPPORT

+ 163 - 7
dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c

@@ -33,6 +33,67 @@
 #include "dp_ratetable.h"
 #endif
 
+#define MAX_TX_MONITOR_STUCK 50
+
+#ifdef TXMON_DEBUG
+/*
+ * dp_tx_mon_debug_statu() - API to display tx monitor status
+ * @tx_mon_be - pointer to dp_pdev_tx_monitor_be
+ * @work_done - tx monitor work done
+ *
+ * Return: void
+ */
+static inline void
+dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be *tx_mon_be,
+		       uint32_t work_done)
+{
+	if (tx_mon_be->mode && !work_done)
+		tx_mon_be->stats.tx_mon_stuck++;
+	else if (tx_mon_be->mode && work_done)
+		tx_mon_be->stats.tx_mon_stuck = 0;
+
+	if (tx_mon_be->stats.tx_mon_stuck > MAX_TX_MONITOR_STUCK) {
+		dp_mon_warn("Tx monitor block got stuck!!!!!");
+		tx_mon_be->stats.tx_mon_stuck = 0;
+		tx_mon_be->stats.total_tx_mon_stuck++;
+	}
+
+	dp_mon_debug_rl("tx_ppdu_info[%u :D %u] STATUS[R %llu: F %llu] PKT_BUF[R %llu: F %llu : P %llu : S %llu]",
+			tx_mon_be->tx_ppdu_info_list_depth,
+			tx_mon_be->defer_ppdu_info_list_depth,
+			tx_mon_be->stats.status_buf_recv,
+			tx_mon_be->stats.status_buf_free,
+			tx_mon_be->stats.pkt_buf_recv,
+			tx_mon_be->stats.pkt_buf_free,
+			tx_mon_be->stats.pkt_buf_processed,
+			tx_mon_be->stats.pkt_buf_to_stack);
+}
+
+#else
+/*
+ * dp_tx_mon_debug_statu() - API to display tx monitor status
+ * @tx_mon_be - pointer to dp_pdev_tx_monitor_be
+ * @work_done - tx monitor work done
+ *
+ * Return: void
+ */
+static inline void
+dp_tx_mon_debug_status(struct dp_pdev_tx_monitor_be *tx_mon_be,
+		       uint32_t work_done)
+{
+	if (tx_mon_be->mode && !work_done)
+		tx_mon_be->stats.tx_mon_stuck++;
+	else if (tx_mon_be->mode && work_done)
+		tx_mon_be->stats.tx_mon_stuck = 0;
+
+	if (tx_mon_be->stats.tx_mon_stuck > MAX_TX_MONITOR_STUCK) {
+		dp_mon_warn("Tx monitor block got stuck!!!!!");
+		tx_mon_be->stats.tx_mon_stuck = 0;
+		tx_mon_be->stats.total_tx_mon_stuck++;
+	}
+}
+#endif
+
 static inline uint32_t
 dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 			   uint32_t mac_id, uint32_t quota)
@@ -49,6 +110,7 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 	struct dp_pdev_tx_monitor_be *tx_mon_be = NULL;
 	struct dp_mon_desc_pool *tx_mon_desc_pool = &mon_soc_be->tx_desc_mon;
 	struct dp_tx_mon_desc_list mon_desc_list;
+	uint32_t replenish_cnt = 0;
 
 	if (!pdev) {
 		dp_mon_err("%pK: pdev is null for mac_id = %d", soc, mac_id);
@@ -110,6 +172,12 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 				    hal_mon_tx_desc.tlv_drop_count,
 				    hal_mon_tx_desc.end_of_ppdu_dropped);
 
+			tx_mon_be->stats.ppdu_drop_cnt +=
+				hal_mon_tx_desc.ppdu_drop_count;
+			tx_mon_be->stats.mpdu_drop_cnt +=
+				hal_mon_tx_desc.mpdu_drop_count;
+			tx_mon_be->stats.tlv_drop_cnt +=
+				hal_mon_tx_desc.tlv_drop_count;
 			work_done++;
 			hal_srng_dst_get_next(hal_soc, mon_dst_srng);
 			continue;
@@ -168,9 +236,12 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 			continue;
 		}
 
+		tx_mon_be->stats.status_buf_recv++;
+
 		if ((hal_mon_tx_desc.end_reason == HAL_MON_FLUSH_DETECTED) ||
 		    (hal_mon_tx_desc.end_reason == HAL_MON_PPDU_TRUNCATED)) {
 			tx_mon_be->be_ppdu_id = hal_mon_tx_desc.ppdu_id;
+
 			dp_tx_mon_update_end_reason(mon_pdev,
 						    hal_mon_tx_desc.ppdu_id,
 						    hal_mon_tx_desc.end_reason);
@@ -178,6 +249,8 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 			dp_tx_mon_status_free_packet_buf(pdev, status_frag,
 							 end_offset,
 							 &mon_desc_list);
+
+			tx_mon_be->stats.status_buf_free++;
 			qdf_frag_free(status_frag);
 
 			work_done++;
@@ -201,12 +274,17 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 					 tx_mon_desc_pool,
 					 mon_desc_list.tx_mon_reap_cnt,
 					 &mon_desc_list.desc_list,
-					 &mon_desc_list.tail);
+					 &mon_desc_list.tail,
+					 &replenish_cnt);
 	}
 	qdf_spin_unlock_bh(&mon_pdev->mon_lock);
 	dp_mon_debug("mac_id: %d, work_done:%d tx_monitor_reap_cnt:%d",
 		     mac_id, work_done, mon_desc_list.tx_mon_reap_cnt);
 
+	tx_mon_be->stats.total_tx_mon_reap_cnt += mon_desc_list.tx_mon_reap_cnt;
+	tx_mon_be->stats.totat_tx_mon_replenish_cnt += replenish_cnt;
+	dp_tx_mon_debug_status(tx_mon_be, work_done);
+
 	return work_done;
 }
 
@@ -309,11 +387,30 @@ dp_tx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size)
 	return dp_mon_buffers_replenish(soc, mon_buf_ring,
 					tx_mon_desc_pool,
 					size,
-					&desc_list, &tail);
+					&desc_list, &tail, NULL);
 }
 
 #ifdef WLAN_TX_PKT_CAPTURE_ENH_BE
 
+/*
+ * dp_tx_mon_nbuf_get_num_frag() - get total number of fragments
+ * @buf: Network buf instance
+ *
+ * Return: number of fragments
+ */
+static inline
+uint32_t dp_tx_mon_nbuf_get_num_frag(qdf_nbuf_t nbuf)
+{
+	uint32_t num_frag = 0;
+
+	if (qdf_unlikely(!nbuf))
+		return num_frag;
+
+	num_frag = qdf_nbuf_get_nr_frags_in_fraglist(nbuf);
+
+	return num_frag;
+}
+
 /*
  * dp_tx_mon_free_usr_mpduq() - API to free user mpduq
  * @tx_ppdu_info - pointer to tx_ppdu_info
@@ -327,12 +424,19 @@ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
 			      struct dp_pdev_tx_monitor_be *tx_mon_be)
 {
 	qdf_nbuf_queue_t *mpdu_q;
+	uint32_t num_frag = 0;
+	qdf_nbuf_t buf = NULL;
 
 	if (qdf_unlikely(!tx_ppdu_info))
 		return;
 
 	mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q);
-	qdf_nbuf_queue_free(mpdu_q);
+
+	while ((buf = qdf_nbuf_queue_remove(mpdu_q)) != NULL) {
+		num_frag += dp_tx_mon_nbuf_get_num_frag(buf);
+		qdf_nbuf_free(buf);
+	}
+	tx_mon_be->stats.pkt_buf_free += num_frag;
 }
 
 /*
@@ -349,9 +453,16 @@ void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info,
 
 	for (; user < TXMON_PPDU_HAL(tx_ppdu_info, num_users); user++) {
 		qdf_nbuf_queue_t *mpdu_q;
+		uint32_t num_frag = 0;
+		qdf_nbuf_t buf = NULL;
 
 		mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, user, mpdu_q);
-		qdf_nbuf_queue_free(mpdu_q);
+
+		while ((buf = qdf_nbuf_queue_remove(mpdu_q)) != NULL) {
+			num_frag += dp_tx_mon_nbuf_get_num_frag(buf);
+			qdf_nbuf_free(buf);
+		}
+		tx_mon_be->stats.pkt_buf_free += num_frag;
 	}
 
 	TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 0;
@@ -424,7 +535,39 @@ struct dp_tx_ppdu_info *dp_tx_mon_get_ppdu_info(struct dp_pdev *pdev,
  */
 void dp_print_pdev_tx_monitor_stats_2_0(struct dp_pdev *pdev)
 {
+	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
+	struct dp_mon_pdev_be *mon_pdev_be =
+			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
+	struct dp_pdev_tx_monitor_be *tx_mon_be =
+			&mon_pdev_be->tx_monitor_be;
+	struct dp_tx_monitor_drop_stats stats = {0};
+
+	qdf_mem_copy(&stats, &tx_mon_be->stats,
+		     sizeof(struct dp_tx_monitor_drop_stats));
+
 	/* TX monitor stats needed for beryllium */
+	DP_PRINT_STATS("\n\tTX Capture BE stats mode[%d]:", tx_mon_be->mode);
+	DP_PRINT_STATS("\tbuffer pending : %u", tx_mon_be->last_frag_q_idx);
+	DP_PRINT_STATS("\treplenish count: %llu",
+		       stats.totat_tx_mon_replenish_cnt);
+	DP_PRINT_STATS("\treap count     : %llu", stats.total_tx_mon_reap_cnt);
+	DP_PRINT_STATS("\tmonitor stuck  : %u", stats.total_tx_mon_stuck);
+	DP_PRINT_STATS("\tStatus buffer");
+	DP_PRINT_STATS("\t\treceived  : %llu", stats.status_buf_recv);
+	DP_PRINT_STATS("\t\tfree      : %llu", stats.status_buf_free);
+	DP_PRINT_STATS("\tPacket buffer");
+	DP_PRINT_STATS("\t\treceived  : %llu", stats.pkt_buf_recv);
+	DP_PRINT_STATS("\t\tfree      : %llu", stats.pkt_buf_free);
+	DP_PRINT_STATS("\t\tprocessed : %llu", stats.pkt_buf_processed);
+	DP_PRINT_STATS("\t\tto stack  : %llu", stats.pkt_buf_to_stack);
+	DP_PRINT_STATS("\tppdu info");
+	DP_PRINT_STATS("\t\tthreshold : %llu", stats.ppdu_info_drop_th);
+	DP_PRINT_STATS("\t\tflush     : %llu", stats.ppdu_info_drop_flush);
+	DP_PRINT_STATS("\t\ttruncated : %llu", stats.ppdu_info_drop_trunc);
+	DP_PRINT_STATS("\tDrop stats");
+	DP_PRINT_STATS("\t\tppdu drop : %llu", stats.ppdu_drop_cnt);
+	DP_PRINT_STATS("\t\tmpdu drop : %llu", stats.mpdu_drop_cnt);
+	DP_PRINT_STATS("\t\ttlv drop : %llu", stats.tlv_drop_cnt);
 }
 
 /*
@@ -455,6 +598,8 @@ dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
 	case TX_MON_BE_FULL_CAPTURE:
 	{
 		/* TODO: send HTT msg to configure TLV based on mode */
+		qdf_mem_zero(&tx_mon_be->stats,
+			     sizeof(struct dp_tx_monitor_drop_stats));
 		tx_mon_be->mode = TX_MON_BE_FULL_CAPTURE;
 		mon_pdev_be->tx_mon_mode = 1;
 		mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH;
@@ -464,7 +609,7 @@ dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
 	{
 		/* TODO: send HTT msg to configure TLV based on mode */
 		tx_mon_be->mode = TX_MON_BE_PEER_FILTER;
-		mon_pdev_be->tx_mon_mode = 1;
+		mon_pdev_be->tx_mon_mode = 2;
 		mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_256B;
 		break;
 	}
@@ -526,17 +671,23 @@ static void dp_fill_lite_mon_vdev(struct cdp_tx_indication_info *tx_cap_info,
  * dp_tx_mon_send_to_stack() - API to send to stack
  * @pdev: pdev Handle
  * @mpdu: pointer to mpdu
+ * @num_frag: number of frag in mpdu
  *
  * Return: void
  */
 static void
-dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu)
+dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu,
+			uint32_t num_frag)
 {
 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
 	struct dp_mon_pdev_be *mon_pdev_be =
 			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
+	struct dp_pdev_tx_monitor_be *tx_mon_be =
+			&mon_pdev_be->tx_monitor_be;
 	struct cdp_tx_indication_info tx_capture_info = {0};
 
+	tx_mon_be->stats.pkt_buf_to_stack += num_frag;
+
 	tx_capture_info.radiotap_done = 1;
 	tx_capture_info.mpdu_nbuf = mpdu;
 	if (!dp_lite_mon_is_tx_enabled(mon_pdev)) {
@@ -578,13 +729,15 @@ dp_tx_mon_send_per_usr_mpdu(struct dp_pdev *pdev,
 	usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_idx, mpdu_q);
 
 	while ((buf = qdf_nbuf_queue_remove(usr_mpdu_q)) != NULL) {
+		uint32_t num_frag = dp_tx_mon_nbuf_get_num_frag(buf);
+
 		ppdu_info->hal_txmon.rx_status.rx_user_status =
 				&ppdu_info->hal_txmon.rx_user_status[user_idx];
 
 		qdf_nbuf_update_radiotap(&ppdu_info->hal_txmon.rx_status,
 					 buf, qdf_nbuf_headroom(buf));
 
-		dp_tx_mon_send_to_stack(pdev, buf);
+		dp_tx_mon_send_to_stack(pdev, buf, num_frag);
 	}
 }
 
@@ -846,6 +999,9 @@ dp_config_enh_tx_core_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
 	case TX_MON_BE_FRM_WRK_FULL_CAPTURE:
 	{
 		tx_mon_be->mode = val;
+		qdf_mem_zero(&tx_mon_be->stats,
+			     sizeof(struct dp_tx_monitor_drop_stats));
+		tx_mon_be->mode = val;
 		mon_pdev_be->tx_mon_mode = 1;
 		mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH;
 		break;

+ 37 - 6
dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h

@@ -358,11 +358,41 @@ struct dp_tx_ppdu_info {
  * @ppdu_drop_cnt: ppdu drop counter
  * @mpdu_drop_cnt: mpdu drop counter
  * @tlv_drop_cnt: tlv drop counter
+ * @pkt_buf_recv: tx monitor packet buffer received
+ * @pkt_buf_free: tx monitor packet buffer free
+ * @pkt_buf_processed: tx monitor packet buffer processed
+ * @pkt_buf_to_stack: tx monitor packet buffer send to stack
+ * @status_buf_recv: tx monitor status buffer received
+ * @status_buf_free: tx monitor status buffer free
+ * @totat_tx_mon_replenish_cnt: tx monitor replenish count
+ * @total_tx_mon_reap_cnt: tx monitor reap count
+ * @tx_mon_stuck: tx monitor stuck count
+ * @total_tx_mon_stuck: tx monitor stuck count
+ * @ppdu_info_drop_th: count ppdu info been dropped due threshold reached
+ * @ppdu_info_drop_flush: count ppdu info been dropped due to flush detected
+ * @ppdu_info_drop_trunc: count ppdu info been dropped due to truncated
  */
 struct dp_tx_monitor_drop_stats {
 	uint64_t ppdu_drop_cnt;
 	uint64_t mpdu_drop_cnt;
 	uint64_t tlv_drop_cnt;
+
+	uint64_t pkt_buf_recv;
+	uint64_t pkt_buf_free;
+	uint64_t pkt_buf_processed;
+	uint64_t pkt_buf_to_stack;
+
+	uint64_t status_buf_recv;
+	uint64_t status_buf_free;
+
+	uint64_t totat_tx_mon_replenish_cnt;
+	uint64_t total_tx_mon_reap_cnt;
+	uint8_t tx_mon_stuck;
+	uint32_t total_tx_mon_stuck;
+
+	uint64_t ppdu_info_drop_th;
+	uint64_t ppdu_info_drop_flush;
+	uint64_t ppdu_info_drop_trunc;
 };
 
 /**
@@ -419,12 +449,13 @@ enum dp_tx_monitor_framework_mode {
  * dp_pdev_tx_monitor_be - info to store tx capture information in pdev
  * @be_ppdu_id: current ppdu id
  * @mode: tx monitor core framework current mode
- * @tx_stats: tx monitor drop stats for that mac
+ * @stats: tx monitor drop stats for that mac
+ *
  */
 struct dp_pdev_tx_monitor_be {
 	uint32_t be_ppdu_id;
 	uint32_t mode;
-	struct dp_tx_monitor_drop_stats tx_stats;
+	struct dp_tx_monitor_drop_stats stats;
 };
 
 /**
@@ -458,7 +489,7 @@ struct dp_txmon_frag_vec {
  * @tx_ppdu_info_list: ppdu info list to hold ppdu
  * @defer_ppdu_info_list_depth: defer ppdu list depth counter
  * @defer_ppdu_info_list: defer ppdu info list to hold defer ppdu
- * @tx_stats: tx monitor drop stats for that mac
+ * @stats: tx monitor drop stats for that mac
  * @tx_prot_ppdu_info: tx monitor protection ppdu info
  * @tx_data_ppdu_info: tx monitor data ppdu info
  * @last_prot_ppdu_info: last tx monitor protection ppdu info
@@ -487,7 +518,7 @@ struct dp_pdev_tx_monitor_be {
 
 	STAILQ_HEAD(, dp_tx_ppdu_info) defer_tx_ppdu_info_queue;
 
-	struct dp_tx_monitor_drop_stats tx_stats;
+	struct dp_tx_monitor_drop_stats stats;
 
 	struct dp_tx_ppdu_info *tx_prot_ppdu_info;
 	struct dp_tx_ppdu_info *tx_data_ppdu_info;
@@ -530,7 +561,7 @@ void dp_tx_mon_ppdu_info_free(struct dp_tx_ppdu_info *tx_ppdu_info);
  */
 void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
 			      uint8_t usr_idx,
-			      struct dp_pdev_tx_monitor_be *tx_cap_be);
+			      struct dp_pdev_tx_monitor_be *tx_mon_be);
 
 /*
  * dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info
@@ -540,7 +571,7 @@ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
  * Return: void
  */
 void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info,
-			      struct dp_pdev_tx_monitor_be *tx_cap_be);
+			      struct dp_pdev_tx_monitor_be *tx_mon_be);
 
 /*
  * dp_tx_mon_get_ppdu_info() - API to allocate dp_tx_ppdu_info

+ 26 - 2
dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c

@@ -26,6 +26,8 @@
 #include <dp_mon_2.0.h>
 #include <dp_lite_mon.h>
 
+#define MAX_PPDU_INFO_LIST_DEPTH 64
+
 /**
  * dp_tx_mon_status_free_packet_buf() - API to free packet buffer
  * @pdev: pdev Handle
@@ -103,6 +105,9 @@ dp_tx_mon_status_free_packet_buf(struct dp_pdev *pdev,
 						     &mon_desc_list_ref->tail,
 						     mon_desc);
 
+			tx_mon_be->stats.pkt_buf_recv++;
+			tx_mon_be->stats.pkt_buf_free++;
+
 			/* free buffer, mapped to descriptor */
 			qdf_frag_free(packet_buffer);
 		}
@@ -140,6 +145,7 @@ dp_tx_mon_status_queue_free(struct dp_pdev *pdev,
 		end_offset = tx_mon_be->frag_q_vec[i].end_offset;
 		dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
 						 mon_desc_list_ref);
+		tx_mon_be->stats.status_buf_free++;
 		qdf_frag_free(status_frag);
 		tx_mon_be->frag_q_vec[i].frag_buf = NULL;
 		tx_mon_be->frag_q_vec[i].end_offset = 0;
@@ -946,6 +952,8 @@ dp_tx_mon_generate_data_frm(struct dp_pdev *pdev,
 	if (!mpdu_nbuf)
 		QDF_BUG(0);
 
+	tx_mon_be->stats.pkt_buf_processed++;
+
 	/* add function to either copy or add frag to frag_list */
 	qdf_nbuf_add_frag(pdev->soc->osdev,
 			  TXMON_STATUS_INFO(tx_status_info, buffer),
@@ -1320,6 +1328,7 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
 			qdf_assert_always(0);
 
 		qdf_assert_always(mon_desc->buf_addr);
+		tx_mon_be->stats.pkt_buf_recv++;
 
 		if (!mon_desc->unmapped) {
 			qdf_mem_unmap_page(pdev->soc->osdev,
@@ -1401,10 +1410,10 @@ dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev,
 	struct hal_tx_status_info *tx_status_data;
 	qdf_frag_t status_frag = NULL;
 	uint32_t end_offset = 0;
-	uint8_t *tx_tlv;
-	uint8_t *tx_tlv_start;
 	uint32_t tlv_status;
 	uint32_t status = QDF_STATUS_SUCCESS;
+	uint8_t *tx_tlv;
+	uint8_t *tx_tlv_start;
 	uint8_t num_users = 0;
 	uint8_t cur_frag_q_idx;
 	bool schedule_wrq = false;
@@ -1513,6 +1522,7 @@ dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev,
 		 * free status buffer after parsing
 		 * is status_frag mapped to mpdu if so make sure
 		 */
+		tx_mon_be->stats.status_buf_free++;
 		qdf_frag_free(status_frag);
 		tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL;
 		tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset = 0;
@@ -1689,10 +1699,12 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc,
 	    tx_mon_be->last_frag_q_idx) {
 		if (tx_mon_be->be_end_reason_bitmap &
 		    (1 << HAL_MON_FLUSH_DETECTED)) {
+			tx_mon_be->stats.ppdu_info_drop_flush++;
 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
 						    mon_desc_list_ref);
 		} else if (tx_mon_be->be_end_reason_bitmap &
 			   (1 << HAL_MON_PPDU_TRUNCATED)) {
+			tx_mon_be->stats.ppdu_info_drop_trunc++;
 			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
 						    mon_desc_list_ref);
 		} else {
@@ -1721,6 +1733,16 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc,
 	tx_mon_be->last_frag_q_idx++;
 
 	if (mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) {
+		/* drop processing of tlv, if ppdu info list exceed threshold */
+		if ((tx_mon_be->defer_ppdu_info_list_depth +
+		     tx_mon_be->tx_ppdu_info_list_depth) >
+		    MAX_PPDU_INFO_LIST_DEPTH) {
+			tx_mon_be->stats.ppdu_info_drop_th++;
+			dp_tx_mon_status_queue_free(pdev, tx_mon_be,
+						    mon_desc_list_ref);
+			return QDF_STATUS_E_PENDING;
+		}
+
 		if (dp_tx_mon_process_tlv_2_0(pdev,
 					      mon_desc_list_ref) !=
 		    QDF_STATUS_SUCCESS)
@@ -1733,6 +1755,7 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc,
 free_status_buffer:
 	dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
 					 mon_desc_list_ref);
+	tx_mon_be->stats.status_buf_free++;
 	qdf_frag_free(status_frag);
 
 	return QDF_STATUS_E_NOMEM;
@@ -1781,6 +1804,7 @@ dp_tx_mon_process_status_tlv(struct dp_soc *soc,
 
 	dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
 					 mon_desc_list_ref);
+	tx_mon_be->stats.status_buf_free++;
 	qdf_frag_free(status_frag);
 
 	return QDF_STATUS_E_INVAL;

+ 1 - 0
dp/wifi3.0/monitor/dp_mon.h

@@ -57,6 +57,7 @@
 #define dp_mon_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_MON, params)
 #define dp_mon_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_MON, params)
 
+#define dp_mon_warn_rl(params...) QDF_TRACE_WARN_RL(QDF_MODULE_ID_MON, params)
 #define dp_mon_debug_rl(params...) QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_MON, params)
 #define dp_mon_info_rl(params...) \
 	__QDF_TRACE_RL(QDF_TRACE_LEVEL_INFO_HIGH, QDF_MODULE_ID_MON, ## params)

+ 5 - 0
qdf/inc/qdf_nbuf.h

@@ -4202,6 +4202,11 @@ static inline uint32_t qdf_nbuf_get_nr_frags(qdf_nbuf_t nbuf)
 	return __qdf_nbuf_get_nr_frags(nbuf);
 }
 
+static inline uint32_t qdf_nbuf_get_nr_frags_in_fraglist(qdf_nbuf_t nbuf)
+{
+	return __qdf_nbuf_get_nr_frags_in_fraglist(nbuf);
+}
+
 static inline qdf_size_t qdf_nbuf_headlen(qdf_nbuf_t buf)
 {
 	return __qdf_nbuf_headlen(buf);

+ 19 - 0
qdf/linux/src/i_qdf_nbuf.h

@@ -1094,6 +1094,25 @@ static inline size_t __qdf_nbuf_get_nr_frags(struct sk_buff *skb)
 	return skb_shinfo(skb)->nr_frags;
 }
 
+/**
+ * __qdf_nbuf_get_nr_frags_in_fraglist() - return the number of fragments
+ * @skb: sk buff
+ *
+ * This API returns a total number of fragments from the fraglist
+ * Return: total number of fragments
+ */
+static inline uint32_t __qdf_nbuf_get_nr_frags_in_fraglist(struct sk_buff *skb)
+{
+	uint32_t num_frag = 0;
+	struct sk_buff *list = NULL;
+
+	num_frag = skb_shinfo(skb)->nr_frags;
+	skb_walk_frags(skb, list)
+		num_frag += skb_shinfo(list)->nr_frags;
+
+	return num_frag;
+}
+
 /*
  * qdf_nbuf_pool_delete() implementation - do nothing in linux
  */