diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 1d351ab704..8eddcea8ed 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/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 diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 64762a3d8f..21a2733440 100644 --- a/dp/wifi3.0/dp_main.c +++ b/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, diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 888bdb4c13..87d8d529d6 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/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 -- diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 15e567ec14..10f5b53605 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/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))); + if (qdf_unlikely(!vdev)) + return; - /* - * The CCE metadata received is just the - * packet_type + RX_PROTOCOL_TAG_START_OFFSET - */ - cce_metadata -= RX_PROTOCOL_TAG_START_OFFSET; + pdev = vdev->pdev; - /* - * 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); - } - } + 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); + uint32_t msdu_ppdu_id = 0; + struct mon_rx_status *mon_recv_status; - if (msdu_ppdu_id != - dp_pdev->ppdu_info.com_info.ppdu_id) { - QDF_TRACE( - QDF_MODULE_ID_DP, + 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; + return; + } - 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); - } - } + /* + * 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 diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index a7be2808f1..367d66c85e 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/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); } diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index c8c3564851..81e1e8d1e4 100644 --- a/dp/wifi3.0/dp_types.h +++ b/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 */ };