Pārlūkot izejas kodu

qcacmn: Support per-ring CCE protocol tag stats

CCE stats are reported across rings today. Since HKv2 is a SMP, it
creates the possibility of missing stats when two or more CPUs are
updating the counters for the same protocol type. In order to avoid
this, we can either use locks or store stats on a per-CPU basis.
Since tagging happens on the core data path, locks are not preferred.
Instead, we use a per-ring counter, since each CPU operates on a REO
ring. Exception packets today go to Ring-0 (also normal rx Reo-0
go to Ring-0). Hence tags are maintained separately for exception
ring as well.

Change-Id: Ib01934619fb026bf64a8ac998eaec2d4df7f5a6e
CRs-Fixed: 2438143
Karunakar Dasineni 6 gadi atpakaļ
vecāks
revīzija
d8c7ad2228
6 mainītis faili ar 292 papildinājumiem un 172 dzēšanām
  1. 0 11
      dp/inc/cdp_txrx_stats_struct.h
  2. 93 44
      dp/wifi3.0/dp_main.c
  3. 2 1
      dp/wifi3.0/dp_rx.c
  4. 171 111
      dp/wifi3.0/dp_rx.h
  5. 5 4
      dp/wifi3.0/dp_rx_err.c
  6. 21 1
      dp/wifi3.0/dp_types.h

+ 0 - 11
dp/inc/cdp_txrx_stats_struct.h

@@ -1152,11 +1152,6 @@ struct cdp_htt_rx_pdev_stats {
  */
 #define RX_PROTOCOL_TAG_ALL 0xff
 
-#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
-struct cdp_pdev_rx_protocol_tag_stats {
-	uint32_t tag_ctr;
-};
-#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
 
 /* struct cdp_pdev_stats - pdev stats
@@ -1234,12 +1229,6 @@ struct cdp_pdev_stats {
 	/* Received wdi messages from fw */
 	uint32_t wdi_event[CDP_WDI_NUM_EVENTS];
 	struct cdp_tid_stats tid_stats;
-
-#if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \
-	defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG)
-	struct cdp_pdev_rx_protocol_tag_stats
-			rx_protocol_tag_stats[RX_PROTOCOL_TAG_MAX];
-#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 };
 
 #ifndef BIG_ENDIAN_HOST

+ 93 - 44
dp/wifi3.0/dp_main.c

@@ -9557,6 +9557,95 @@ dp_enable_peer_based_pktlog(
 }
 
 #ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
+#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
+/**
+ * dp_summarize_tag_stats - sums up the given protocol type's counters
+ * across all the rings and dumps the same
+ * @pdev_handle: cdp_pdev handle
+ * @protocol_type: protocol type for which stats should be displayed
+ *
+ * Return: none
+ */
+static uint64_t dp_summarize_tag_stats(struct cdp_pdev *pdev_handle,
+				       uint16_t protocol_type)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
+	uint8_t ring_idx;
+	uint64_t total_tag_cnt = 0;
+
+	for (ring_idx = 0; ring_idx < MAX_REO_DEST_RINGS; ring_idx++) {
+		total_tag_cnt +=
+		pdev->reo_proto_tag_stats[ring_idx][protocol_type].tag_ctr;
+	}
+	total_tag_cnt += pdev->rx_err_proto_tag_stats[protocol_type].tag_ctr;
+	DP_PRINT_STATS("ProtoID: %d, Tag: %u Tagged MSDU cnt: %llu",
+		       protocol_type,
+		       pdev->rx_proto_tag_map[protocol_type].tag,
+		       total_tag_cnt);
+	return total_tag_cnt;
+}
+
+/**
+ * dp_dump_pdev_rx_protocol_tag_stats - dump the number of packets tagged for
+ * given protocol type (RX_PROTOCOL_TAG_ALL indicates for all protocol)
+ * @pdev_handle: cdp_pdev handle
+ * @protocol_type: protocol type for which stats should be displayed
+ *
+ * Return: none
+ */
+static void
+dp_dump_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle,
+				   uint16_t protocol_type)
+{
+	uint16_t proto_idx;
+
+	if (protocol_type != RX_PROTOCOL_TAG_ALL &&
+	    protocol_type >= RX_PROTOCOL_TAG_MAX) {
+		DP_PRINT_STATS("Invalid protocol type : %u", protocol_type);
+		return;
+	}
+
+	/* protocol_type in [0 ... RX_PROTOCOL_TAG_MAX] */
+	if (protocol_type != RX_PROTOCOL_TAG_ALL) {
+		dp_summarize_tag_stats(pdev_handle, protocol_type);
+		return;
+	}
+
+	/* protocol_type == RX_PROTOCOL_TAG_ALL */
+	for (proto_idx = 0; proto_idx < RX_PROTOCOL_TAG_MAX; proto_idx++)
+		dp_summarize_tag_stats(pdev_handle, proto_idx);
+}
+#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
+
+/**
+ * dp_reset_pdev_rx_protocol_tag_stats - resets the stats counters for
+ * given protocol type
+ * @pdev_handle: cdp_pdev handle
+ * @protocol_type: protocol type for which stats should be reset
+ *
+ * Return: none
+ */
+#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
+static void
+dp_reset_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle,
+				    uint16_t protocol_type)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
+	uint8_t ring_idx;
+
+	for (ring_idx = 0; ring_idx < MAX_REO_DEST_RINGS; ring_idx++)
+		pdev->reo_proto_tag_stats[ring_idx][protocol_type].tag_ctr = 0;
+	pdev->rx_err_proto_tag_stats[protocol_type].tag_ctr = 0;
+}
+#else
+static void
+dp_reset_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle,
+				    uint16_t protocol_type)
+{
+	/** Stub API  */
+}
+#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
+
 /**
  * dp_update_pdev_rx_protocol_tag - Add/remove a protocol tag that should be
  * applied to the desired protocol type packets
@@ -9582,62 +9671,22 @@ dp_update_pdev_rx_protocol_tag(struct cdp_pdev *pdev_handle,
 	 */
 	if (enable_rx_protocol_tag) {
 		/* Tagging for one or more protocols has been set by user */
-		pdev->rx_protocol_tagging_enabled = true;
+		pdev->is_rx_protocol_tagging_enabled = true;
 	} else {
 		/*
 		 * No protocols being tagged, disable feature till next add
 		 * operation
 		 */
-		pdev->rx_protocol_tagging_enabled = false;
+		pdev->is_rx_protocol_tagging_enabled = false;
 	}
 
-	if (tag == 0) {
-		/*
-		 * In case of tag deletion, clear the stats for given
-		 * protocol type.
-		 */
-		DP_STATS_UPD(pdev,
-			     rx_protocol_tag_stats[protocol_type].tag_ctr, 0);
-	}
+	/** Reset stats counter across all rings for given protocol */
+	dp_reset_pdev_rx_protocol_tag_stats(pdev_handle, protocol_type);
 
 	pdev->rx_proto_tag_map[protocol_type].tag = tag;
 
 	return QDF_STATUS_SUCCESS;
 }
-
-#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
-static void
-dp_dump_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle,
-				   uint16_t protocol_type)
-{
-	struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
-
-	if (protocol_type != RX_PROTOCOL_TAG_ALL &&
-	    protocol_type >= RX_PROTOCOL_TAG_MAX) {
-		DP_PRINT_STATS("%s : Invalid protocol type : %u\n",
-			       __func__, protocol_type);
-		return;
-	}
-
-	if (protocol_type == RX_PROTOCOL_TAG_ALL) {
-		uint8_t protocol_index = 0;
-
-		for (protocol_index = 0; protocol_index < RX_PROTOCOL_TAG_MAX;
-		     protocol_index++) {
-			DP_PRINT_STATS("PROTO: %d, TAG: %u COUNT = %u\n",
-				       protocol_index,
-			pdev->rx_proto_tag_map[protocol_index].tag,
-			pdev->stats.
-				rx_protocol_tag_stats[protocol_index].tag_ctr);
-		}
-	} else {
-		DP_PRINT_STATS("PROTO: %d, TAG: %u COUNT = %u\n",
-			       protocol_type,
-		pdev->rx_proto_tag_map[protocol_type].tag,
-		pdev->stats.rx_protocol_tag_stats[protocol_type].tag_ctr);
-	}
-}
-#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
 
 static QDF_STATUS dp_peer_map_attach_wifi3(struct cdp_soc_t  *soc_hdl,

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

@@ -2022,7 +2022,8 @@ done:
 		dp_set_rx_queue(nbuf, ring_id);
 
 		/* Update the protocol tag in SKB based on CCE metadata */
-		dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr, true);
+		dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr,
+					  reo_ring_num, false, true);
 
 		/*
 		 * HW structures call this L3 header padding --

+ 171 - 111
dp/wifi3.0/dp_rx.h

@@ -941,169 +941,229 @@ static inline bool check_qwrap_multicast_loopback(struct dp_vdev *vdev,
 
 #if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \
 	defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG)
-/*
+/**
  * dp_rx_update_rx_protocol_tag_stats() - Increments the protocol tag stats
  *                                        for the given protocol type
- *
  * @soc: core txrx main context
- * @pdev: TXRX pdev context for which the stats should be incremented
+ * @pdev: TXRX pdev context for which stats should be incremented
  * @protocol_index: Protocol index for which the stats should be incremented
+ * @ring_index: REO ring number from which this tag was received.
+ *
+ * Since HKv2 is a SMP, two or more cores may simultaneously receive packets
+ * of same type, and hence attempt to increment counters for the same protocol
+ * type at the same time. This creates the possibility of missing stats.
+ *
+ * For example,  when two or more CPUs have each read the old tag value, V,
+ * for protocol type, P and each increment the value to V+1. Instead, the
+ * operations should have been  sequenced to achieve a final value of V+2.
+ *
+ * In order to avoid this scenario,  we can either use locks or store stats
+ * on a per-CPU basis. Since tagging happens in the core data path, locks
+ * are not preferred. Instead, we use a per-ring counter, since each CPU
+ * operates on a REO ring.
+ *
  * Return: void
  */
 static inline void dp_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
-						      uint16_t protocol_index)
+						      uint16_t protocol_index,
+						      uint16_t ring_index)
 {
-	DP_STATS_INC(pdev, rx_protocol_tag_stats[protocol_index].tag_ctr, 1);
+	if (ring_index >= MAX_REO_DEST_RINGS)
+		return;
+
+	pdev->reo_proto_tag_stats[ring_index][protocol_index].tag_ctr++;
 }
 #else
 static inline void dp_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
-						      uint16_t protocol_index)
+						      uint16_t protocol_index,
+						      uint16_t ring_index)
 {
 }
 #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 
-/*
+#if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \
+	defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG)
+/**
+ * dp_rx_update_rx_err_protocol_tag_stats() - Increments the protocol tag stats
+ *                                        for the given protocol type
+ *                                        received from exception ring
+ * @soc: core txrx main context
+ * @pdev: TXRX pdev context for which stats should be incremented
+ * @protocol_index: Protocol index for which the stats should be incremented
+ *
+ * In HKv2, all exception packets are received on Ring-0 (along with normal
+ * Rx). Hence tags are maintained separately for exception ring as well.
+ *
+ * Return: void
+ */
+static inline
+void dp_rx_update_rx_err_protocol_tag_stats(struct dp_pdev *pdev,
+					    uint16_t protocol_index)
+{
+	pdev->rx_err_proto_tag_stats[protocol_index].tag_ctr++;
+}
+#else
+static inline
+void dp_rx_update_rx_err_protocol_tag_stats(struct dp_pdev *pdev,
+					    uint16_t protocol_index)
+{
+}
+#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
+/**
  * dp_rx_update_protocol_tag() - Reads CCE metadata from the RX MSDU end TLV
  *                              and set the corresponding tag in QDF packet
- *
- * @soc           : core txrx main context
- * @vdev          : vdev on which the packet is received
- * @nbuf          : QDF packet buffer on which the protocol tag should be set
- * @rx_tlv_hdr    : base address where the RX TLVs starts
- * @update_stats  : Flag to indicate whether to update stats or not
- * Return         : void
+ * @soc: core txrx main context
+ * @vdev: vdev on which the packet is received
+ * @nbuf: QDF pkt buffer on which the protocol tag should be set
+ * @rx_tlv_hdr: rBbase address where the RX TLVs starts
+ * @ring_index: REO ring number, not used for error & monitor ring
+ * @is_reo_exception: flag to indicate if rx from REO ring or exception ring
+ * @is_update_stats: flag to indicate whether to update stats or not
+ * Return: void
  */
 #ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
 static inline void
 dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev,
 			  qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
-			  bool update_stats)
+			  uint16_t ring_index,
+			  bool is_reo_exception, bool is_update_stats)
 {
 	uint16_t cce_metadata = RX_PROTOCOL_TAG_START_OFFSET;
 	bool     cce_match = false;
-	struct   dp_pdev *pdev = vdev->pdev;
+	struct   dp_pdev *pdev;
 	uint16_t protocol_tag = 0;
 
-	if (qdf_unlikely(pdev->rx_protocol_tagging_enabled)) {
-		/*
-		 * In case of raw frames, rx_attention and rx_msdu_end tlv
-		 * may be stale or invalid. Do not tag such frames.
-		 * Default decap_type is set to ethernet for monitor vdev,
-		 * therefore, cannot check decap_type for monitor mode.
-		 * We will call this only for eth frames from dp_rx_mon_dest.c.
-		 */
-		if (qdf_unlikely((pdev->monitor_vdev &&
-				  pdev->monitor_vdev == vdev) ||
-		    (vdev->rx_decap_type ==  htt_cmn_pkt_type_ethernet))) {
-			/*
-			 * Check whether HW has filled in the CCE metadata in
-			 * this packet, if not filled, just return
-			 */
-			if (qdf_unlikely(
-			    hal_rx_msdu_cce_match_get(rx_tlv_hdr))) {
-				cce_match = true;
-				/* Get the cce_metadata from RX MSDU TLV */
-				cce_metadata =
-				    (hal_rx_msdu_cce_metadata_get(rx_tlv_hdr) &
-				     RX_MSDU_END_16_CCE_METADATA_MASK);
-				/*
-				 * Received CCE metadata should be within the
-				 * valid limits
-				 */
-				qdf_assert_always((cce_metadata >=
-					RX_PROTOCOL_TAG_START_OFFSET) &&
-					(cce_metadata <
-					(RX_PROTOCOL_TAG_START_OFFSET +
-						RX_PROTOCOL_TAG_MAX)));
-
-				/*
-				 * The CCE metadata received is just the
-				 * packet_type + RX_PROTOCOL_TAG_START_OFFSET
-				 */
-				cce_metadata -= RX_PROTOCOL_TAG_START_OFFSET;
+	if (qdf_unlikely(!vdev))
+		return;
 
-				/*
-				 * Update the QDF packet with the user-specified
-				 * tag/metadata by looking up tag value for
-				 * received protocol type.
-				 */
-				protocol_tag =
-				    pdev->rx_proto_tag_map[cce_metadata].tag;
-				qdf_nbuf_set_rx_protocol_tag(nbuf,
-							     protocol_tag);
-				if (qdf_unlikely(update_stats))
-					dp_rx_update_rx_protocol_tag_stats(
-							pdev, cce_metadata);
-			}
-		}
+	pdev = vdev->pdev;
+
+	if (qdf_likely(!pdev->is_rx_protocol_tagging_enabled))
+		return;
 
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
-			  "Seq:%u decap:%u CCE Match:%d ProtoID:%u Tag:%u US:%d",
-			  hal_rx_get_rx_sequence(rx_tlv_hdr),
-			  vdev->rx_decap_type, cce_match, cce_metadata,
-			  protocol_tag, update_stats);
+	/*
+	 * In case of raw frames, rx_attention and rx_msdu_end tlv
+	 * may be stale or invalid. Do not tag such frames.
+	 * Default decap_type is set to ethernet for monitor vdev,
+	 * therefore, cannot check decap_type for monitor mode.
+	 * We will call this only for eth frames from dp_rx_mon_dest.c.
+	 */
+	if (qdf_likely(!(pdev->monitor_vdev && pdev->monitor_vdev == vdev) &&
+		       (vdev->rx_decap_type !=  htt_cmn_pkt_type_ethernet)))
+		return;
+
+	/*
+	 * Check whether HW has filled in the CCE metadata in
+	 * this packet, if not filled, just return
+	 */
+	if (qdf_likely(!hal_rx_msdu_cce_match_get(rx_tlv_hdr)))
+		return;
+
+	cce_match = true;
+	/* Get the cce_metadata from RX MSDU TLV */
+	cce_metadata = (hal_rx_msdu_cce_metadata_get(rx_tlv_hdr) &
+			RX_MSDU_END_16_CCE_METADATA_MASK);
+	/*
+	 * Received CCE metadata should be within the
+	 * valid limits
+	 */
+	qdf_assert_always((cce_metadata >= RX_PROTOCOL_TAG_START_OFFSET) &&
+			  (cce_metadata < (RX_PROTOCOL_TAG_START_OFFSET +
+			   RX_PROTOCOL_TAG_MAX)));
+
+	/*
+	 * The CCE metadata received is just the
+	 * packet_type + RX_PROTOCOL_TAG_START_OFFSET
+	 */
+	cce_metadata -= RX_PROTOCOL_TAG_START_OFFSET;
+
+	/*
+	 * Update the QDF packet with the user-specified
+	 * tag/metadata by looking up tag value for
+	 * received protocol type.
+	 */
+	protocol_tag = pdev->rx_proto_tag_map[cce_metadata].tag;
+	qdf_nbuf_set_rx_protocol_tag(nbuf, protocol_tag);
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
+		  "Seq:%u decap:%u CCE Match:%d ProtoID:%u Tag:%u US:%d",
+		  hal_rx_get_rx_sequence(rx_tlv_hdr),
+		  vdev->rx_decap_type, cce_match, cce_metadata,
+		  protocol_tag, is_update_stats);
+
+	if (qdf_likely(!is_update_stats))
+		return;
+
+	if (qdf_unlikely(is_reo_exception)) {
+		dp_rx_update_rx_err_protocol_tag_stats(pdev,
+						       cce_metadata);
+	} else {
+		dp_rx_update_rx_protocol_tag_stats(pdev,
+						   cce_metadata,
+						   ring_index);
 	}
+
 }
 #else
 static inline void
 dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev,
 			  qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
-			  bool update_stats)
+			  uint16_t ring_index,
+			  bool is_reo_exception, bool is_update_stats)
 {
 	/* Stub API */
 }
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
 
-/*
+/**
  * dp_rx_mon_update_protocol_tag() - Performs necessary checks for monitor mode
  *				and then tags appropriate packets
- * @soc           : core txrx main context
- * @vdev          : pdev on which packet is received
- * @msdu          : QDF packet buffer on which the protocol tag should be set
- * @rx_desc       : base address where the RX TLVs start
- * Return         : void
+ * @soc: core txrx main context
+ * @vdev: pdev on which packet is received
+ * @msdu: QDF packet buffer on which the protocol tag should be set
+ * @rx_desc: base address where the RX TLVs start
+ * Return: void
  */
 #ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
 static inline
 void dp_rx_mon_update_protocol_tag(struct dp_soc *soc, struct dp_pdev *dp_pdev,
 				   qdf_nbuf_t msdu, void *rx_desc)
 {
-	/*
-	 * Update the protocol tag in SKB for packets received on BSS.
-	 * Do not update tag stats since it would double actual received count
-	 */
-	if (qdf_unlikely(dp_pdev->rx_protocol_tagging_enabled &&
-			 dp_pdev->monitor_vdev &&
-			 (1 == dp_pdev->ppdu_info.rx_status.rxpcu_filter_pass)
-			 )) {
-		uint32_t msdu_ppdu_id =
-		    HAL_RX_HW_DESC_GET_PPDUID_GET(rx_desc);
-
-		if (msdu_ppdu_id !=
-		    dp_pdev->ppdu_info.com_info.ppdu_id) {
-			QDF_TRACE(
-			  QDF_MODULE_ID_DP,
+	uint32_t msdu_ppdu_id = 0;
+	struct mon_rx_status *mon_recv_status;
+
+	if (qdf_likely(!dp_pdev->is_rx_protocol_tagging_enabled))
+		return;
+
+	if (qdf_likely(!dp_pdev->monitor_vdev))
+		return;
+
+	if (qdf_likely(1 != dp_pdev->ppdu_info.rx_status.rxpcu_filter_pass))
+		return;
+
+	msdu_ppdu_id = HAL_RX_HW_DESC_GET_PPDUID_GET(rx_desc);
+
+	if (msdu_ppdu_id != dp_pdev->ppdu_info.com_info.ppdu_id) {
+		QDF_TRACE(QDF_MODULE_ID_DP,
 			  QDF_TRACE_LEVEL_ERROR,
 			  "msdu_ppdu_id=%x,com_info.ppdu_id=%x",
 			  msdu_ppdu_id,
 			  dp_pdev->ppdu_info.com_info.ppdu_id);
-		} else {
-			struct mon_rx_status *pmon_rx_status;
-
-			pmon_rx_status =
-				&dp_pdev->ppdu_info.rx_status;
-			if (pmon_rx_status->
-			    frame_control_info_valid &&
-			    ((pmon_rx_status->frame_control &
-			    IEEE80211_FC0_TYPE_MASK) ==
-			    IEEE80211_FC0_TYPE_DATA)) {
-				dp_rx_update_protocol_tag(
-				  soc,
-				  dp_pdev->monitor_vdev,
-				  msdu,
-				  rx_desc, false);
-			}
-		}
+		return;
+	}
+
+	/*
+	 * Update the protocol tag in SKB for packets received on BSS.
+	 * Do not update tag stats since it would double actual received count
+	 */
+	mon_recv_status = &dp_pdev->ppdu_info.rx_status;
+	if (mon_recv_status->frame_control_info_valid &&
+	    ((mon_recv_status->frame_control & IEEE80211_FC0_TYPE_MASK) ==
+	      IEEE80211_FC0_TYPE_DATA)) {
+		dp_rx_update_protocol_tag(soc,
+					  dp_pdev->monitor_vdev,
+					  msdu, rx_desc,
+					  MAX_REO_DEST_RINGS,
+					  false, false);
 	}
 }
 #else

+ 5 - 4
dp/wifi3.0/dp_rx_err.c

@@ -820,8 +820,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf,
 			 * Update the protocol tag in SKB based on
 			 * CCE metadata
 			 */
-			dp_rx_update_protocol_tag(soc, vdev, nbuf,
-						  rx_tlv_hdr, true);
+			dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr,
+						  EXCEPTION_DEST_RING_ID,
+						  true, true);
 
 			if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(
 						rx_tlv_hdr) &&
@@ -1000,8 +1001,8 @@ process_rx:
 		dp_rx_deliver_raw(vdev, nbuf, peer);
 	} else {
 		/* Update the protocol tag in SKB based on CCE metadata */
-		dp_rx_update_protocol_tag(soc, vdev, nbuf,
-					  rx_tlv_hdr, true);
+		dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr,
+					  EXCEPTION_DEST_RING_ID, true, true);
 		DP_STATS_INC(peer, rx.to_stack.num, 1);
 		vdev->osif_rx(vdev->osif_vdev, nbuf);
 	}

+ 21 - 1
dp/wifi3.0/dp_types.h

@@ -82,6 +82,7 @@
 #define MAX_TXDESC_POOLS 4
 #define MAX_RXDESC_POOLS 4
 #define MAX_REO_DEST_RINGS 4
+#define EXCEPTION_DEST_RING_ID 0
 #define MAX_TCL_DATA_RINGS 4
 #define MAX_IDLE_SCATTER_BUFS 16
 #define DP_MAX_IRQ_PER_CONTEXT 12
@@ -1139,6 +1140,13 @@ struct rx_protocol_tag_map {
 	/* This is the user configured tag for the said protocol type */
 	uint16_t tag;
 };
+
+#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
+struct rx_protocol_tag_stats {
+	uint32_t tag_ctr;
+};
+#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
+
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
 
 /* PDEV level structure for data path */
@@ -1442,13 +1450,25 @@ struct dp_pdev {
 	 * Run time enabled when the first protocol tag is added,
 	 * run time disabled when the last protocol tag is deleted
 	 */
-	bool  rx_protocol_tagging_enabled;
+	bool  is_rx_protocol_tagging_enabled;
 
 	/*
 	 * The protocol type is used as array index to save
 	 * user provided tag info
 	 */
 	struct rx_protocol_tag_map rx_proto_tag_map[RX_PROTOCOL_TAG_MAX];
+
+#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
+	/*
+	 * Track msdus received from each reo ring separately to avoid
+	 * simultaneous writes from different core
+	 */
+	struct rx_protocol_tag_stats
+		reo_proto_tag_stats[MAX_REO_DEST_RINGS][RX_PROTOCOL_TAG_MAX];
+	/* Track msdus received from expection ring separately */
+	struct rx_protocol_tag_stats
+		rx_err_proto_tag_stats[RX_PROTOCOL_TAG_MAX];
+#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
 #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
 };