Răsfoiți Sursa

qcacmn: Add support for Extended Mcopy Mode

Currently, mcopy mode delivers first msdu(fcs_passed 128 bytes) per-ppdu
to upper layer, add support for Extended mcopy mode to deliver first
msdu(128 bytes) per-MPDU(fcs_passed).

Change-Id: Ib345fc14a8d468788b9de78516d27e8dff24caa4
CRs-Fixed: 2644175
Himanshu Batra 5 ani în urmă
părinte
comite
879fd03fe1

+ 3 - 5
dp/wifi3.0/dp_main.c

@@ -4591,7 +4591,6 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force)
 	dp_tx_ppdu_stats_detach(pdev);
 
 	qdf_nbuf_free(pdev->sojourn_buf);
-	qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q);
 
 	dp_cal_client_detach(&pdev->cal_client_ctx);
 
@@ -7231,10 +7230,9 @@ QDF_STATUS dp_monitor_mode_ring_config(struct dp_soc *soc, uint8_t mac_for_pdev,
 static inline void
 dp_pdev_disable_mcopy_code(struct dp_pdev *pdev)
 {
-	pdev->mcopy_mode = 0;
+	pdev->mcopy_mode = M_COPY_DISABLED;
 	pdev->monitor_configured = false;
 	pdev->monitor_vdev = NULL;
-	qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q);
 }
 
 /**
@@ -8236,7 +8234,6 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val)
 		}
 #endif /* FEATURE_PERPKT_INFO */
 	}
-
 	switch (val) {
 	case 0:
 		pdev->tx_sniffer_enable = 0;
@@ -8274,13 +8271,14 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val)
 				DP_PPDU_STATS_CFG_SNIFFER, pdev->pdev_id);
 		break;
 	case 2:
+	case 4:
 		if (pdev->monitor_vdev) {
 			status = QDF_STATUS_E_RESOURCES;
 			break;
 		}
 
 #ifdef FEATURE_PERPKT_INFO
-		pdev->mcopy_mode = 1;
+		pdev->mcopy_mode = val;
 		pdev->tx_sniffer_enable = 0;
 		pdev->monitor_configured = true;
 

+ 1 - 0
dp/wifi3.0/dp_mon_filter.c

@@ -605,6 +605,7 @@ void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev)
 	/* Setup the filter */
 	filter.tlv_filter.enable_mo = 1;
 	filter.tlv_filter.packet_header = 1;
+	filter.tlv_filter.mpdu_end = 1;
 	dp_mon_filter_show_filter(pdev, mode, &filter);
 
 	srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS;

+ 202 - 119
dp/wifi3.0/dp_rx_mon_status.c

@@ -695,87 +695,14 @@ static void dp_rx_stats_update(struct dp_pdev *pdev,
 }
 #endif
 
-/*
- * dp_rx_get_fcs_ok_msdu() - get ppdu status buffer containing fcs_ok msdu
- * @pdev: pdev object
- * @ppdu_info: ppdu info object
- *
- * Return: nbuf
- */
-
-static inline qdf_nbuf_t
-dp_rx_get_fcs_ok_msdu(struct dp_pdev *pdev,
-		      struct hal_rx_ppdu_info *ppdu_info)
-{
-	uint16_t mpdu_fcs_ok;
-	qdf_nbuf_t status_nbuf = NULL;
-	unsigned long *fcs_ok_bitmap;
-
-	if (qdf_unlikely(qdf_nbuf_is_queue_empty(&pdev->rx_ppdu_buf_q)))
-		return NULL;
-
-	/* Obtain fcs_ok passed index from bitmap
-	 * this index is used to get fcs passed first msdu payload
-	 */
-
-	fcs_ok_bitmap =
-		(unsigned long *)&ppdu_info->com_info.mpdu_fcs_ok_bitmap[0];
-	mpdu_fcs_ok = qdf_find_first_bit(fcs_ok_bitmap,
-					 HAL_RX_MAX_MPDU);
-
-	if (qdf_unlikely(mpdu_fcs_ok >= HAL_RX_MAX_MPDU))
-		goto end;
-
-	if (qdf_unlikely(!ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf))
-		goto end;
-
-	/* Get status buffer by indexing mpdu_fcs_ok index
-	 * containing first msdu payload with fcs passed
-	 * and clone the buffer
-	 */
-	status_nbuf = ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf;
-	ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf = NULL;
-
-	/* Take ref of status nbuf as this nbuf is to be
-	 * freeed by upper layer.
-	 */
-	qdf_nbuf_ref(status_nbuf);
-	ppdu_info->fcs_ok_msdu_info.first_msdu_payload =
-		ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].first_msdu_payload;
-	ppdu_info->fcs_ok_msdu_info.payload_len =
-		ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].payload_len;
-
-
-end:
-	/* Free the ppdu status buffer queue */
-	qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q);
-
-	qdf_mem_zero(&ppdu_info->ppdu_msdu_info,
-		     (ppdu_info->com_info.mpdu_cnt_fcs_ok +
-		      ppdu_info->com_info.mpdu_cnt_fcs_err)
-		     * sizeof(struct hal_rx_msdu_payload_info));
-	return status_nbuf;
-}
-
-static inline void
-dp_rx_handle_ppdu_status_buf(struct dp_pdev *pdev,
-			     struct hal_rx_ppdu_info *ppdu_info,
-			     qdf_nbuf_t status_nbuf)
-{
-	qdf_nbuf_t dropnbuf;
-
-	if (qdf_nbuf_queue_len(&pdev->rx_ppdu_buf_q) >
-			       HAL_RX_MAX_MPDU) {
-		dropnbuf = qdf_nbuf_queue_remove(&pdev->rx_ppdu_buf_q);
-		qdf_nbuf_free(dropnbuf);
-	}
-	qdf_nbuf_queue_add(&pdev->rx_ppdu_buf_q, status_nbuf);
-}
 /**
  * dp_rx_handle_mcopy_mode() - Allocate and deliver first MSDU payload
  * @soc: core txrx main context
- * @pdev: pdev strcuture
+ * @pdev: pdev structure
  * @ppdu_info: structure for rx ppdu ring
+ * @nbuf: QDF nbuf
+ * @fcs_ok_mpdu_cnt: fcs passsed mpdu index
+ * @deliver_frame: flag to deliver wdi event
  *
  * Return: QDF_STATUS_SUCCESS - If nbuf to be freed by caller
  *         QDF_STATUS_E_ALREADY - If nbuf not to be freed by caller
@@ -783,24 +710,25 @@ dp_rx_handle_ppdu_status_buf(struct dp_pdev *pdev,
 #ifdef FEATURE_PERPKT_INFO
 static inline QDF_STATUS
 dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev,
-			struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf)
+			struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf,
+			uint8_t fcs_ok_mpdu_cnt, bool deliver_frame)
 {
-	uint8_t size = 0;
+	uint16_t size = 0;
 	struct ieee80211_frame *wh;
 	uint32_t *nbuf_data;
 
-	if (!ppdu_info->fcs_ok_msdu_info.first_msdu_payload)
+	if (!ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].first_msdu_payload)
 		return QDF_STATUS_SUCCESS;
 
-	if (pdev->m_copy_id.rx_ppdu_id == ppdu_info->com_info.ppdu_id)
-		return QDF_STATUS_SUCCESS;
-
-	pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id;
+	/* For M_COPY mode only one msdu per ppdu is sent to upper layer*/
+	if (pdev->mcopy_mode == M_COPY) {
+		if (pdev->m_copy_id.rx_ppdu_id == ppdu_info->com_info.ppdu_id)
+			return QDF_STATUS_SUCCESS;
+	}
 
-	wh = (struct ieee80211_frame *)
-		(ppdu_info->fcs_ok_msdu_info.first_msdu_payload + 4);
+	wh = (struct ieee80211_frame *)(ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].first_msdu_payload + 4);
 
-	size = (ppdu_info->fcs_ok_msdu_info.first_msdu_payload -
+	size = (ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].first_msdu_payload -
 				qdf_nbuf_data(nbuf));
 
 	if (qdf_nbuf_pull_head(nbuf, size) == NULL)
@@ -813,63 +741,215 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev,
 		return QDF_STATUS_SUCCESS;
 	}
 
-	ppdu_info->fcs_ok_msdu_info.first_msdu_payload = NULL;
 	nbuf_data = (uint32_t *)qdf_nbuf_data(nbuf);
 	*nbuf_data = pdev->ppdu_info.com_info.ppdu_id;
 	/* only retain RX MSDU payload in the skb */
-	qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) -
-				ppdu_info->fcs_ok_msdu_info.payload_len);
-	dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc,
-			nbuf, HTT_INVALID_PEER, WDI_NO_VAL, pdev->pdev_id);
+	qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) - ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].payload_len);
+	if (deliver_frame) {
+		pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id;
+		dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc,
+				     nbuf, HTT_INVALID_PEER,
+				     WDI_NO_VAL, pdev->pdev_id);
+	}
 	return QDF_STATUS_E_ALREADY;
 }
 #else
 static inline QDF_STATUS
 dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev,
-			struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf)
+			struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf,
+			uint8_t fcs_ok_cnt, bool deliver_frame)
 {
 	return QDF_STATUS_SUCCESS;
 }
 #endif
 
+/**
+ * dp_rx_mcopy_handle_last_mpdu() - cache and delive last MPDU header in a
+ * status buffer if MPDU end tlv is received in different buffer
+ * @soc: core txrx main context
+ * @pdev: pdev structure
+ * @ppdu_info: structure for rx ppdu ring
+ * @status_nbuf: QDF nbuf
+ *
+ * Return: void
+ */
 #ifdef FEATURE_PERPKT_INFO
 static inline void
-dp_rx_process_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev,
-			 struct hal_rx_ppdu_info *ppdu_info,
-			 uint32_t tlv_status,
-			 qdf_nbuf_t status_nbuf)
+dp_rx_mcopy_handle_last_mpdu(struct dp_soc *soc, struct dp_pdev *pdev,
+			     struct hal_rx_ppdu_info *ppdu_info,
+			     qdf_nbuf_t status_nbuf)
 {
 	QDF_STATUS mcopy_status;
+	qdf_nbuf_t nbuf_clone = NULL;
+	/* If the MPDU end tlv and RX header are received in different buffers,
+	 * process the RX header based on fcs status.
+	 */
+	if (pdev->mcopy_status_nbuf) {
+		/* For M_COPY mode only one msdu per ppdu is sent to upper layer*/
+		if (pdev->mcopy_mode == M_COPY) {
+			if (pdev->m_copy_id.rx_ppdu_id ==
+			    ppdu_info->com_info.ppdu_id)
+				goto end1;
+		}
 
-	if (qdf_unlikely(!ppdu_info->com_info.mpdu_cnt)) {
-		qdf_nbuf_free(status_nbuf);
-		return;
+		if (ppdu_info->is_fcs_passed) {
+			nbuf_clone = qdf_nbuf_clone(pdev->mcopy_status_nbuf);
+			if (!nbuf_clone) {
+				QDF_TRACE(QDF_MODULE_ID_TXRX,
+					  QDF_TRACE_LEVEL_ERROR,
+					  "Failed to clone nbuf",
+					  __func__, __LINE__);
+				goto end1;
+			}
+
+			pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id;
+			dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc,
+					     nbuf_clone,
+					     HTT_INVALID_PEER,
+					     WDI_NO_VAL, pdev->pdev_id);
+			ppdu_info->is_fcs_passed = false;
+		}
+end1:
+		qdf_nbuf_free(pdev->mcopy_status_nbuf);
+		pdev->mcopy_status_nbuf = NULL;
 	}
-	/* Add buffers to queue until we receive
-	 * HAL_TLV_STATUS_PPDU_DONE
+
+	/* If the MPDU end tlv and RX header are received in different buffers,
+	 * preserve the RX header as the fcs status will be received in MPDU
+	 * end tlv in next buffer. So, cache the buffer to be processd in next
+	 * iteration
 	 */
-	dp_rx_handle_ppdu_status_buf(pdev, ppdu_info, status_nbuf);
+	if ((ppdu_info->fcs_ok_cnt + ppdu_info->fcs_err_cnt) !=
+	    ppdu_info->com_info.mpdu_cnt) {
+		pdev->mcopy_status_nbuf = qdf_nbuf_clone(status_nbuf);
+		if (pdev->mcopy_status_nbuf) {
+			mcopy_status = dp_rx_handle_mcopy_mode(
+							soc, pdev,
+							ppdu_info,
+							pdev->mcopy_status_nbuf,
+							ppdu_info->fcs_ok_cnt,
+							false);
+			if (mcopy_status == QDF_STATUS_SUCCESS) {
+				qdf_nbuf_free(pdev->mcopy_status_nbuf);
+				pdev->mcopy_status_nbuf = NULL;
+			}
+		}
+	}
+}
+#else
+static inline void
+dp_rx_mcopy_handle_last_mpdu(struct dp_soc *soc, struct dp_pdev *pdev,
+			     struct hal_rx_ppdu_info *ppdu_info,
+			     qdf_nbuf_t status_nbuf)
+{
+}
+#endif
+
+/**
+ * dp_rx_mcopy_process_ppdu_info() - update mcopy ppdu info
+ * @ppdu_info: structure for rx ppdu ring
+ * @tlv_status: processed TLV status
+ *
+ * Return: void
+ */
+#ifdef FEATURE_PERPKT_INFO
+static inline void
+dp_rx_mcopy_process_ppdu_info(struct dp_pdev *pdev,
+			      struct hal_rx_ppdu_info *ppdu_info,
+			      uint32_t tlv_status)
+{
+	if (!pdev->mcopy_mode)
+		return;
 
-	/* If tlv_status is PPDU_DONE, process rx_ppdu_buf_q
-	 * and devliver fcs_ok msdu buffer
+	/* The fcs status is received in MPDU end tlv. If the RX header
+	 * and its MPDU end tlv are received in different status buffer then
+	 * to process that header ppdu_info->is_fcs_passed is used.
+	 * If end tlv is received in next status buffer then com_info.mpdu_cnt
+	 * will be 0 at the time of receiving MPDU end tlv and we update the
+	 * is_fcs_passed flag based on ppdu_info->fcs_err.
 	 */
-	if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
-		if (qdf_unlikely(ppdu_info->com_info.mpdu_cnt !=
-			(ppdu_info->com_info.mpdu_cnt_fcs_ok +
-			 ppdu_info->com_info.mpdu_cnt_fcs_err))) {
-			qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q);
+	if (tlv_status != HAL_TLV_STATUS_MPDU_END)
+		return;
+
+	if (!ppdu_info->fcs_err) {
+		if (ppdu_info->fcs_ok_cnt >
+		    HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER) {
+			dp_err("No. of MPDUs(%d) per status buff exceeded",
+					ppdu_info->fcs_ok_cnt);
 			return;
 		}
-		/* Get rx ppdu status buffer having fcs ok msdu */
-		status_nbuf = dp_rx_get_fcs_ok_msdu(pdev, ppdu_info);
-		if (status_nbuf) {
-			mcopy_status = dp_rx_handle_mcopy_mode(soc, pdev,
-							       ppdu_info,
-							       status_nbuf);
-			if (mcopy_status == QDF_STATUS_SUCCESS)
-				qdf_nbuf_free(status_nbuf);
+		if (ppdu_info->com_info.mpdu_cnt)
+			ppdu_info->fcs_ok_cnt++;
+		else
+			ppdu_info->is_fcs_passed = true;
+	} else {
+		if (ppdu_info->com_info.mpdu_cnt)
+			ppdu_info->fcs_err_cnt++;
+		else
+			ppdu_info->is_fcs_passed = false;
+	}
+}
+#else
+static inline void
+dp_rx_mcopy_process_ppdu_info(struct dp_pdev *pdev,
+			      struct hal_rx_ppdu_info *ppdu_info,
+			      uint32_t tlv_status)
+{
+}
+#endif
+
+#ifdef FEATURE_PERPKT_INFO
+static inline void
+dp_rx_process_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev,
+			 struct hal_rx_ppdu_info *ppdu_info,
+			 uint32_t tlv_status,
+			 qdf_nbuf_t status_nbuf)
+{
+	QDF_STATUS mcopy_status;
+	qdf_nbuf_t nbuf_clone = NULL;
+	uint8_t fcs_ok_mpdu_cnt = 0;
+
+	dp_rx_mcopy_handle_last_mpdu(soc, pdev, ppdu_info, status_nbuf);
+
+	if (qdf_unlikely(!ppdu_info->com_info.mpdu_cnt))
+		goto end;
+
+	if (qdf_unlikely(!ppdu_info->fcs_ok_cnt))
+		goto end;
+
+	/* For M_COPY mode only one msdu per ppdu is sent to upper layer*/
+	if (pdev->mcopy_mode == M_COPY)
+		ppdu_info->fcs_ok_cnt = 1;
+
+	while (fcs_ok_mpdu_cnt < ppdu_info->fcs_ok_cnt) {
+		nbuf_clone = qdf_nbuf_clone(status_nbuf);
+		if (!nbuf_clone) {
+			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+				  "Failed to clone nbuf",
+				  __func__, __LINE__);
+			goto end;
 		}
+
+		mcopy_status = dp_rx_handle_mcopy_mode(soc, pdev,
+						       ppdu_info,
+						       nbuf_clone,
+						       fcs_ok_mpdu_cnt,
+						       true);
+
+		if (mcopy_status == QDF_STATUS_SUCCESS)
+			qdf_nbuf_free(nbuf_clone);
+
+		fcs_ok_mpdu_cnt++;
 	}
+end:
+	qdf_nbuf_free(status_nbuf);
+	ppdu_info->fcs_ok_cnt = 0;
+	ppdu_info->fcs_err_cnt = 0;
+	ppdu_info->com_info.mpdu_cnt = 0;
+	qdf_mem_zero(&ppdu_info->ppdu_msdu_info,
+		     HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER
+		     * sizeof(struct hal_rx_msdu_payload_info));
+
 }
 #else
 static inline void
@@ -1534,6 +1614,10 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id,
 					status_nbuf, ppdu_info,
 					&nbuf_used);
 
+				dp_rx_mcopy_process_ppdu_info(pdev,
+							      ppdu_info,
+							      tlv_status);
+
 				rx_tlv = hal_rx_status_get_next_tlv(rx_tlv);
 
 				if ((rx_tlv - rx_tlv_start) >=
@@ -2103,7 +2187,6 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev, int ring_id) {
 		return status;
 
 	qdf_nbuf_queue_init(&pdev->rx_status_q);
-	qdf_nbuf_queue_init(&pdev->rx_ppdu_buf_q);
 
 	pdev->mon_ppdu_status = DP_PPDU_STATUS_START;
 

+ 11 - 5
dp/wifi3.0/dp_types.h

@@ -123,6 +123,15 @@ enum rx_pktlog_mode {
 };
 #endif
 
+/* enum m_copy_mode - Available mcopy mode
+ *
+ */
+enum m_copy_mode {
+	M_COPY_DISABLED = 0,
+	M_COPY = 2,
+	M_COPY_EXTENDED = 4,
+};
+
 struct msdu_list {
 	qdf_nbuf_t head;
 	qdf_nbuf_t tail;
@@ -1735,7 +1744,7 @@ struct dp_pdev {
 
 	bool tx_sniffer_enable;
 	/* mirror copy mode */
-	bool mcopy_mode;
+	enum m_copy_mode mcopy_mode;
 	bool cfr_rcc_mode;
 	bool enable_reap_timer_non_pkt;
 	bool bpr_enable;
@@ -1845,10 +1854,6 @@ struct dp_pdev {
 
 	uint32_t *ppdu_tlv_buf; /* Buffer to hold HTT ppdu stats TLVs*/
 
-	/* nbuf queue to maintain rx ppdu status buffer
-	 * belonging to one ppdu
-	 */
-	qdf_nbuf_queue_t rx_ppdu_buf_q;
 #ifdef WLAN_SUPPORT_RX_FLOW_TAG
 	/**
 	 * Pointer to DP Flow FST at SOC level if
@@ -1877,6 +1882,7 @@ struct dp_pdev {
 	 */
 	struct hal_rx_mon_desc_info *mon_desc;
 #endif
+	qdf_nbuf_t mcopy_status_nbuf;
 };
 
 struct dp_peer;

+ 9 - 4
hal/wifi3.0/hal_api_mon.h

@@ -161,6 +161,7 @@
 /* Max MPDUs per status buffer */
 #define HAL_RX_MAX_MPDU 256
 #define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5)
+#define HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER 16
 
 /* Max pilot count */
 #define HAL_RX_MAX_SU_EVM_COUNT 32
@@ -476,12 +477,10 @@ struct hal_rx_ppdu_common_info {
  * struct hal_rx_msdu_payload_info - msdu payload info
  * @first_msdu_payload: pointer to first msdu payload
  * @payload_len: payload len
- * @nbuf: status network buffer to which msdu belongs to
  */
 struct hal_rx_msdu_payload_info {
 	uint8_t *first_msdu_payload;
 	uint32_t payload_len;
-	qdf_nbuf_t nbuf;
 };
 
 /**
@@ -630,8 +629,14 @@ struct hal_rx_ppdu_info {
 	/* Id to indicate how to process mpdu */
 	uint8_t sw_frame_group_id;
 	struct hal_rx_ppdu_msdu_info rx_msdu_info[HAL_MAX_UL_MU_USERS];
-	/* first msdu payload for all mpdus in ppdu */
-	struct hal_rx_msdu_payload_info ppdu_msdu_info[HAL_RX_MAX_MPDU];
+	/* fcs passed mpdu count in rx monitor status buffer */
+	uint8_t fcs_ok_cnt;
+	/* fcs error mpdu count in rx monitor status buffer */
+	uint8_t fcs_err_cnt;
+	/* MPDU FCS passed */
+	bool is_fcs_passed;
+	/* first msdu payload for all mpdus in rx monitor status buffer */
+	struct hal_rx_msdu_payload_info ppdu_msdu_info[HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER];
 	/* evm info */
 	struct hal_rx_su_evm_info evm_info;
 	/**

+ 7 - 6
hal/wifi3.0/hal_generic_api.h

@@ -1513,19 +1513,20 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo,
 	case WIFIRX_HEADER_E:
 	{
 		struct hal_rx_ppdu_common_info *com_info = &ppdu_info->com_info;
-		uint16_t mpdu_cnt = com_info->mpdu_cnt;
 
-		if (mpdu_cnt >= HAL_RX_MAX_MPDU) {
-			hal_alert("Number of MPDUs per PPDU exceeded");
+		if (ppdu_info->fcs_ok_cnt >=
+		    HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER) {
+			hal_err("Number of MPDUs(%d) per status buff exceeded",
+				ppdu_info->fcs_ok_cnt);
 			break;
 		}
+
 		/* Update first_msdu_payload for every mpdu and increment
 		 * com_info->mpdu_cnt for every WIFIRX_HEADER_E TLV
 		 */
-		ppdu_info->ppdu_msdu_info[mpdu_cnt].first_msdu_payload =
+		ppdu_info->ppdu_msdu_info[ppdu_info->fcs_ok_cnt].first_msdu_payload =
 			rx_tlv;
-		ppdu_info->ppdu_msdu_info[mpdu_cnt].payload_len = tlv_len;
-		ppdu_info->ppdu_msdu_info[mpdu_cnt].nbuf = nbuf;
+		ppdu_info->ppdu_msdu_info[ppdu_info->fcs_ok_cnt].payload_len = tlv_len;
 		ppdu_info->msdu_info.first_msdu_payload = rx_tlv;
 		ppdu_info->msdu_info.payload_len = tlv_len;
 		ppdu_info->user_id = user_id;