Эх сурвалжийг харах

qcacmn: Optimize monitor mode memory utilization

a. Optimize ppdu_info memory
b. Use kmem cache for ppdu info allocation

CRs-Fixed: 3265620
Change-Id: Ieee040aa703aef8c5eee5e5a34a52ef18300b696
Amir Patel 2 жил өмнө
parent
commit
0fe7f4446b

+ 8 - 0
dp/inc/cdp_txrx_mon_struct.h

@@ -390,6 +390,10 @@ enum cdp_mon_phyrx_abort_reason_code {
  * @mpdus_to_stack: Number of MPDUs delivered to stack
  * @status_buf_count: Number of status buffer received
  * @empty_desc_ppdu: Number of empty desc received
+ * @total_ppdu_info_enq: Number of PPDUs enqueued to wq
+ * @total_ppdu_info_drop: Number of PPDUs dropped
+ * @total_ppdu_info_alloc: Number of PPDU info allocated
+ * @total_ppdu_info_free: Number of PPDU info freeed
  */
 struct cdp_pdev_mon_stats {
 #ifndef REMOVE_MON_DBG_STATS
@@ -434,6 +438,10 @@ struct cdp_pdev_mon_stats {
 	uint32_t mpdus_buf_to_stack;
 	uint32_t status_buf_count;
 	uint32_t empty_desc_ppdu;
+	uint32_t total_ppdu_info_enq;
+	uint32_t total_ppdu_info_drop;
+	uint32_t total_ppdu_info_alloc;
+	uint32_t total_ppdu_info_free;
 };
 
 #ifdef QCA_SUPPORT_LITE_MONITOR

+ 1 - 0
dp/wifi3.0/monitor/1.0/dp_mon_1.0.c

@@ -1220,6 +1220,7 @@ dp_mon_register_feature_ops_1_0(struct dp_soc *soc)
 	mon_ops->mon_filter_reset_undecoded_metadata_capture =
 		dp_mon_filter_reset_undecoded_metadata_capture_1_0;
 #endif
+	mon_ops->mon_rx_print_advanced_stats = NULL;
 }
 
 struct dp_mon_ops monitor_ops_1_0 = {

+ 66 - 1
dp/wifi3.0/monitor/2.0/dp_mon_2.0.c

@@ -35,6 +35,65 @@
 
 #if !defined(DISABLE_MON_CONFIG)
 
+QDF_STATUS dp_rx_mon_ppdu_info_cache_create(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);
+	uint16_t obj;
+	struct hal_rx_ppdu_info *ppdu_info = NULL;
+
+	mon_pdev_be->ppdu_info_cache =
+		qdf_kmem_cache_create("rx_mon_ppdu_info_cache",
+				      sizeof(struct hal_rx_ppdu_info));
+
+	if (!mon_pdev_be->ppdu_info_cache) {
+		dp_mon_err("cache creation failed pdev :%px", pdev);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	TAILQ_INIT(&mon_pdev_be->rx_mon_free_queue);
+	for (obj = 0; obj < DP_RX_MON_WQ_THRESHOLD; obj++) {
+		ppdu_info =  (struct hal_rx_ppdu_info *)qdf_kmem_cache_alloc(mon_pdev_be->ppdu_info_cache);
+
+		if (ppdu_info) {
+			TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_free_queue,
+					  ppdu_info,
+					  ppdu_free_list_elem);
+			mon_pdev_be->total_free_elem++;
+		}
+	}
+	qdf_spinlock_create(&mon_pdev_be->ppdu_info_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void dp_rx_mon_ppdu_info_cache_destroy(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 hal_rx_ppdu_info *ppdu_info = NULL, *temp_ppdu_info = NULL;
+
+	qdf_err(" total free element: %d", mon_pdev_be->total_free_elem);
+	qdf_spin_lock(&mon_pdev_be->ppdu_info_lock);
+	TAILQ_FOREACH_SAFE(ppdu_info,
+			   &mon_pdev_be->rx_mon_free_queue,
+			   ppdu_free_list_elem,
+			   temp_ppdu_info) {
+		TAILQ_REMOVE(&mon_pdev_be->rx_mon_free_queue,
+			     ppdu_info, ppdu_free_list_elem);
+		if (ppdu_info) {
+			mon_pdev_be->total_free_elem--;
+			qdf_err(" total free element: %d", mon_pdev_be->total_free_elem);
+			qdf_kmem_cache_free(mon_pdev_be->ppdu_info_cache,
+					    ppdu_info);
+		}
+	}
+	qdf_spin_unlock(&mon_pdev_be->ppdu_info_lock);
+	qdf_kmem_cache_destroy(mon_pdev_be->ppdu_info_cache);
+}
+
 /**
  * dp_mon_pdev_ext_init_2_0() - Init pdev ext param
  *
@@ -61,6 +120,7 @@ QDF_STATUS dp_mon_pdev_ext_init_2_0(struct dp_pdev *pdev)
 	TAILQ_INIT(&mon_pdev_be->rx_mon_queue);
 
 	qdf_spinlock_create(&mon_pdev_be->rx_mon_wq_lock);
+	qdf_err(" total free element: %d", mon_pdev_be->total_free_elem);
 
 	return QDF_STATUS_SUCCESS;
 
@@ -84,11 +144,12 @@ QDF_STATUS dp_mon_pdev_ext_deinit_2_0(struct dp_pdev *pdev)
 	if (!mon_pdev_be->rx_mon_workqueue)
 		return QDF_STATUS_E_FAILURE;
 
-	dp_rx_mon_drain_wq(pdev);
+	qdf_err(" total free element: %d", mon_pdev_be->total_free_elem);
 	qdf_flush_workqueue(0, mon_pdev_be->rx_mon_workqueue);
 	qdf_destroy_workqueue(0, mon_pdev_be->rx_mon_workqueue);
 	qdf_flush_work(&mon_pdev_be->rx_mon_work);
 	qdf_disable_work(&mon_pdev_be->rx_mon_work);
+	dp_rx_mon_drain_wq(pdev);
 	mon_pdev_be->rx_mon_workqueue = NULL;
 	qdf_spinlock_destroy(&mon_pdev_be->rx_mon_wq_lock);
 
@@ -1389,6 +1450,8 @@ dp_mon_register_feature_ops_2_0(struct dp_soc *soc)
 		dp_mon_filter_reset_undecoded_metadata_capture_2_0;
 #endif
 	mon_ops->rx_enable_fpmo = dp_rx_mon_enable_fpmo;
+	mon_ops->mon_rx_print_advanced_stats =
+		dp_mon_rx_print_advanced_stats_2_0;
 }
 
 struct dp_mon_ops monitor_ops_2_0 = {
@@ -1477,6 +1540,8 @@ struct dp_mon_ops monitor_ops_2_0 = {
 	.mon_lite_mon_dealloc = dp_lite_mon_dealloc,
 	.mon_lite_mon_vdev_delete = dp_lite_mon_vdev_delete,
 	.mon_lite_mon_disable_rx = dp_lite_mon_disable_rx,
+	.mon_rx_ppdu_info_cache_create = dp_rx_mon_ppdu_info_cache_create,
+	.mon_rx_ppdu_info_cache_destroy = dp_rx_mon_ppdu_info_cache_destroy,
 };
 
 struct cdp_mon_ops dp_ops_mon_2_0 = {

+ 12 - 0
dp/wifi3.0/monitor/2.0/dp_mon_2.0.h

@@ -142,9 +142,17 @@ struct dp_mon_desc_pool {
  * @rx_mon_workqueue: Rx mon workqueue
  * @rx_mon_work: Rx mon work
  * @rx_mon_queue: RxMON queue
+ * @rx_mon_free_queue: RxMON ppdu info free element queue
+ * @ppdu_info_lock: RxPPDU ppdu info queue lock
  * @rx_mon_queue_depth: RxMON queue depth
  * @desc_count: reaped status desc count
  * @status: reaped status buffer per ppdu
+ * @lite_mon_rx_config: rx litemon config
+ * @lite_mon_tx_config: tx litemon config
+ * @prev_rxmon_desc: prev destination desc
+ * @prev_rxmon_cookie: prev rxmon cookie
+ * @ppdu_info_cache: PPDU info cache
+ * @total_free_elem: total free element in queue
  */
 struct dp_mon_pdev_be {
 	struct dp_mon_pdev mon_pdev;
@@ -158,6 +166,8 @@ struct dp_mon_pdev_be {
 	qdf_work_t rx_mon_work;
 
 	TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_queue;
+	TAILQ_HEAD(, hal_rx_ppdu_info) rx_mon_free_queue;
+	qdf_spinlock_t ppdu_info_lock;
 	uint16_t rx_mon_queue_depth;
 	uint16_t desc_count;
 	struct dp_mon_desc *status[DP_MON_MAX_STATUS_BUF];
@@ -167,6 +177,8 @@ struct dp_mon_pdev_be {
 #endif
 	void *prev_rxmon_desc;
 	uint32_t prev_rxmon_cookie;
+	qdf_kmem_cache_t ppdu_info_cache;
+	uint32_t total_free_elem;
 };
 
 /**

+ 139 - 28
dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c

@@ -87,6 +87,54 @@ void dp_rx_mon_set_zero(qdf_nbuf_t nbuf)
 	qdf_mem_zero(qdf_nbuf_head(nbuf), DP_RX_MON_TLV_ROOM);
 }
 
+/**
+ * dp_rx_mon_get_ppdu_info() - Get PPDU info from freelist
+ *
+ * @mon_pdev: monitor pdev
+ *
+ * Return: ppdu_info
+ */
+static inline struct hal_rx_ppdu_info*
+dp_rx_mon_get_ppdu_info(struct dp_mon_pdev *mon_pdev)
+{
+	struct dp_mon_pdev_be *mon_pdev_be =
+			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
+	struct hal_rx_ppdu_info *ppdu_info, *temp_ppdu_info;
+
+	qdf_spin_lock_bh(&mon_pdev_be->ppdu_info_lock);
+	TAILQ_FOREACH_SAFE(ppdu_info,
+			   &mon_pdev_be->rx_mon_free_queue,
+			   ppdu_list_elem,
+			   temp_ppdu_info) {
+		TAILQ_REMOVE(&mon_pdev_be->rx_mon_free_queue,
+			     ppdu_info, ppdu_free_list_elem);
+
+		if (ppdu_info) {
+			mon_pdev_be->total_free_elem--;
+			break;
+		}
+	}
+	qdf_spin_unlock_bh(&mon_pdev_be->ppdu_info_lock);
+
+	return ppdu_info;
+}
+
+static inline void
+__dp_rx_mon_free_ppdu_info(struct dp_mon_pdev *mon_pdev,
+			   struct hal_rx_ppdu_info *ppdu_info)
+{
+	struct dp_mon_pdev_be *mon_pdev_be =
+			dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
+
+	qdf_spin_lock_bh(&mon_pdev_be->ppdu_info_lock);
+	if (ppdu_info) {
+		TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_free_queue, ppdu_info,
+				  ppdu_free_list_elem);
+		mon_pdev_be->total_free_elem++;
+	}
+	qdf_spin_unlock_bh(&mon_pdev_be->ppdu_info_lock);
+}
+
 /**
  * dp_rx_mon_nbuf_add_rx_frag () -  Add frag to SKB
  *
@@ -337,13 +385,14 @@ dp_rx_mon_free_ppdu_info(struct dp_pdev *pdev,
 		qdf_nbuf_t mpdu;
 
 		for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) {
-			mpdu = (qdf_nbuf_t)ppdu_info->mpdu_q[user][mpdu_idx];
+			mpdu = qdf_nbuf_queue_remove(&ppdu_info->mpdu_q[user]);
 
 			if (!mpdu)
 				continue;
 			dp_mon_free_parent_nbuf(mon_pdev, mpdu);
 		}
 	}
+	__dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
 }
 
 void dp_rx_mon_drain_wq(struct dp_pdev *pdev)
@@ -375,7 +424,7 @@ void dp_rx_mon_drain_wq(struct dp_pdev *pdev)
 		TAILQ_REMOVE(&mon_pdev_be->rx_mon_queue,
 			     ppdu_info, ppdu_list_elem);
 
-		dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
+		__dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
 	}
 	qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
 }
@@ -439,7 +488,7 @@ dp_rx_mon_process_ppdu_info(struct dp_pdev *pdev,
 		QDF_STATUS status;
 
 		for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) {
-			mpdu = (qdf_nbuf_t)ppdu_info->mpdu_q[user][mpdu_idx];
+			mpdu = qdf_nbuf_queue_remove(&ppdu_info->mpdu_q[user]);
 
 			if (!mpdu)
 				continue;
@@ -535,7 +584,7 @@ void dp_rx_mon_process_ppdu(void *context)
 
 		mon_pdev_be->rx_mon_queue_depth--;
 		dp_rx_mon_process_ppdu_info(pdev, ppdu_info);
-		qdf_mem_free(ppdu_info);
+		__dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
 	}
 	qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
 }
@@ -549,10 +598,11 @@ void dp_rx_mon_process_ppdu(void *context)
  * Return: SUCCESS or FAILIRE
  */
 
-QDF_STATUS
-dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev *mon_pdev,
+static QDF_STATUS
+dp_rx_mon_add_ppdu_info_to_wq(struct dp_pdev *pdev,
 			      struct hal_rx_ppdu_info *ppdu_info)
 {
+	struct dp_mon_pdev *mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
 	struct dp_mon_pdev_be *mon_pdev_be =
 		dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
 
@@ -562,10 +612,16 @@ dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev *mon_pdev,
 		return QDF_STATUS_E_FAILURE;
 
 	if (qdf_likely(ppdu_info)) {
-		qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
-		TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue,
-				  ppdu_info, ppdu_list_elem);
-		mon_pdev_be->rx_mon_queue_depth++;
+		if (mon_pdev_be->rx_mon_queue_depth < DP_RX_MON_WQ_THRESHOLD) {
+			qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
+			TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue,
+					  ppdu_info, ppdu_list_elem);
+			mon_pdev_be->rx_mon_queue_depth++;
+			mon_pdev->rx_mon_stats.total_ppdu_info_enq++;
+		} else {
+			mon_pdev->rx_mon_stats.total_ppdu_info_drop++;
+			dp_rx_mon_free_ppdu_info(pdev, ppdu_info);
+		}
 		qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
 
 		if (mon_pdev_be->rx_mon_queue_depth > DP_MON_QUEUE_DEPTH_MAX) {
@@ -1041,7 +1097,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 
 			qdf_nbuf_set_next(nbuf, NULL);
 
-			ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf;
+			qdf_nbuf_queue_add(&ppdu_info->mpdu_q[user_id], nbuf);
 
 			status = dp_rx_mon_nbuf_add_rx_frag(nbuf, status_frag,
 							    ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET,
@@ -1067,7 +1123,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 			    !dp_lite_mon_is_level_msdu(mon_pdev))
 				break;
 
-			nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
+			nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
 			if (qdf_unlikely(!nbuf)) {
 				dp_mon_debug("nbuf is NULL");
 				return num_buf_reaped;
@@ -1095,6 +1151,7 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 						   DP_MON_DATA_BUFFER_SIZE,
 						   true);
 		}
+		ppdu_info->rx_hdr_rcvd[user_id] = true;
 	}
 	break;
 	case HAL_TLV_STATUS_MON_BUF_ADDR:
@@ -1125,9 +1182,8 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 		num_buf_reaped++;
 
 		mon_pdev->rx_mon_stats.pkt_buf_count++;
-		nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
 
-		if (qdf_unlikely(!nbuf)) {
+		if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
 
 			/* WAR: RX_HDR is not received for this MPDU, drop this frame */
 			mon_pdev->rx_mon_stats.rx_hdr_not_received++;
@@ -1136,15 +1192,17 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 			return num_buf_reaped;
 		}
 
+		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
+
 		if (mpdu_info->decap_type == DP_MON_DECAP_FORMAT_INVALID) {
 			/* decap type is invalid, drop the frame */
 			mon_pdev->rx_mon_stats.mpdu_decap_type_invalid++;
 			DP_STATS_INC(mon_soc, frag_free, 1);
 			mon_pdev->rx_mon_stats.parent_buf_free++;
 			qdf_frag_free(addr);
+			qdf_nbuf_queue_remove_last(&ppdu_info->mpdu_q[user_id]);
 			qdf_nbuf_free(nbuf);
 			/* we have freed the nbuf mark the q entry null */
-			ppdu_info->mpdu_q[user_id][mpdu_idx] = NULL;
 			return num_buf_reaped;
 		}
 
@@ -1160,8 +1218,9 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 				DP_STATS_INC(mon_soc, frag_free, 1);
 				mon_pdev->rx_mon_stats.parent_buf_free++;
 				qdf_frag_free(addr);
+				/* remove this nbuf from queue */
+				qdf_nbuf_queue_remove_last(&ppdu_info->mpdu_q[user_id]);
 				qdf_nbuf_free(nbuf);
-				ppdu_info->mpdu_q[user_id][mpdu_idx] = NULL;
 				return num_buf_reaped;
 			}
 			mon_pdev->rx_mon_stats.parent_buf_alloc++;
@@ -1222,14 +1281,14 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 		struct hal_rx_mon_msdu_info *msdu_info = &ppdu_info->msdu[user_id];
 		struct hal_rx_mon_msdu_info *last_buf_info;
 		/* update msdu metadata at last buffer of msdu in MPDU */
-		nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
-		if (!nbuf) {
+		if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
 			/* reset msdu info for next msdu for same user */
 			qdf_mem_zero(msdu_info, sizeof(*msdu_info));
 			dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d",
 				     __LINE__, user_id, mpdu_idx);
 			break;
 		}
+		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
 		num_frags = qdf_nbuf_get_nr_frags(nbuf);
 		if (ppdu_info->mpdu_info[user_id].decap_type ==
 				HAL_HW_RX_DECAP_FORMAT_RAW) {
@@ -1263,12 +1322,11 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 	{
 		struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta;
 
-		nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
-		if (!nbuf) {
-			dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d",
-				     __LINE__, user_id, mpdu_idx);
+		if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
+			dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx);
 			break;
 		}
+		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
 		mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
 		mpdu_info = &ppdu_info->mpdu_info[user_id];
 		mpdu_meta->decap_type = mpdu_info->decap_type;
@@ -1279,14 +1337,14 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 	{
 		struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta;
 		mpdu_info = &ppdu_info->mpdu_info[user_id];
-		nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
-		if (!nbuf) {
+		if (qdf_unlikely(!ppdu_info->rx_hdr_rcvd[user_id])) {
 			/* reset mpdu info for next mpdu for same user */
 			qdf_mem_zero(mpdu_info, sizeof(*mpdu_info));
 			dp_mon_debug(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d",
 				     __LINE__, user_id, mpdu_idx);
 			break;
 		}
+		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
 		mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
 		mpdu_meta->mpdu_length_err = mpdu_info->mpdu_length_err;
 		mpdu_meta->fcs_err = mpdu_info->fcs_err;
@@ -1296,11 +1354,11 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 		mpdu_meta->full_pkt = mpdu_info->full_pkt;
 		mpdu_meta->truncated = mpdu_info->truncated;
 
-		ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf;
 		/* reset mpdu info for next mpdu for same user */
 		qdf_mem_zero(mpdu_info, sizeof(*mpdu_info));
 		ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = false;
 		ppdu_info->mpdu_count[user_id]++;
+		ppdu_info->rx_hdr_rcvd[user_id] = false;
 	}
 	break;
 	}
@@ -1324,7 +1382,7 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev)
 	union dp_mon_desc_list_elem_t *desc_list = NULL;
 	union dp_mon_desc_list_elem_t *tail = NULL;
 	struct dp_mon_desc *mon_desc;
-	uint8_t idx;
+	uint8_t idx, user;
 	void *buf;
 	struct hal_rx_ppdu_info *ppdu_info;
 	uint8_t *rx_tlv;
@@ -1342,12 +1400,17 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev)
 		return NULL;
 	}
 
-	ppdu_info = &mon_pdev->ppdu_info;
+	ppdu_info = dp_rx_mon_get_ppdu_info(mon_pdev);
 
 	if (!ppdu_info) {
 		dp_mon_err("ppdu_info malloc failed pdev: %pK", pdev);
+		dp_rx_mon_flush_status_buf_queue(pdev);
 		return NULL;
 	}
+	mon_pdev->rx_mon_stats.total_ppdu_info_alloc++;
+
+	for (user = 0; user < HAL_MAX_UL_MU_USERS; user++)
+		qdf_nbuf_queue_init(&ppdu_info->mpdu_q[user]);
 
 	status_buf_count = mon_pdev_be->desc_count;
 	for (idx = 0; idx < status_buf_count; idx++) {
@@ -1592,7 +1655,11 @@ dp_rx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
 		else if (dp_cfr_rcc_mode_status(pdev) && ppdu_info)
 			dp_rx_handle_cfr(soc, pdev, ppdu_info);
 
-		dp_rx_mon_process_ppdu_info(pdev, ppdu_info);
+		status = dp_rx_mon_add_ppdu_info_to_wq(pdev, ppdu_info);
+		if (status != QDF_STATUS_SUCCESS) {
+			if (ppdu_info)
+				__dp_rx_mon_free_ppdu_info(mon_pdev, ppdu_info);
+		}
 
 		work_done++;
 
@@ -1810,4 +1877,48 @@ dp_rx_mon_populate_ppdu_info_2_0(struct hal_rx_ppdu_info *hal_ppdu_info,
 	ppdu->punc_bw = NO_PUNCTURE;
 }
 #endif
+void dp_mon_rx_print_advanced_stats_2_0(struct dp_soc *soc,
+					struct dp_pdev *pdev)
+{
+	struct cdp_pdev_mon_stats *rx_mon_stats;
+	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
+	struct dp_mon_soc *mon_soc = pdev->soc->monitor_soc;
+	struct dp_mon_pdev_be *mon_pdev_be =
+				dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
+
+	rx_mon_stats = &mon_pdev->rx_mon_stats;
+
+	DP_PRINT_STATS("total_ppdu_info_alloc = %d",
+		       rx_mon_stats->total_ppdu_info_alloc);
+	DP_PRINT_STATS("total_ppdu_info_free = %d",
+		       rx_mon_stats->total_ppdu_info_free);
+	DP_PRINT_STATS("total_ppdu_info_enq = %d",
+		       rx_mon_stats->total_ppdu_info_enq);
+	DP_PRINT_STATS("total_ppdu_info_drop = %d",
+		       rx_mon_stats->total_ppdu_info_drop);
+	DP_PRINT_STATS("rx_hdr_not_received = %d",
+		       rx_mon_stats->rx_hdr_not_received);
+	DP_PRINT_STATS("parent_buf_alloc = %d",
+		       rx_mon_stats->parent_buf_alloc);
+	DP_PRINT_STATS("parent_buf_free = %d",
+		       rx_mon_stats->parent_buf_free);
+	DP_PRINT_STATS("mpdus_buf_to_stack = %d",
+		       rx_mon_stats->mpdus_buf_to_stack);
+	DP_PRINT_STATS("frag_alloc = %d",
+		       mon_soc->stats.frag_alloc);
+	DP_PRINT_STATS("frag_free = %d",
+		       mon_soc->stats.frag_free);
+	DP_PRINT_STATS("status_buf_count = %d",
+		       rx_mon_stats->status_buf_count);
+	DP_PRINT_STATS("pkt_buf_count = %d",
+		       rx_mon_stats->pkt_buf_count);
+	DP_PRINT_STATS("rx_mon_queue_depth= %d",
+		       mon_pdev_be->rx_mon_queue_depth);
+	DP_PRINT_STATS("empty_desc= %d",
+		       mon_pdev->rx_mon_stats.empty_desc_ppdu);
+	DP_PRINT_STATS("mpdu_dropped_due_invalid_decap= %d",
+		       mon_pdev->rx_mon_stats.mpdu_decap_type_invalid);
+	DP_PRINT_STATS("total_free_elem= %d",
+		       mon_pdev_be->total_free_elem);
+}
 #endif

+ 11 - 0
dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.h

@@ -49,6 +49,7 @@
 			    + (DP_RX_MON_TLV_HDR_MARKER_LEN)\
 			    + (DP_RX_MON_TLV_TOTAL_LEN))
 
+#define DP_RX_MON_WQ_THRESHOLD 128
 /*
  * dp_rx_mon_buffers_alloc() - allocate rx monitor buffers
  * @soc: DP soc handle
@@ -232,4 +233,14 @@ void dp_rx_mon_shift_pf_tag_in_headroom(qdf_nbuf_t nbuf, struct dp_soc *soc)
 {
 }
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
+/**
+ * dp_mon_rx_print_advanced_stats_2_0 () - print advanced monitor statistics
+ *
+ * @soc: DP soc handle
+ * @pdev: DP pdev handle
+ *
+ * Return: void
+ */
+void dp_mon_rx_print_advanced_stats_2_0(struct dp_soc *soc,
+					struct dp_pdev *pdev);
 #endif /* _DP_RX_MON_2_0_H_ */

+ 12 - 17
dp/wifi3.0/monitor/dp_mon.c

@@ -827,7 +827,6 @@ dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev)
 	uint32_t *dest_ring_ppdu_ids;
 	int i, idx;
 	struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
-	struct dp_mon_soc *mon_soc = pdev->soc->monitor_soc;
 
 	rx_mon_stats = &mon_pdev->rx_mon_stats;
 
@@ -906,23 +905,8 @@ dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev)
 	DP_PRINT_STATS("mon_rx_dest_stuck = %d",
 		       rx_mon_stats->mon_rx_dest_stuck);
 
-	DP_PRINT_STATS("rx_hdr_not_received = %d",
-		       rx_mon_stats->rx_hdr_not_received);
-	DP_PRINT_STATS("parent_buf_alloc = %d",
-		       rx_mon_stats->parent_buf_alloc);
-	DP_PRINT_STATS("parent_buf_free = %d",
-		       rx_mon_stats->parent_buf_free);
-	DP_PRINT_STATS("mpdus_buf_to_stack = %d",
-		       rx_mon_stats->mpdus_buf_to_stack);
-	DP_PRINT_STATS("frag_alloc = %d",
-		       mon_soc->stats.frag_alloc);
-	DP_PRINT_STATS("frag_free = %d",
-		       mon_soc->stats.frag_free);
-	DP_PRINT_STATS("status_buf_count = %d",
-		       rx_mon_stats->status_buf_count);
-	DP_PRINT_STATS("pkt_buf_count = %d",
-		       rx_mon_stats->pkt_buf_count);
 	dp_pdev_get_undecoded_capture_stats(mon_pdev, rx_mon_stats);
+	dp_mon_rx_print_advanced_stats(pdev->soc, pdev);
 }
 
 #ifdef QCA_SUPPORT_BPR
@@ -5046,10 +5030,19 @@ QDF_STATUS dp_mon_pdev_attach(struct dp_pdev *pdev)
 		}
 	}
 
+	if (mon_ops->mon_rx_ppdu_info_cache_create) {
+		if (mon_ops->mon_rx_ppdu_info_cache_create(pdev)) {
+			dp_mon_err("%pK: dp_rx_pdev_mon_attach failed", pdev);
+			goto fail4;
+		}
+	}
 	pdev->monitor_pdev = mon_pdev;
 	dp_mon_pdev_per_target_config(pdev);
 
 	return QDF_STATUS_SUCCESS;
+fail4:
+	if (mon_ops->rx_mon_desc_pool_free)
+		mon_ops->rx_mon_desc_pool_free(pdev);
 fail3:
 	if (mon_ops->mon_rings_free)
 		mon_ops->mon_rings_free(pdev);
@@ -5085,6 +5078,8 @@ QDF_STATUS dp_mon_pdev_detach(struct dp_pdev *pdev)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (mon_ops->mon_rx_ppdu_info_cache_destroy)
+		mon_ops->mon_rx_ppdu_info_cache_destroy(pdev);
 	if (mon_ops->rx_mon_desc_pool_free)
 		mon_ops->rx_mon_desc_pool_free(pdev);
 	if (mon_ops->mon_rings_free)

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

@@ -820,6 +820,11 @@ struct dp_mon_ops {
 	void (*mon_lite_mon_vdev_delete)(struct dp_pdev *pdev,
 					 struct dp_vdev *vdev);
 	void (*mon_lite_mon_disable_rx)(struct dp_pdev *pdev);
+	/* Print advanced monitor stats */
+	void (*mon_rx_print_advanced_stats)
+		(struct dp_soc *soc, struct dp_pdev *pdev);
+	QDF_STATUS (*mon_rx_ppdu_info_cache_create)(struct dp_pdev *pdev);
+	void (*mon_rx_ppdu_info_cache_destroy)(struct dp_pdev *pdev);
 };
 
 /**
@@ -4257,6 +4262,7 @@ void dp_monitor_peer_telemetry_stats(struct dp_peer *peer,
 #endif
 
 /**
+<<<<<<< HEAD
  * dp_monitor_is_tx_cap_enabled() - get tx-cature enabled/disabled
  * @peer: DP peer handle
  *
@@ -4298,4 +4304,33 @@ qdf_size_t dp_mon_get_context_size_be(enum dp_context_type context_type)
 	}
 }
 #endif
+
+/*
+ * dp_mon_rx_print_advanced_stats () - print advanced monitor stats
+ *
+ * @soc: DP soc handle
+ * @pdev: DP pdev handle
+ *
+ * Return: void
+ */
+static inline void
+dp_mon_rx_print_advanced_stats(struct dp_soc *soc,
+			       struct dp_pdev *pdev)
+{
+	struct dp_mon_soc *mon_soc = soc->monitor_soc;
+	struct dp_mon_ops *monitor_ops;
+
+	if (!mon_soc) {
+		dp_mon_debug("mon soc is NULL");
+		return;
+	}
+
+	monitor_ops = mon_soc->mon_ops;
+	if (!monitor_ops ||
+	    !monitor_ops->mon_rx_print_advanced_stats) {
+		dp_mon_debug("callback not registered");
+		return;
+	}
+	return monitor_ops->mon_rx_print_advanced_stats(soc, pdev);
+}
 #endif /* _DP_MON_H_ */

+ 63 - 60
hal/wifi3.0/hal_api_mon.h

@@ -224,9 +224,9 @@ enum hal_eht_ppdu_sig_cmn_type {
  */
 struct hal_mon_packet_info {
 	uint64_t sw_cookie;
-	uint16_t dma_length;
-	bool msdu_continuation;
-	bool truncated;
+	uint32_t dma_length : 16,
+		 msdu_continuation : 1,
+		 truncated : 1;
 };
 
 /*
@@ -239,34 +239,34 @@ struct hal_mon_packet_info {
  * @first_msdu: first msdu
  * @decap_type: decap type
  * @last_msdu: last msdu
- * @buffer_len: buffer len
- * @frag_len: frag len
- * @msdu_len: msdu len
- * @msdu_index: msdu index
- * @user_rssi: user rssi
  * @l3_header_padding: L3 padding header
  * @stbc: stbc enabled
  * @sgi: SGI value
  * @reception_type: reception type
+ * @msdu_index: msdu index
+ * @buffer_len: buffer len
+ * @frag_len: frag len
+ * @msdu_len: msdu len
+ * @user_rssi: user rssi
  */
 struct hal_rx_mon_msdu_info {
-	uint8_t first_buffer;
-	uint8_t last_buffer;
-	uint8_t first_mpdu;
-	uint8_t mpdu_length_err;
-	uint8_t fcs_err;
-	uint8_t first_msdu;
-	uint8_t decap_type;
-	uint8_t last_msdu;
-	uint16_t buffer_len;
-	uint16_t frag_len;
+	uint32_t first_buffer : 1,
+		 last_buffer : 1,
+		 first_mpdu : 1,
+		 mpdu_length_err : 1,
+		 fcs_err : 1,
+		 first_msdu : 1,
+		 decap_type : 3,
+		 last_msdu : 1,
+		 l3_header_padding : 3,
+		 stbc : 1,
+		 sgi : 2,
+		 reception_type : 3,
+		 msdu_index : 4;
+	uint16_t buffer_len : 12;
+	uint16_t frag_len : 12;
 	uint16_t msdu_len;
-	uint8_t msdu_index;
-	int8_t user_rssi;
-	uint8_t l3_header_padding;
-	uint8_t stbc;
-	uint8_t sgi;
-	uint8_t reception_type;
+	int16_t user_rssi;
 };
 
 /*
@@ -282,15 +282,15 @@ struct hal_rx_mon_msdu_info {
  * @truncated: truncated MPDU
  */
 struct hal_rx_mon_mpdu_info {
-	uint8_t decap_type;
-	bool mpdu_length_err;
-	bool fcs_err;
-	bool overflow_err;
-	bool decrypt_err;
-	bool mpdu_start_received;
-	bool full_pkt;
-	bool first_rx_hdr_rcvd;
-	bool truncated;
+	uint32_t decap_type : 8,
+		 mpdu_length_err : 1,
+		 fcs_err : 1,
+		 overflow_err : 1,
+		 decrypt_err : 1,
+		 mpdu_start_received : 1,
+		 full_pkt : 1,
+		 first_rx_hdr_rcvd : 1,
+		 truncated : 1;
 };
 
 /**
@@ -628,12 +628,12 @@ enum {
 struct hal_rx_ppdu_common_info {
 	uint32_t ppdu_id;
 	uint64_t ppdu_timestamp;
-	uint32_t mpdu_cnt_fcs_ok;
-	uint32_t mpdu_cnt_fcs_err;
+	uint16_t mpdu_cnt_fcs_ok;
+	uint8_t mpdu_cnt_fcs_err;
+	uint8_t num_users;
 	uint32_t mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
 	uint32_t last_ppdu_id;
-	uint32_t mpdu_cnt;
-	uint8_t num_users;
+	uint16_t mpdu_cnt;
 };
 
 /**
@@ -643,7 +643,7 @@ struct hal_rx_ppdu_common_info {
  */
 struct hal_rx_msdu_payload_info {
 	uint8_t *first_msdu_payload;
-	uint32_t payload_len;
+	uint8_t payload_len;
 };
 
 /**
@@ -652,32 +652,32 @@ struct hal_rx_msdu_payload_info {
  * @frame_control: frame control from each MPDU
  * @to_ds_flag: flag indicate to_ds bit
  * @mac_addr2_valid: flag indicate if mac_addr2 is valid
- * @mac_addr2: mac address2 in wh
  * @mcast_bcast: multicast/broadcast
+ * @mac_addr2: mac address2 in wh
  */
 struct hal_rx_nac_info {
-	uint8_t fc_valid;
-	uint16_t frame_control;
-	uint8_t to_ds_flag;
-	uint8_t mac_addr2_valid;
+	uint32_t fc_valid : 1,
+		 frame_control : 16,
+		 to_ds_flag : 1,
+		 mac_addr2_valid : 1,
+		 mcast_bcast : 1;
 	uint8_t mac_addr2[QDF_MAC_ADDR_SIZE];
-	uint8_t mcast_bcast;
 };
 
 /**
  * struct hal_rx_ppdu_msdu_info - struct for msdu info from HW TLVs
+ * @fse_metadata: cached FSE metadata value received in the MSDU END TLV
  * @cce_metadata: cached CCE metadata value received in the MSDU_END TLV
  * @is_flow_idx_timeout: flag to indicate if flow search timeout occurred
  * @is_flow_idx_invalid: flag to indicate if flow idx is valid or not
- * @fse_metadata: cached FSE metadata value received in the MSDU END TLV
  * @flow_idx: flow idx matched in FSE received in the MSDU END TLV
  */
 struct hal_rx_ppdu_msdu_info {
-	uint16_t cce_metadata;
-	bool is_flow_idx_timeout;
-	bool is_flow_idx_invalid;
 	uint32_t fse_metadata;
-	uint32_t flow_idx;
+	uint32_t cce_metadata : 16,
+		 is_flow_idx_timeout : 1,
+		 is_flow_idx_invalid : 1;
+	uint32_t flow_idx : 20;
 };
 
 #if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE)
@@ -691,7 +691,7 @@ struct hal_rx_ppdu_msdu_info {
  */
 struct hal_rx_ppdu_cfr_user_info {
 	uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE];
-	uint32_t ast_index;
+	uint16_t ast_index;
 };
 
 /**
@@ -790,7 +790,6 @@ struct hal_rx_ppdu_cfr_info {
 	uint8_t chan_capture_status;
 	uint8_t rtt_che_buffer_pointer_high8;
 	uint32_t rtt_che_buffer_pointer_low32;
-	struct hal_rx_ppdu_cfr_user_info cfr_user_info[HAL_MAX_UL_MU_USERS];
 	int16_t rtt_cfo_measurement;
 	uint32_t agc_gain_info0;
 	uint32_t agc_gain_info1;
@@ -809,7 +808,7 @@ struct mon_rx_info {
 	uint16_t qos_control;
 	uint8_t mac_addr1_valid;
 	uint8_t mac_addr1[QDF_MAC_ADDR_SIZE];
-	uint32_t user_id;
+	uint16_t user_id;
 };
 
 struct mon_rx_user_info {
@@ -819,9 +818,9 @@ struct mon_rx_user_info {
 
 #ifdef QCA_SUPPORT_SCAN_SPCL_VAP_STATS
 struct hal_rx_frm_type_info {
-	uint32_t rx_mgmt_cnt;
-	uint32_t rx_ctrl_cnt;
-	uint32_t rx_data_cnt;
+	uint8_t rx_mgmt_cnt;
+	uint8_t rx_ctrl_cnt;
+	uint8_t rx_data_cnt;
 };
 #else
 struct hal_rx_frm_type_info {};
@@ -1211,9 +1210,9 @@ struct hal_rx_ppdu_info {
 	struct hal_rx_msdu_payload_info fcs_ok_msdu_info;
 	struct hal_rx_nac_info nac_info;
 	/* status ring PPDU start and end state */
-	uint32_t rx_state;
+	uint8_t rx_state;
 	/* MU user id for status ring TLV */
-	uint32_t user_id;
+	uint8_t user_id;
 	/* MPDU/MSDU truncated to 128 bytes header start addr in status skb */
 	unsigned char *data;
 	/* MPDU/MSDU truncated to 128 bytes header real length */
@@ -1245,9 +1244,9 @@ struct hal_rx_ppdu_info {
 	/* EHT SIG user info */
 	uint32_t eht_sig_user_info;
 	/*per user mpdu count */
-	uint16_t mpdu_count[HAL_MAX_UL_MU_USERS];
+	uint8_t mpdu_count[HAL_MAX_UL_MU_USERS];
 	/*per user msdu count */
-	uint16_t msdu_count[HAL_MAX_UL_MU_USERS];
+	uint8_t msdu_count[HAL_MAX_UL_MU_USERS];
 	/* Placeholder to update per user last processed msdu’s info */
 	struct hal_rx_mon_msdu_info  msdu[HAL_MAX_UL_MU_USERS];
 	/* Placeholder to update per user last processed mpdu’s info */
@@ -1256,10 +1255,14 @@ struct hal_rx_ppdu_info {
 	struct hal_mon_packet_info packet_info;
 #ifdef QCA_MONITOR_2_0_SUPPORT
 	 /* per user per MPDU queue */
-	qdf_nbuf_t mpdu_q[HAL_MAX_UL_MU_USERS][HAL_RX_MAX_MPDU];
+	qdf_nbuf_queue_t mpdu_q[HAL_MAX_UL_MU_USERS];
 #endif
 	 /* ppdu info list element */
 	TAILQ_ENTRY(hal_rx_ppdu_info) ppdu_list_elem;
+	 /* ppdu info free list element */
+	TAILQ_ENTRY(hal_rx_ppdu_info) ppdu_free_list_elem;
+	/* placeholder to track if RX_HDR is received */
+	uint8_t rx_hdr_rcvd[HAL_MAX_UL_MU_USERS];
 };
 
 static inline uint32_t

+ 0 - 6
hal/wifi3.0/li/hal_li_generic_api.h

@@ -661,9 +661,6 @@ hal_rx_status_get_tlv_info_generic_li(void *rx_tlv_hdr, void *ppduinfo,
 
 	rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE;
 
-	qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
-			   rx_tlv, tlv_len);
-
 	switch (tlv_tag) {
 	case WIFIRX_PPDU_START_E:
 	{
@@ -1750,9 +1747,6 @@ hal_rx_status_get_tlv_info_generic_li(void *rx_tlv_hdr, void *ppduinfo,
 			  __func__, tlv_tag, tlv_len,
 			  unhandled == true ? "unhandled" : "");
 
-	qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
-				rx_tlv, tlv_len);
-
 	return HAL_TLV_STATUS_PPDU_NOT_DONE;
 }