فهرست منبع

qcacmn: Changes for vdev and pdev stats

Changes for vdev and pdev stats as per the new peer stats
re-organization architecture.

Change-Id: I48f9fb4b0915c40f4add83f2e2dd074cc97874fd
CRs-Fixed: 3092123
Harsh Kumar Bijlani 3 سال پیش
والد
کامیت
d8e05be641

+ 47 - 0
dp/wifi3.0/dp_internal.h

@@ -247,6 +247,21 @@ void dp_monitor_peer_get_stats(struct dp_soc *soc, struct dp_peer *peer,
 {
 }
 
+static inline
+void dp_monitor_invalid_peer_update_pdev_stats(struct dp_soc *soc,
+					       struct dp_pdev *pdev)
+{
+}
+
+static inline
+QDF_STATUS dp_monitor_peer_get_stats_param(struct dp_soc *soc,
+					   struct dp_peer *peer,
+					   enum cdp_peer_stats_type type,
+					   cdp_peer_stats_param_t *buf)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
 static inline QDF_STATUS dp_monitor_pdev_init(struct dp_pdev *pdev)
 {
 	return QDF_STATUS_SUCCESS;
@@ -1235,6 +1250,28 @@ void dp_txrx_clear_tso_stats(struct dp_soc *soc)
 }
 #endif /* FEATURE_TSO_STATS */
 
+/* dp_txrx_get_peer_per_pkt_stats_param() - Get peer per pkt stats param
+ * @peer: DP peer handle
+ * @type: Requested stats type
+ * @ buf: Buffer to hold the value
+ *
+ * Return: status success/failure
+ */
+QDF_STATUS dp_txrx_get_peer_per_pkt_stats_param(struct dp_peer *peer,
+						enum cdp_peer_stats_type type,
+						cdp_peer_stats_param_t *buf);
+
+/* dp_txrx_get_peer_extd_stats_param() - Get peer extd stats param
+ * @peer: DP peer handle
+ * @type: Requested stats type
+ * @ buf: Buffer to hold the value
+ *
+ * Return: status success/failure
+ */
+QDF_STATUS dp_txrx_get_peer_extd_stats_param(struct dp_peer *peer,
+					     enum cdp_peer_stats_type type,
+					     cdp_peer_stats_param_t *buf);
+
 #define DP_HTT_T2H_HP_PIPE 5
 /**
  * dp_update_pdev_stats(): Update the pdev stats
@@ -1284,6 +1321,16 @@ void dp_update_vdev_stats(struct dp_soc *soc,
 			  struct dp_peer *srcobj,
 			  void *arg);
 
+/**
+ * dp_update_vdev_stats_on_peer_unmap() - Update the vdev stats on peer unmap
+ * @vdev: DP_VDEV handle
+ * @peer: DP_PEER handle
+ *
+ * Return: None
+ */
+void dp_update_vdev_stats_on_peer_unmap(struct dp_vdev *vdev,
+					struct dp_peer *peer);
+
 #define DP_UPDATE_STATS(_tgtobj, _srcobj)	\
 	do {				\
 		uint8_t i;		\

+ 11 - 52
dp/wifi3.0/dp_main.c

@@ -8581,7 +8581,7 @@ void dp_aggregate_pdev_stats(struct dp_pdev *pdev)
 	qdf_mem_zero(&pdev->stats.rx_i, sizeof(pdev->stats.rx_i));
 
 	if (dp_monitor_is_enable_mcopy_mode(pdev))
-		DP_UPDATE_STATS(pdev, pdev->invalid_peer);
+		dp_monitor_invalid_peer_update_pdev_stats(soc, pdev);
 
 	qdf_spin_lock_bh(&pdev->vdev_list_lock);
 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
@@ -10237,7 +10237,7 @@ dp_txrx_get_peer_stats_param(struct cdp_soc_t *soc, uint8_t vdev_id,
 			     uint8_t *peer_mac, enum cdp_peer_stats_type type,
 			     cdp_peer_stats_param_t *buf)
 {
-	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+	QDF_STATUS ret;
 	struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc,
 						      peer_mac, 0, vdev_id,
 						      DP_MOD_ID_CDP);
@@ -10246,57 +10246,16 @@ dp_txrx_get_peer_stats_param(struct cdp_soc_t *soc, uint8_t vdev_id,
 		dp_peer_err("%pK: Invalid Peer for Mac " QDF_MAC_ADDR_FMT,
 			    soc, QDF_MAC_ADDR_REF(peer_mac));
 		return QDF_STATUS_E_FAILURE;
-	} else if (type < cdp_peer_stats_max) {
-		switch (type) {
-		case cdp_peer_tx_ucast:
-			buf->tx_ucast = peer->stats.tx.ucast;
-			break;
-		case cdp_peer_tx_mcast:
-			buf->tx_mcast = peer->stats.tx.mcast;
-			break;
-		case cdp_peer_tx_rate:
-			buf->tx_rate = peer->stats.tx.tx_rate;
-			break;
-		case cdp_peer_tx_last_tx_rate:
-			buf->last_tx_rate = peer->stats.tx.last_tx_rate;
-			break;
-		case cdp_peer_tx_inactive_time:
-			buf->tx_inactive_time = peer->stats.tx.inactive_time;
-			break;
-		case cdp_peer_tx_ratecode:
-			buf->tx_ratecode = peer->stats.tx.tx_ratecode;
-			break;
-		case cdp_peer_tx_flags:
-			buf->tx_flags = peer->stats.tx.tx_flags;
-			break;
-		case cdp_peer_tx_power:
-			buf->tx_power = peer->stats.tx.tx_power;
-			break;
-		case cdp_peer_rx_rate:
-			buf->rx_rate = peer->stats.rx.rx_rate;
-			break;
-		case cdp_peer_rx_last_rx_rate:
-			buf->last_rx_rate = peer->stats.rx.last_rx_rate;
-			break;
-		case cdp_peer_rx_ratecode:
-			buf->rx_ratecode = peer->stats.rx.rx_ratecode;
-			break;
-		case cdp_peer_rx_ucast:
-			buf->rx_ucast = peer->stats.rx.unicast;
-			break;
-		case cdp_peer_rx_flags:
-			buf->rx_flags = peer->stats.rx.rx_flags;
-			break;
-		case cdp_peer_rx_avg_snr:
-			buf->rx_avg_snr = peer->stats.rx.avg_snr;
-			break;
-		default:
-			dp_peer_err("%pK: Invalid value", soc);
-			ret = QDF_STATUS_E_FAILURE;
-			break;
-		}
+	}
+
+	if (type >= cdp_peer_per_pkt_stats_min &&
+	    type < cdp_peer_per_pkt_stats_max) {
+		ret = dp_txrx_get_peer_per_pkt_stats_param(peer, type, buf);
+	} else if (type >= cdp_peer_extd_stats_min &&
+		   type < cdp_peer_extd_stats_max) {
+		ret = dp_txrx_get_peer_extd_stats_param(peer, type, buf);
 	} else {
-		dp_peer_err("%pK: Invalid value", soc);
+		dp_err("%pK: Invalid stat type requested", soc);
 		ret = QDF_STATUS_E_FAILURE;
 	}
 

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

@@ -2864,7 +2864,7 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id,
 	}
 
 	vdev = peer->vdev;
-	DP_UPDATE_STATS(vdev, peer);
+	dp_update_vdev_stats_on_peer_unmap(vdev, peer);
 
 	dp_peer_update_state(soc, peer, DP_PEER_STATE_INACTIVE);
 	dp_peer_unref_delete(peer, DP_MOD_ID_HTT);

+ 255 - 156
dp/wifi3.0/dp_stats.c

@@ -7204,28 +7204,171 @@ void dp_txrx_clear_tso_stats(struct dp_soc *soc)
 }
 #endif /* FEATURE_TSO_STATS */
 
+QDF_STATUS dp_txrx_get_peer_per_pkt_stats_param(struct dp_peer *peer,
+						enum cdp_peer_stats_type type,
+						cdp_peer_stats_param_t *buf)
+{
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+	struct dp_txrx_peer *txrx_peer;
+	struct dp_peer_per_pkt_stats *peer_stats;
+
+	txrx_peer = dp_get_txrx_peer(peer);
+	if (!txrx_peer)
+		return QDF_STATUS_E_FAILURE;
+
+	peer_stats = &txrx_peer->stats.per_pkt_stats;
+	switch (type) {
+	case cdp_peer_tx_ucast:
+		buf->tx_ucast = peer_stats->tx.ucast;
+		break;
+	case cdp_peer_tx_mcast:
+		buf->tx_mcast = peer_stats->tx.mcast;
+		break;
+	case cdp_peer_tx_inactive_time:
+		buf->tx_inactive_time = peer->stats.tx.inactive_time;
+		break;
+	case cdp_peer_rx_ucast:
+		buf->rx_ucast = peer_stats->rx.unicast;
+		break;
+	default:
+		ret = QDF_STATUS_E_FAILURE;
+		break;
+	}
+
+	return ret;
+}
+
+#ifdef QCA_ENHANCED_STATS_SUPPORT
+#ifdef WLAN_FEATURE_11BE_MLO
+QDF_STATUS dp_txrx_get_peer_extd_stats_param(struct dp_peer *peer,
+					     enum cdp_peer_stats_type type,
+					     cdp_peer_stats_param_t *buf)
+{
+	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
+	struct dp_soc *soc = peer->vdev->pdev->soc;
+
+	if (IS_MLO_DP_MLD_PEER(peer)) {
+		struct dp_peer *link_peer;
+		struct dp_soc *link_peer_soc;
+
+		link_peer = dp_get_primary_link_peer_by_id(soc, peer->peer_id,
+							   DP_MOD_ID_CDP);
+
+		if (link_peer) {
+			link_peer_soc = link_peer->vdev->pdev->soc;
+			ret = dp_monitor_peer_get_stats_param(link_peer_soc,
+							      link_peer,
+							      type, buf);
+			dp_peer_unref_delete(link_peer, DP_MOD_ID_CDP);
+		}
+		return ret;
+	} else {
+		return dp_monitor_peer_get_stats_param(soc, peer, type, buf);
+	}
+}
+#else
+QDF_STATUS dp_txrx_get_peer_extd_stats_param(struct dp_peer *peer,
+					     enum cdp_peer_stats_type type,
+					     cdp_peer_stats_param_t *buf)
+{
+	struct dp_soc *soc = peer->vdev->pdev->soc;
+
+	return dp_monitor_peer_get_stats_param(soc, peer, type, buf);
+}
+#endif
+#else
+QDF_STATUS dp_txrx_get_peer_extd_stats_param(struct dp_peer *peer,
+					     enum cdp_peer_stats_type type,
+					     cdp_peer_stats_param_t *buf)
+{
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+	struct dp_txrx_peer *txrx_peer;
+	struct dp_peer_extd_stats *peer_stats;
+
+	txrx_peer = dp_get_txrx_peer(peer);
+	if (!txrx_peer)
+		return QDF_STATUS_E_FAILURE;
+
+	peer_stats = &txrx_peer->stats.extd_stats;
+
+	switch (type) {
+	case cdp_peer_tx_rate:
+		buf->tx_rate = peer_stats->tx.tx_rate;
+		break;
+	case cdp_peer_tx_last_tx_rate:
+		buf->last_tx_rate = peer_stats->tx.last_tx_rate;
+		break;
+	case cdp_peer_tx_ratecode:
+		buf->tx_ratecode = peer_stats->tx.tx_ratecode;
+		break;
+	case cdp_peer_rx_rate:
+		buf->rx_rate = peer_stats->rx.rx_rate;
+		break;
+	case cdp_peer_rx_last_rx_rate:
+		buf->last_rx_rate = peer_stats->rx.last_rx_rate;
+		break;
+	case cdp_peer_rx_ratecode:
+		buf->rx_ratecode = peer_stats->rx.rx_ratecode;
+		break;
+	case cdp_peer_rx_avg_snr:
+		buf->rx_avg_snr = peer_stats->rx.avg_snr;
+		break;
+	case cdp_peer_rx_snr:
+		buf->rx_snr = peer_stats->rx.snr;
+		break;
+	default:
+		ret = QDF_STATUS_E_FAILURE;
+		break;
+	}
+
+	return ret;
+}
+#endif
+
 /**
- * dp_is_wds_extended(): Check if wds ext is enabled
- * @vdev: DP VDEV handle
+ * dp_is_wds_extended() - Check if wds ext is enabled
+ * @txrx_peer: DP txrx_peer handle
  *
  * return: true if enabled, false if not
  */
 #ifdef QCA_SUPPORT_WDS_EXTENDED
-static bool dp_is_wds_extended(struct dp_peer *peer)
+static inline
+bool dp_is_wds_extended(struct dp_txrx_peer *txrx_peer)
 {
 	if (qdf_atomic_test_bit(WDS_EXT_PEER_INIT_BIT,
-				&peer->wds_ext.init))
+				&txrx_peer->wds_ext.init))
 		return true;
 
 	return false;
 }
 #else
-static bool dp_is_wds_extended(struct dp_peer *peer)
+static inline
+bool dp_is_wds_extended(struct dp_txrx_peer *txrx_peer)
 {
 	return false;
 }
 #endif /* QCA_SUPPORT_WDS_EXTENDED */
 
+/**
+ * dp_peer_get_hw_txrx_stats_en() - Get value of hw_txrx_stats_en
+ * @txrx_peer: DP txrx_peer handle
+ *
+ * Return: true if enabled, false if not
+ */
+#ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
+static inline
+bool dp_peer_get_hw_txrx_stats_en(struct dp_txrx_peer *txrx_peer)
+{
+	return txrx_peer->hw_txrx_stats_en;
+}
+#else
+static inline
+bool dp_peer_get_hw_txrx_stats_en(struct dp_txrx_peer *txrx_peer)
+{
+	return false;
+}
+#endif
+
 #ifdef WLAN_FEATURE_11BE_MLO
 static inline struct dp_peer *dp_get_stats_peer(struct dp_peer *peer)
 {
@@ -7242,170 +7385,126 @@ static inline struct dp_peer *dp_get_stats_peer(struct dp_peer *peer)
 }
 #endif
 
-void dp_update_vdev_stats(struct dp_soc *soc,
-			  struct dp_peer *srcobj,
+/**
+ * dp_update_vdev_basic_stats() - Update vdev basic stats
+ * @txrx_peer: DP txrx_peer handle
+ * @tgtobj: Pointer to buffer for vdev stats
+ *
+ * Return: None
+ */
+static inline
+void dp_update_vdev_basic_stats(struct dp_txrx_peer *txrx_peer,
+				struct cdp_vdev_stats *tgtobj)
+{
+	if (qdf_unlikely(!txrx_peer || !tgtobj))
+		return;
+
+	if (!dp_peer_get_hw_txrx_stats_en(txrx_peer)) {
+		tgtobj->tx.comp_pkt.num += txrx_peer->comp_pkt.num;
+		tgtobj->tx.comp_pkt.bytes += txrx_peer->comp_pkt.bytes;
+		tgtobj->tx.tx_failed += txrx_peer->tx_failed;
+	}
+	tgtobj->rx.to_stack.num += txrx_peer->to_stack.num;
+	tgtobj->rx.to_stack.bytes += txrx_peer->to_stack.bytes;
+}
+
+#ifdef QCA_ENHANCED_STATS_SUPPORT
+void dp_update_vdev_stats(struct dp_soc *soc, struct dp_peer *srcobj,
 			  void *arg)
 {
-	struct cdp_vdev_stats *tgtobj = (struct cdp_vdev_stats *)arg;
-	uint8_t i;
-	uint8_t pream_type;
+	struct dp_txrx_peer *txrx_peer;
+	struct cdp_vdev_stats *vdev_stats = (struct cdp_vdev_stats *)arg;
+	struct dp_peer_per_pkt_stats *per_pkt_stats;
 
-	if (qdf_unlikely(dp_is_wds_extended(srcobj)))
+	txrx_peer = dp_get_txrx_peer(srcobj);
+	if (qdf_unlikely(!txrx_peer))
+		goto link_stats;
+
+	if (qdf_unlikely(dp_is_wds_extended(txrx_peer)))
 		return;
 
-	srcobj = dp_get_stats_peer(srcobj);
+	if (!dp_peer_is_primary_link_peer(srcobj))
+		goto link_stats;
 
-	for (pream_type = 0; pream_type < DOT11_MAX; pream_type++) {
-		for (i = 0; i < MAX_MCS; i++) {
-			tgtobj->tx.pkt_type[pream_type].
-				mcs_count[i] +=
-			srcobj->stats.tx.pkt_type[pream_type].
-				mcs_count[i];
-			tgtobj->rx.pkt_type[pream_type].
-				mcs_count[i] +=
-			srcobj->stats.rx.pkt_type[pream_type].
-				mcs_count[i];
-		}
-	}
+	dp_update_vdev_basic_stats(txrx_peer, vdev_stats);
 
-	for (i = 0; i < MAX_BW; i++) {
-		tgtobj->tx.bw[i] += srcobj->stats.tx.bw[i];
-		tgtobj->rx.bw[i] += srcobj->stats.rx.bw[i];
-	}
+	per_pkt_stats = &txrx_peer->stats.per_pkt_stats;
+	DP_UPDATE_PER_PKT_STATS(vdev_stats, per_pkt_stats);
 
-	for (i = 0; i < SS_COUNT; i++) {
-		tgtobj->tx.nss[i] += srcobj->stats.tx.nss[i];
-		tgtobj->rx.nss[i] += srcobj->stats.rx.nss[i];
-	}
+link_stats:
+	dp_monitor_peer_get_stats(soc, srcobj, vdev_stats, UPDATE_VDEV_STATS);
+}
 
-	for (i = 0; i < WME_AC_MAX; i++) {
-		tgtobj->tx.wme_ac_type[i] +=
-			srcobj->stats.tx.wme_ac_type[i];
-		tgtobj->rx.wme_ac_type[i] +=
-			srcobj->stats.rx.wme_ac_type[i];
-		tgtobj->tx.excess_retries_per_ac[i] +=
-			srcobj->stats.tx.excess_retries_per_ac[i];
-	}
+void dp_update_vdev_stats_on_peer_unmap(struct dp_vdev *vdev,
+					struct dp_peer *peer)
+{
+	struct dp_soc *soc = vdev->pdev->soc;
+	struct dp_txrx_peer *txrx_peer;
+	struct dp_peer_per_pkt_stats *per_pkt_stats;
+	struct cdp_vdev_stats *vdev_stats = &vdev->stats;
 
-	for (i = 0; i < MAX_GI; i++) {
-		tgtobj->tx.sgi_count[i] +=
-			srcobj->stats.tx.sgi_count[i];
-		tgtobj->rx.sgi_count[i] +=
-			srcobj->stats.rx.sgi_count[i];
-	}
+	txrx_peer = peer->txrx_peer;
+	if (!txrx_peer)
+		goto link_stats;
 
-	for (i = 0; i < MAX_RECEPTION_TYPES; i++)
-		tgtobj->rx.reception_type[i] +=
-			srcobj->stats.rx.reception_type[i];
-
-	if (!wlan_cfg_get_vdev_stats_hw_offload_config(soc->wlan_cfg_ctx)) {
-		tgtobj->tx.comp_pkt.bytes += srcobj->stats.tx.comp_pkt.bytes;
-		tgtobj->tx.comp_pkt.num += srcobj->stats.tx.comp_pkt.num;
-		tgtobj->tx.tx_failed += srcobj->stats.tx.tx_failed;
-	}
-	tgtobj->tx.ucast.num += srcobj->stats.tx.ucast.num;
-	tgtobj->tx.ucast.bytes += srcobj->stats.tx.ucast.bytes;
-	tgtobj->tx.mcast.num += srcobj->stats.tx.mcast.num;
-	tgtobj->tx.mcast.bytes += srcobj->stats.tx.mcast.bytes;
-	tgtobj->tx.bcast.num += srcobj->stats.tx.bcast.num;
-	tgtobj->tx.bcast.bytes += srcobj->stats.tx.bcast.bytes;
-	tgtobj->tx.tx_success.num += srcobj->stats.tx.tx_success.num;
-	tgtobj->tx.tx_success.bytes +=
-		srcobj->stats.tx.tx_success.bytes;
-	tgtobj->tx.nawds_mcast.num +=
-		srcobj->stats.tx.nawds_mcast.num;
-	tgtobj->tx.nawds_mcast.bytes +=
-		srcobj->stats.tx.nawds_mcast.bytes;
-	tgtobj->tx.nawds_mcast_drop +=
-		srcobj->stats.tx.nawds_mcast_drop;
-	tgtobj->tx.num_ppdu_cookie_valid +=
-		srcobj->stats.tx.num_ppdu_cookie_valid;
-	tgtobj->tx.ofdma += srcobj->stats.tx.ofdma;
-	tgtobj->tx.stbc += srcobj->stats.tx.stbc;
-	tgtobj->tx.ldpc += srcobj->stats.tx.ldpc;
-	tgtobj->tx.pream_punct_cnt += srcobj->stats.tx.pream_punct_cnt;
-	tgtobj->tx.retries += srcobj->stats.tx.retries;
-	tgtobj->tx.retries_mpdu += srcobj->stats.tx.retries_mpdu;
-	tgtobj->tx.non_amsdu_cnt += srcobj->stats.tx.non_amsdu_cnt;
-	tgtobj->tx.amsdu_cnt += srcobj->stats.tx.amsdu_cnt;
-	tgtobj->tx.non_ampdu_cnt += srcobj->stats.tx.non_ampdu_cnt;
-	tgtobj->tx.ampdu_cnt += srcobj->stats.tx.ampdu_cnt;
-	tgtobj->tx.dropped.fw_rem.num += srcobj->stats.tx.dropped.fw_rem.num;
-	tgtobj->tx.dropped.fw_rem.bytes +=
-			srcobj->stats.tx.dropped.fw_rem.bytes;
-	tgtobj->tx.dropped.fw_rem_tx +=
-			srcobj->stats.tx.dropped.fw_rem_tx;
-	tgtobj->tx.dropped.fw_rem_notx +=
-			srcobj->stats.tx.dropped.fw_rem_notx;
-	tgtobj->tx.dropped.fw_reason1 +=
-			srcobj->stats.tx.dropped.fw_reason1;
-	tgtobj->tx.dropped.fw_reason2 +=
-			srcobj->stats.tx.dropped.fw_reason2;
-	tgtobj->tx.dropped.fw_reason3 +=
-			srcobj->stats.tx.dropped.fw_reason3;
-	tgtobj->tx.dropped.age_out += srcobj->stats.tx.dropped.age_out;
-	tgtobj->tx.mpdu_success_with_retries +=
-			srcobj->stats.tx.mpdu_success_with_retries;
-	tgtobj->rx.err.mic_err += srcobj->stats.rx.err.mic_err;
-	tgtobj->rx.err.decrypt_err += srcobj->stats.rx.err.decrypt_err;
-	tgtobj->rx.err.fcserr += srcobj->stats.rx.err.fcserr;
-	tgtobj->rx.err.pn_err += srcobj->stats.rx.err.pn_err;
-	tgtobj->rx.err.oor_err += srcobj->stats.rx.err.oor_err;
-	tgtobj->rx.err.jump_2k_err += srcobj->stats.rx.err.jump_2k_err;
-	tgtobj->rx.err.rxdma_wifi_parse_err +=
-				srcobj->stats.rx.err.rxdma_wifi_parse_err;
-	if (srcobj->stats.rx.snr != 0)
-		tgtobj->rx.snr = srcobj->stats.rx.snr;
-	tgtobj->rx.rx_rate = srcobj->stats.rx.rx_rate;
-	tgtobj->rx.non_ampdu_cnt += srcobj->stats.rx.non_ampdu_cnt;
-	tgtobj->rx.amsdu_cnt += srcobj->stats.rx.ampdu_cnt;
-	tgtobj->rx.non_amsdu_cnt += srcobj->stats.rx.non_amsdu_cnt;
-	tgtobj->rx.amsdu_cnt += srcobj->stats.rx.amsdu_cnt;
-	tgtobj->rx.nawds_mcast_drop += srcobj->stats.rx.nawds_mcast_drop;
-	tgtobj->rx.to_stack.num += srcobj->stats.rx.to_stack.num;
-	tgtobj->rx.to_stack.bytes += srcobj->stats.rx.to_stack.bytes;
+	dp_update_vdev_basic_stats(txrx_peer, vdev_stats);
 
-	for (i = 0; i <  CDP_MAX_RX_RINGS; i++) {
-		tgtobj->rx.rcvd_reo[i].num +=
-			srcobj->stats.rx.rcvd_reo[i].num;
-		tgtobj->rx.rcvd_reo[i].bytes +=
-			srcobj->stats.rx.rcvd_reo[i].bytes;
-	}
-
-	srcobj->stats.rx.unicast.num =
-		srcobj->stats.rx.to_stack.num -
-				srcobj->stats.rx.multicast.num;
-	srcobj->stats.rx.unicast.bytes =
-		srcobj->stats.rx.to_stack.bytes -
-				srcobj->stats.rx.multicast.bytes;
-
-	tgtobj->rx.unicast.num += srcobj->stats.rx.unicast.num;
-	tgtobj->rx.unicast.bytes += srcobj->stats.rx.unicast.bytes;
-	tgtobj->rx.multicast.num += srcobj->stats.rx.multicast.num;
-	tgtobj->rx.multicast.bytes += srcobj->stats.rx.multicast.bytes;
-	tgtobj->rx.bcast.num += srcobj->stats.rx.bcast.num;
-	tgtobj->rx.bcast.bytes += srcobj->stats.rx.bcast.bytes;
-	tgtobj->rx.raw.num += srcobj->stats.rx.raw.num;
-	tgtobj->rx.raw.bytes += srcobj->stats.rx.raw.bytes;
-	tgtobj->rx.intra_bss.pkts.num +=
-			srcobj->stats.rx.intra_bss.pkts.num;
-	tgtobj->rx.intra_bss.pkts.bytes +=
-			srcobj->stats.rx.intra_bss.pkts.bytes;
-	tgtobj->rx.intra_bss.fail.num +=
-			srcobj->stats.rx.intra_bss.fail.num;
-	tgtobj->rx.intra_bss.fail.bytes +=
-			srcobj->stats.rx.intra_bss.fail.bytes;
-	tgtobj->tx.last_ack_rssi =
-		srcobj->stats.tx.last_ack_rssi;
-	tgtobj->rx.mec_drop.num += srcobj->stats.rx.mec_drop.num;
-	tgtobj->rx.mec_drop.bytes += srcobj->stats.rx.mec_drop.bytes;
-	tgtobj->rx.multipass_rx_pkt_drop +=
-		srcobj->stats.rx.multipass_rx_pkt_drop;
-	tgtobj->rx.peer_unauth_rx_pkt_drop +=
-		srcobj->stats.rx.peer_unauth_rx_pkt_drop;
-	tgtobj->rx.policy_check_drop +=
-		srcobj->stats.rx.policy_check_drop;
+	per_pkt_stats = &txrx_peer->stats.per_pkt_stats;
+	DP_UPDATE_PER_PKT_STATS(vdev_stats, per_pkt_stats);
+
+link_stats:
+	dp_monitor_peer_get_stats(soc, peer, vdev_stats, UPDATE_VDEV_STATS);
+}
+
+#else
+void dp_update_vdev_stats(struct dp_soc *soc, struct dp_peer *srcobj,
+			  void *arg)
+{
+	struct dp_txrx_peer *txrx_peer;
+	struct cdp_vdev_stats *vdev_stats = (struct cdp_vdev_stats *)arg;
+	struct dp_peer_per_pkt_stats *per_pkt_stats;
+	struct dp_peer_extd_stats *extd_stats;
+
+	txrx_peer = dp_get_txrx_peer(srcobj);
+	if (qdf_unlikely(!txrx_peer))
+		return;
+
+	if (qdf_unlikely(dp_is_wds_extended(txrx_peer)))
+		return;
+
+	if (!dp_peer_is_primary_link_peer(srcobj))
+		return;
+
+	dp_update_vdev_basic_stats(txrx_peer, vdev_stats);
+
+	per_pkt_stats = &txrx_peer->stats.per_pkt_stats;
+	DP_UPDATE_PER_PKT_STATS(vdev_stats, per_pkt_stats);
+
+	extd_stats = &txrx_peer->stats.extd_stats;
+	DP_UPDATE_EXTD_STATS(vdev_stats, extd_stats);
+}
+
+void dp_update_vdev_stats_on_peer_unmap(struct dp_vdev *vdev,
+					struct dp_peer *peer)
+{
+	struct dp_txrx_peer *txrx_peer;
+	struct dp_peer_per_pkt_stats *per_pkt_stats;
+	struct dp_peer_extd_stats *extd_stats;
+	struct cdp_vdev_stats *vdev_stats = &vdev->stats;
+
+	txrx_peer = peer->txrx_peer;
+	if (!txrx_peer)
+		return;
+
+	dp_update_vdev_basic_stats(txrx_peer, vdev_stats);
+
+	per_pkt_stats = &txrx_peer->stats.per_pkt_stats;
+	DP_UPDATE_PER_PKT_STATS(vdev_stats, per_pkt_stats);
+
+	extd_stats = &txrx_peer->stats.extd_stats;
+	DP_UPDATE_EXTD_STATS(vdev_stats, extd_stats);
 }
+#endif
 
 void dp_update_pdev_stats(struct dp_pdev *tgtobj,
 			  struct cdp_vdev_stats *srcobj)

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

@@ -998,6 +998,9 @@ struct dp_mon_ops monitor_ops_1_0 = {
 	.mon_peer_get_rdkstats_ctx = dp_mon_peer_get_rdkstats_ctx,
 	.mon_peer_reset_stats = dp_mon_peer_reset_stats,
 	.mon_peer_get_stats = dp_mon_peer_get_stats,
+	.mon_invalid_peer_update_pdev_stats =
+				dp_mon_invalid_peer_update_pdev_stats,
+	.mon_peer_get_stats_param = dp_mon_peer_get_stats_param,
 	.mon_flush_rings = dp_flush_monitor_rings,
 #if !defined(DISABLE_MON_CONFIG)
 	.mon_pdev_htt_srng_setup = dp_mon_htt_srng_setup_1_0,

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

@@ -1140,6 +1140,9 @@ struct dp_mon_ops monitor_ops_2_0 = {
 	.mon_peer_get_rdkstats_ctx = dp_mon_peer_get_rdkstats_ctx,
 	.mon_peer_reset_stats = dp_mon_peer_reset_stats,
 	.mon_peer_get_stats = dp_mon_peer_get_stats,
+	.mon_invalid_peer_update_pdev_stats =
+				dp_mon_invalid_peer_update_pdev_stats,
+	.mon_peer_get_stats_param = dp_mon_peer_get_stats_param,
 	.mon_flush_rings = NULL,
 #if !defined(DISABLE_MON_CONFIG)
 	.mon_pdev_htt_srng_setup = dp_mon_pdev_htt_srng_setup_2_0,

+ 62 - 0
dp/wifi3.0/monitor/dp_mon.c

@@ -5144,6 +5144,68 @@ void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg,
 		dp_mon_err("Invalid stats_update_type");
 	}
 }
+
+void dp_mon_invalid_peer_update_pdev_stats(struct dp_pdev *pdev)
+{
+	struct dp_mon_peer *mon_peer;
+	struct dp_mon_peer_stats *mon_peer_stats;
+	struct cdp_pdev_stats *pdev_stats;
+
+	if (!pdev || !pdev->monitor_pdev)
+		return;
+
+	mon_peer = pdev->monitor_pdev->invalid_mon_peer;
+	if (!mon_peer)
+		return;
+
+	mon_peer_stats = &mon_peer->stats;
+	pdev_stats = &pdev->stats;
+	DP_UPDATE_MON_STATS(pdev_stats, mon_peer_stats);
+}
+
+QDF_STATUS
+dp_mon_peer_get_stats_param(struct dp_peer *peer, enum cdp_peer_stats_type type,
+			    cdp_peer_stats_param_t *buf)
+{
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+	struct dp_mon_peer *mon_peer;
+
+	mon_peer = peer->monitor_peer;
+	if (!mon_peer)
+		return QDF_STATUS_E_FAILURE;
+
+	switch (type) {
+	case cdp_peer_tx_rate:
+		buf->tx_rate = mon_peer->stats.tx.tx_rate;
+		break;
+	case cdp_peer_tx_last_tx_rate:
+		buf->last_tx_rate = mon_peer->stats.tx.last_tx_rate;
+		break;
+	case cdp_peer_tx_ratecode:
+		buf->tx_ratecode = mon_peer->stats.tx.tx_ratecode;
+		break;
+	case cdp_peer_rx_rate:
+		buf->rx_rate = mon_peer->stats.rx.rx_rate;
+		break;
+	case cdp_peer_rx_last_rx_rate:
+		buf->last_rx_rate = mon_peer->stats.rx.last_rx_rate;
+		break;
+	case cdp_peer_rx_ratecode:
+		buf->rx_ratecode = mon_peer->stats.rx.rx_ratecode;
+		break;
+	case cdp_peer_rx_avg_snr:
+		buf->rx_avg_snr = mon_peer->stats.rx.avg_snr;
+		break;
+	case cdp_peer_rx_snr:
+		buf->rx_snr = mon_peer->stats.rx.snr;
+		break;
+	default:
+		dp_err("Invalid stats type requested");
+		ret = QDF_STATUS_E_FAILURE;
+	}
+
+	return ret;
+}
 #endif
 
 void dp_mon_ops_register(struct dp_soc *soc)

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

@@ -217,6 +217,27 @@ void dp_mon_peer_reset_stats(struct dp_peer *peer);
  */
 void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg,
 			   enum cdp_stat_update_type type);
+
+/*
+ * dp_mon_invalid_peer_update_pdev_stats() - Update pdev stats from
+ *					invalid monitor peer
+ * @pdev: Datapath pdev handle
+ *
+ * Return: none
+ */
+void dp_mon_invalid_peer_update_pdev_stats(struct dp_pdev *pdev);
+
+/*
+ * dp_mon_peer_get_stats_param() - Get stats param value from monitor peer
+ * @peer: Datapath peer handle
+ * @type: Stats type requested
+ * @buf: Pointer to buffer for stats param
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_mon_peer_get_stats_param(struct dp_peer *peer,
+				       enum cdp_peer_stats_type type,
+				       cdp_peer_stats_param_t *buf);
 #else
 static inline void dp_mon_peer_reset_stats(struct dp_peer *peer)
 {
@@ -227,6 +248,18 @@ void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg,
 			   enum cdp_stat_update_type type)
 {
 }
+
+static inline void dp_mon_invalid_peer_update_pdev_stats(struct dp_pdev *pdev)
+{
+}
+
+static inline
+QDF_STATUS dp_mon_peer_get_stats_param(struct dp_peer *peer,
+				       enum cdp_peer_stats_type type,
+				       cdp_peer_stats_param_t *buf)
+{
+	return QDF_STATUS_E_FAILURE;
+}
 #endif
 
 /*
@@ -482,6 +515,10 @@ struct dp_mon_ops {
 	void (*mon_peer_reset_stats)(struct dp_peer *peer);
 	void (*mon_peer_get_stats)(struct dp_peer *peer, void *arg,
 				   enum cdp_stat_update_type type);
+	void (*mon_invalid_peer_update_pdev_stats)(struct dp_pdev *pdev);
+	QDF_STATUS (*mon_peer_get_stats_param)(struct dp_peer *peer,
+					       enum cdp_peer_stats_type type,
+					       cdp_peer_stats_param_t *buf);
 	QDF_STATUS (*mon_config_debug_sniffer)(struct dp_pdev *pdev, int val);
 	void (*mon_flush_rings)(struct dp_soc *soc);
 #if !defined(DISABLE_MON_CONFIG)
@@ -1752,6 +1789,62 @@ void dp_monitor_peer_get_stats(struct dp_soc *soc, struct dp_peer *peer,
 	monitor_ops->mon_peer_get_stats(peer, arg, type);
 }
 
+/*
+ * dp_monitor_invalid_peer_update_pdev_stats() - Update pdev stats from
+ *						invalid monitor peer
+ * @soc: Datapath soc handle
+ * @pdev: Datapath pdev handle
+ *
+ * Return: none
+ */
+static inline
+void dp_monitor_invalid_peer_update_pdev_stats(struct dp_soc *soc,
+					       struct dp_pdev *pdev)
+{
+	struct dp_mon_ops *monitor_ops;
+	struct dp_mon_soc *mon_soc = soc->monitor_soc;
+
+	if (!mon_soc)
+		return;
+
+	monitor_ops = mon_soc->mon_ops;
+	if (!monitor_ops || !monitor_ops->mon_invalid_peer_update_pdev_stats) {
+		dp_mon_debug("callback not registered");
+		return;
+	}
+
+	monitor_ops->mon_invalid_peer_update_pdev_stats(pdev);
+}
+
+/*
+ * dp_monitor_peer_get_stats_param() - Get stats param value from monitor peer
+ * @soc: Datapath soc handle
+ * @peer: Datapath peer handle
+ * @type: Stats type requested
+ * @buf: Pointer to buffer for stats param
+ *
+ * Return: QDF_STATUS
+ */
+static inline QDF_STATUS
+dp_monitor_peer_get_stats_param(struct dp_soc *soc, struct dp_peer *peer,
+				enum cdp_peer_stats_type type,
+				cdp_peer_stats_param_t *buf)
+{
+	struct dp_mon_ops *monitor_ops;
+	struct dp_mon_soc *mon_soc = soc->monitor_soc;
+
+	if (!mon_soc)
+		return QDF_STATUS_E_FAILURE;
+
+	monitor_ops = mon_soc->mon_ops;
+	if (!monitor_ops || !monitor_ops->mon_peer_get_stats_param) {
+		dp_mon_debug("callback not registered");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return monitor_ops->mon_peer_get_stats_param(peer, type, buf);
+}
+
 /*
  * dp_monitor_pdev_init() - Monitor pdev init
  * @pdev: point to pdev