Преглед на файлове

qcacmn: Add MIB statistics

Add new stats_id WMI_REQUEST_MIB_STATS &
WMI_REQUEST_MIB_EXTD_STATS in WMI_REQUEST_STATS_CMDID
to retrieve MIB statistics from fw.

Change-Id: I17bccc2673d1a2ce035db04d8426bab49db80790
CRs-Fixed: 2548165
tinlin преди 5 години
родител
ревизия
21f7286344

+ 16 - 1
os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -52,6 +52,21 @@ int wlan_cfg80211_mc_cp_stats_get_wakelock_stats(struct wlan_objmgr_psoc *psoc,
  */
 int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
 					   int *dbm);
+#ifdef WLAN_FEATURE_MIB_STATS
+/**
+ * wlan_cfg80211_mc_cp_stats_get_mib_stats() - API to get mib stats
+ * statistics from firmware
+ * @vdev:    Pointer to vdev
+ * @errno:   error type in case of failure
+ *
+ * Callers of this API must call wlan_cfg80211_mc_cp_stats_free_stats_event
+ * API.
+ * Return: stats buffer on success, Null on failure
+ */
+struct stats_event *
+wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev,
+					int *errno);
+#endif
 
 /**
  * wlan_cfg80211_mc_cp_stats_get_station_stats() - API to get station

+ 139 - 0
os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c

@@ -32,6 +32,24 @@
 /* max time in ms, caller may wait for stats request get serviced */
 #define CP_STATS_WAIT_TIME_STAT 800
 
+#ifdef WLAN_FEATURE_MIB_STATS
+/**
+ * wlan_free_mib_stats() - free allocations for mib stats
+ * @stats: Pointer to stats event statucture
+ *
+ * Return: None
+ */
+static void wlan_free_mib_stats(struct stats_event *stats)
+{
+	qdf_mem_free(stats->mib_stats);
+	stats->mib_stats = NULL;
+}
+#else
+static void wlan_free_mib_stats(struct stats_event *stats)
+{
+}
+#endif
+
 /**
  * wlan_cfg80211_mc_cp_stats_dealloc() - callback to free priv
  * allocations for stats
@@ -56,6 +74,7 @@ static void wlan_cfg80211_mc_cp_stats_dealloc(void *priv)
 	qdf_mem_free(stats->vdev_summary_stats);
 	qdf_mem_free(stats->vdev_chain_rssi);
 	qdf_mem_free(stats->peer_adv_stats);
+	wlan_free_mib_stats(stats);
 	osif_debug("Exit");
 }
 
@@ -581,6 +600,125 @@ get_station_stats_fail:
 	return NULL;
 }
 
+#ifdef WLAN_FEATURE_MIB_STATS
+/**
+ * get_mib_stats_cb() - get mib stats from fw callback function
+ * @ev: mib stats buffer
+ * @cookie: a cookie for the request context
+ *
+ * Return: None
+ */
+static void get_mib_stats_cb(struct stats_event *ev, void *cookie)
+{
+	struct stats_event *priv;
+	struct osif_request *request;
+
+	request = osif_request_get(cookie);
+	if (!request) {
+		osif_err("Obsolete request");
+		return;
+	}
+
+	priv = osif_request_priv(request);
+
+	priv->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats));
+	if (!priv->mib_stats)
+		goto get_mib_stats_cb_fail;
+
+	priv->num_mib_stats = ev->num_mib_stats;
+	qdf_mem_copy(priv->mib_stats, ev->mib_stats, sizeof(*ev->mib_stats));
+
+get_mib_stats_cb_fail:
+	osif_request_complete(request);
+	osif_request_put(request);
+}
+
+struct stats_event *
+wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev,
+					int *errno)
+{
+	void *cookie;
+	QDF_STATUS status;
+	struct stats_event *priv, *out;
+	struct wlan_objmgr_peer *peer;
+	struct osif_request *request;
+	struct request_info info = {0};
+	static const struct osif_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT,
+		.dealloc = wlan_cfg80211_mc_cp_stats_dealloc,
+	};
+
+	out = qdf_mem_malloc(sizeof(*out));
+	if (!out) {
+		*errno = -ENOMEM;
+		return NULL;
+	}
+
+	request = osif_request_alloc(&params);
+	if (!request) {
+		qdf_mem_free(out);
+		*errno = -ENOMEM;
+		return NULL;
+	}
+
+	cookie = osif_request_cookie(request);
+	priv = osif_request_priv(request);
+	info.cookie = cookie;
+	info.u.get_mib_stats_cb = get_mib_stats_cb;
+	info.vdev_id = wlan_vdev_get_id(vdev);
+	info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
+	if (!peer) {
+		osif_err("peer is null");
+		*errno = -EINVAL;
+		goto get_mib_stats_fail;
+	}
+	qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE);
+
+	osif_debug("vdev id %d, pdev id %d, peer " QDF_MAC_ADDR_STR,
+		   info.vdev_id, info.pdev_id,
+		   QDF_MAC_ADDR_ARRAY(info.peer_mac_addr));
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
+
+	status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_MIB_STATS,
+						     &info);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_err("Failed to send stats request status: %d", status);
+		*errno = qdf_status_to_os_return(status);
+		goto get_mib_stats_fail;
+	}
+
+	*errno = osif_request_wait_for_response(request);
+	if (*errno) {
+		osif_err("wait failed or timed out ret: %d", *errno);
+		goto get_mib_stats_fail;
+	}
+
+	if (!priv->mib_stats || priv->num_mib_stats == 0 ) {
+		osif_err("Invalid mib stats %d:%pK",
+			 priv->num_mib_stats, priv->mib_stats);
+		*errno = -EINVAL;
+		goto get_mib_stats_fail;
+	}
+
+	out->num_mib_stats = priv->num_mib_stats;
+	out->mib_stats = priv->mib_stats;
+	priv->mib_stats = NULL;
+
+	osif_request_put(request);
+
+	return out;
+
+get_mib_stats_fail:
+	osif_request_put(request);
+	wlan_cfg80211_mc_cp_stats_free_stats_event(out);
+
+	return NULL;
+}
+#endif
+
 void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats)
 {
 	if (!stats)
@@ -592,5 +730,6 @@ void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats)
 	qdf_mem_free(stats->vdev_summary_stats);
 	qdf_mem_free(stats->vdev_chain_rssi);
 	qdf_mem_free(stats->peer_adv_stats);
+	wlan_free_mib_stats(stats);
 	qdf_mem_free(stats);
 }

+ 69 - 2
target_if/cp_stats/src/target_if_mc_cp_stats.c

@@ -35,6 +35,17 @@
 #include <wlan_cp_stats_mc_tgt_api.h>
 #include "../../../umac/cmn_services/utils/inc/wlan_utility.h"
 
+#ifdef WLAN_FEATURE_MIB_STATS
+static void target_if_cp_stats_free_mib_stats(struct stats_event *ev)
+{
+	qdf_mem_free(ev->mib_stats);
+	ev->mib_stats = NULL;
+}
+#else
+static void target_if_cp_stats_free_mib_stats(struct stats_event *ev)
+{
+}
+#endif
 static void target_if_cp_stats_free_stats_event(struct stats_event *ev)
 {
 	qdf_mem_free(ev->pdev_stats);
@@ -51,6 +62,7 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev)
 	ev->vdev_summary_stats = NULL;
 	qdf_mem_free(ev->vdev_chain_rssi);
 	ev->vdev_chain_rssi = NULL;
+	target_if_cp_stats_free_mib_stats(ev);
 }
 
 static QDF_STATUS target_if_cp_stats_extract_pdev_stats(
@@ -232,6 +244,51 @@ static QDF_STATUS target_if_cp_stats_extract_cca_stats(
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_MIB_STATS
+static QDF_STATUS target_if_cp_stats_extract_mib_stats(
+					struct wmi_unified *wmi_hdl,
+					wmi_host_stats_event *stats_param,
+					struct stats_event *ev, uint8_t *data)
+{
+	QDF_STATUS status;
+
+	if (!stats_param->num_mib_stats) {
+		cp_stats_debug("no mib stats");
+		return QDF_STATUS_SUCCESS;
+	}
+	if (stats_param->num_mib_stats != MAX_MIB_STATS ||
+	    (stats_param->num_mib_extd_stats &&
+	    stats_param->num_mib_extd_stats != MAX_MIB_STATS)) {
+		cp_stats_err("number of mib stats wrong, num_mib_stats %d, num_mib_extd_stats %d",
+			     stats_param->num_mib_stats,
+			     stats_param->num_mib_extd_stats);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	ev->num_mib_stats = stats_param->num_mib_stats;
+
+	ev->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats));
+	if (!ev->mib_stats)
+		return QDF_STATUS_E_NOMEM;
+
+	status = wmi_extract_mib_stats(wmi_hdl, data, ev->mib_stats);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("wmi_extract_mib_stats failed");
+		return status;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static QDF_STATUS target_if_cp_stats_extract_mib_stats(
+					struct wmi_unified *wmi_hdl,
+					wmi_host_stats_event *stats_param,
+					struct stats_event *ev, uint8_t *data)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats(
 					struct wmi_unified *wmi_hdl,
 					wmi_host_stats_event *stats_param,
@@ -358,9 +415,11 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
 		cp_stats_err("stats param extract failed: %d", status);
 		return status;
 	}
-	cp_stats_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d",
+	cp_stats_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d, mib %d, mib_extd %d",
 		       stats_param.num_pdev_stats, stats_param.num_vdev_stats,
-		       stats_param.num_peer_stats, stats_param.num_rssi_stats);
+		       stats_param.num_peer_stats, stats_param.num_rssi_stats,
+		       stats_param.num_mib_stats,
+		       stats_param.num_mib_extd_stats);
 
 	ev->last_event = stats_param.last_event;
 	status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param,
@@ -390,6 +449,12 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
+	status = target_if_cp_stats_extract_mib_stats(wmi_hdl,
+						      &stats_param,
+						      ev, data);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -591,6 +656,8 @@ static uint32_t get_stats_id(enum stats_req_type type)
 			WMI_REQUEST_PDEV_STAT |
 			WMI_REQUEST_PEER_EXTD2_STAT |
 			WMI_REQUEST_RSSI_PER_CHAIN_STAT);
+	case TYPE_MIB_STATS:
+		return (WMI_REQUEST_MIB_STAT | WMI_REQUEST_MIB_EXTD_STAT);
 	}
 
 	return 0;

+ 145 - 1
umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h

@@ -33,6 +33,8 @@
 
 #define MAX_NUM_CHAINS              2
 
+#define MAX_MIB_STATS               1
+
 #define IS_MSB_SET(__num) ((__num) & BIT(31))
 #define IS_LSB_SET(__num) ((__num) & BIT(0))
 
@@ -42,11 +44,13 @@
  * @TYPE_CONNECTION_TX_POWER: tx power was requested
  * @TYPE_STATION_STATS: station stats was requested
  * @TYPE_PEER_STATS: peer stats was requested
+ * @TYPE_MIB_STATS: MIB stats was requested
  */
 enum stats_req_type {
 	TYPE_CONNECTION_TX_POWER = 0,
 	TYPE_STATION_STATS,
 	TYPE_PEER_STATS,
+	TYPE_MIB_STATS,
 	TYPE_MAX,
 };
 
@@ -153,7 +157,8 @@ struct stats_event;
 /**
  * struct request_info: details of each request
  * @cookie: identifier for os_if request
- * @callback: callback to process os_if request when response comes.
+ * @u: unified data type for callback to process tx power/peer rssi/
+ *     station stats/mib stats request when response comes.
  * @vdev_id: vdev_id of request
  * @pdev_id: pdev_id of request
  * @peer_mac_addr: peer mac address
@@ -165,6 +170,8 @@ struct request_info {
 		void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie);
 		void (*get_station_stats_cb)(struct stats_event *ev,
 					     void *cookie);
+		void (*get_mib_stats_cb)(struct stats_event *ev,
+					 void *cookie);
 	} u;
 	uint32_t vdev_id;
 	uint32_t pdev_id;
@@ -313,6 +320,137 @@ struct peer_adv_mc_cp_stats {
 	uint64_t rx_bytes;
 };
 
+#ifdef WLAN_FEATURE_MIB_STATS
+/**
+ * struct dot11_counters - mib group containing attributes that are MAC counters
+ * @tx_frags: successfully transmitted fragments
+ * @group_tx_frames: transmitted group addressed frames
+ * @failed_cnt: MSDUs not transmitted successfully
+ * @rx_frags: fragments successfully received
+ * @group_rx_frames: group addressed frames received
+ * @fcs_error_cnt: FCS errors detected
+ * @tx_frames: frames successfully transmitted
+ */
+struct dot11_counters {
+	uint32_t tx_frags;
+	uint32_t group_tx_frames;
+	uint32_t failed_cnt;
+	uint32_t rx_frags;
+	uint32_t group_rx_frames;
+	uint32_t fcs_error_cnt;
+	uint32_t tx_frames;
+};
+
+/**
+ * struct dot11_mac_statistics - mib stats information on the operation of MAC
+ * @retry_cnt: retries done by mac for successful transmition
+ * @multi_retry_cnt: multiple retries done before successful transmition
+ * @frame_dup_cnt: duplicate no of frames
+ * @rts_success_cnt: number of CTS received (in response to RTS)
+ * @rts_fail_cnt: number of CTS not received (in response to RTS)
+ * @tx_ack_fail_cnt: number of ACK not received
+ */
+struct dot11_mac_statistics {
+	uint32_t retry_cnt;
+	uint32_t multi_retry_cnt;
+	uint32_t frame_dup_cnt;
+	uint32_t rts_success_cnt;
+	uint32_t rts_fail_cnt;
+	uint32_t tx_ack_fail_cnt;
+};
+
+/**
+ * dot11_qos_counters - qos mac counters
+ * @qos_tx_frag_cnt: transmitted QoS fragments
+ * @qos_failed_cnt: failed Qos fragments
+ * @qos_retry_cnt: Qos frames transmitted after retransmissions
+ * @qos_multi_retry_cnt: Qos frames transmitted after more than
+ *                       one retransmissions
+ * @qos_frame_dup_cnt: duplicate frames
+ * @qos_rts_success_cnt: number of CTS received (in response to RTS)
+ * @qos_rts_fail_cnt: number of CTS not received (in response to RTS)
+ * @tx_qos_ack_fail_cnt_up: number of ACK not received
+ *                          (in response to Qos frame)
+ * @qos_rx_frag_cnt: number of received MPDU of type Data
+ * @qos_tx_frame_cnt: number of transmitted MPDU of type Data
+ * @qos_discarded_frame_cnt: total Discarded MSDUs
+ * @qos_mpdu_rx_cnt: total received MPDU
+ * @qos_retries_rx_cnt: received MPDU with retry bit equal to 1
+ */
+struct dot11_qos_counters {
+	uint32_t qos_tx_frag_cnt;
+	uint32_t qos_failed_cnt;
+	uint32_t qos_retry_cnt;
+	uint32_t qos_multi_retry_cnt;
+	uint32_t qos_frame_dup_cnt;
+	uint32_t qos_rts_success_cnt;
+	uint32_t qos_rts_fail_cnt;
+	uint32_t tx_qos_ack_fail_cnt_up;
+	uint32_t qos_rx_frag_cnt;
+	uint32_t qos_tx_frame_cnt;
+	uint32_t qos_discarded_frame_cnt;
+	uint32_t qos_mpdu_rx_cnt;
+	uint32_t qos_retries_rx_cnt;
+};
+
+/**
+ * dot11_rsna_stats - mib rsn stats
+ * @rm_ccmp_replays: received robust management CCMP MPDUs discarded
+ *                   by the replay mechanism
+ * @tkip_icv_err: TKIP ICV errors encountered
+ * @tkip_replays: TKIP replay errors detected
+ * @ccmp_decrypt_err: MPDUs discarded by the CCMP decryption algorithm
+ * @ccmp_replays: received CCMP MPDUs discarded by the replay mechanism
+ * @cmac_icv_err: MPDUs discarded by the CMAC integrity check algorithm
+ * @cmac_replays: MPDUs discarded by the CMAC replay errors
+ */
+struct dot11_rsna_stats {
+	uint32_t rm_ccmp_replays;
+	uint32_t tkip_icv_err;
+	uint32_t tkip_replays;
+	uint32_t ccmp_decrypt_err;
+	uint32_t ccmp_replays;
+	uint32_t cmac_icv_err;
+	uint32_t cmac_replays;
+};
+
+/**
+ * dot11_counters_group3 - dot11 group3 stats
+ * @tx_ampdu_cnt: transmitted AMPDUs
+ * @tx_mpdus_in_ampdu_cnt: number of MPDUs in the A-MPDU in transmitted AMPDUs
+ * @tx_octets_in_ampdu_cnt: octets in the transmitted A-MPDUs
+ * @ampdu_rx_cnt: received A-MPDU
+ * @mpdu_in_rx_ampdu_cnt: MPDUs received in the A-MPDU
+ * @rx_octets_in_ampdu_cnt: octets in the received A-MPDU
+ * @rx_ampdu_deli_crc_err_cnt: number of MPDUs delimiter with CRC error
+ */
+struct dot11_counters_group3 {
+	uint32_t tx_ampdu_cnt;
+	uint32_t tx_mpdus_in_ampdu_cnt;
+	uint64_t tx_octets_in_ampdu_cnt;
+	uint32_t ampdu_rx_cnt;
+	uint32_t mpdu_in_rx_ampdu_cnt;
+	uint64_t rx_octets_in_ampdu_cnt;
+	uint32_t rx_ampdu_deli_crc_err_cnt;
+};
+
+/**
+ * mib_stats_metrics - mib stats counters
+ * @mib_counters: dot11Counters group
+ * @mib_mac_statistics: dot11MACStatistics group
+ * @mib_qos_counters: dot11QoSCounters group
+ * @mib_rsna_stats: dot11RSNAStats group
+ * @mib_counters_group3: dot11CountersGroup3 group
+ */
+struct mib_stats_metrics {
+	struct dot11_counters mib_counters;
+	struct dot11_mac_statistics mib_mac_statistics;
+	struct dot11_qos_counters mib_qos_counters;
+	struct dot11_rsna_stats mib_rsna_stats;
+	struct dot11_counters_group3 mib_counters_group3;
+};
+#endif
+
 /**
  * struct congestion_stats_event: congestion stats event param
  * @vdev_id: vdev_id of the event
@@ -356,6 +494,8 @@ struct chain_rssi_event {
  * @cca_stats: if populated indicates congestion stats
  * @num_summary_stats: number of summary stats
  * @vdev_summary_stats: if populated indicates array of summary stats per vdev
+ * @num_mib_stats: number of mib stats
+ * @mib_stats: if populated indicates array of mib stats per vdev
  * @num_chain_rssi_stats: number of chain rssi stats
  * @vdev_chain_rssi: if populated indicates array of chain rssi per vdev
  * @tx_rate: tx rate (kbps)
@@ -375,6 +515,10 @@ struct stats_event {
 	struct congestion_stats_event *cca_stats;
 	uint32_t num_summary_stats;
 	struct summary_stats_event *vdev_summary_stats;
+#ifdef WLAN_FEATURE_MIB_STATS
+	uint32_t num_mib_stats;
+	struct mib_stats_metrics *mib_stats;
+#endif
 	uint32_t num_chain_rssi_stats;
 	struct chain_rssi_event *vdev_chain_rssi;
 	uint32_t tx_rate;

+ 36 - 0
umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c

@@ -549,6 +549,39 @@ complete:
 	}
 }
 
+#ifdef WLAN_FEATURE_MIB_STATS
+static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
+					      struct stats_event *ev)
+{
+	QDF_STATUS status;
+	struct request_info last_req = {0};
+
+	if (!ev->mib_stats) {
+		cp_stats_debug("no mib stats");
+		return;
+	}
+
+	status = ucfg_mc_cp_stats_get_pending_req(psoc,
+						  TYPE_MIB_STATS, &last_req);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
+		return;
+	}
+
+	if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) {
+		ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS);
+		if (last_req.u.get_mib_stats_cb)
+			last_req.u.get_mib_stats_cb(ev, last_req.cookie);
+	}
+}
+#else
+static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
+					      struct stats_event *ev)
+{
+}
+#endif
+
 static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc,
 						  struct stats_event *ev)
 {
@@ -877,6 +910,9 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
 	if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_STATION_STATS))
 		tgt_mc_cp_stats_extract_station_stats(psoc, ev);
 
+	if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_MIB_STATS))
+		tgt_mc_cp_stats_extract_mib_stats(psoc, ev);
+
 	tgt_mc_cp_stats_extract_cca_stats(psoc, ev);
 
 	tgt_mc_cp_send_lost_link_stats(psoc, ev);

+ 13 - 0
wmi/inc/wmi_unified_api.h

@@ -2828,6 +2828,19 @@ QDF_STATUS wmi_extract_per_chain_rssi_stats(
 		uint32_t index,
 		struct wmi_host_per_chain_rssi_stats *rssi_stats);
 
+#ifdef WLAN_FEATURE_MIB_STATS
+/**
+ * wmi_extract_mib_stats() - extract mib stats from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @mib_stats: pointer to hold mib stats
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS wmi_extract_mib_stats(wmi_unified_t wmi_handle, void *evt_buf,
+				 struct mib_stats_metrics *mib_stats);
+#endif
+
 /**
  * wmi_extract_vdev_extd_stats() - extract extended vdev stats from event
  * @wmi_handle: wmi handle

+ 4 - 0
wmi/inc/wmi_unified_param.h

@@ -3801,6 +3801,8 @@ struct rx_reorder_queue_remove_params {
  * @num_bcn_stats: number of beacon stats
  * @num_rssi_stats: number of rssi stats
  * @num_peer_adv_stats: number of peer adv stats
+ * @num_mib_stats: number of mib stats
+ * @num_mib_extd_stats: number of extended mib stats
  * @last_event: specify if the current event is the last event
  */
 typedef struct {
@@ -3816,6 +3818,8 @@ typedef struct {
 	uint32_t num_bcn_stats;
 	uint32_t num_rssi_stats;
 	uint32_t num_peer_adv_stats;
+	uint32_t num_mib_stats;
+	uint32_t num_mib_extd_stats;
 	uint32_t last_event;
 } wmi_host_stats_event;
 

+ 5 - 0
wmi/inc/wmi_unified_priv.h

@@ -1592,6 +1592,11 @@ QDF_STATUS (*extract_peer_adv_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 QDF_STATUS (*extract_chan_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 			 uint32_t index, wmi_host_chan_stats *chan_stats);
 
+#ifdef WLAN_FEATURE_MIB_STATS
+QDF_STATUS (*extract_mib_stats)(wmi_unified_t wmi_handle, void *evt_buf,
+				struct mib_stats_metrics *mib_stats);
+#endif
+
 QDF_STATUS (*extract_thermal_stats)(wmi_unified_t wmi_handle, void *evt_buf,
 	uint32_t *temp, uint32_t *level, uint32_t *pdev_id);
 

+ 13 - 0
wmi/src/wmi_unified_api.c

@@ -2178,6 +2178,19 @@ wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf,
 	return QDF_STATUS_E_FAILURE;
 }
 
+#ifdef WLAN_FEATURE_MIB_STATS
+QDF_STATUS wmi_extract_mib_stats(wmi_unified_t wmi_handle, void *evt_buf,
+				 struct mib_stats_metrics *mib_stats)
+{
+	if (wmi_handle->ops->extract_mib_stats)
+		return wmi_handle->ops->extract_mib_stats(wmi_handle,
+							  evt_buf,
+							  mib_stats);
+
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
+
 QDF_STATUS wmi_extract_thermal_stats(wmi_unified_t wmi_handle, void *evt_buf,
 				     uint32_t *temp, uint32_t *level,
 				     uint32_t *pdev_id)

+ 146 - 1
wmi/src/wmi_unified_tlv.c

@@ -9019,7 +9019,9 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle,
 		(((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) +
 		(((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) +
 		(((uint64_t)ev->num_peer_extd_stats) *
-		 sizeof(wmi_peer_extd_stats));
+		 sizeof(wmi_peer_extd_stats)) +
+		(((uint64_t)ev->num_mib_extd_stats) *
+		 sizeof(wmi_mib_extd_stats));
 	if (param_buf->num_data != min_data_len) {
 		WMI_LOGE("data len: %u isn't same as calculated: %llu",
 			 param_buf->num_data, min_data_len);
@@ -9034,6 +9036,8 @@ static QDF_STATUS extract_all_stats_counts_tlv(wmi_unified_t wmi_handle,
 	stats_param->num_peer_extd_stats = ev->num_peer_extd_stats;
 	stats_param->num_bcnflt_stats = ev->num_bcnflt_stats;
 	stats_param->num_chan_stats = ev->num_chan_stats;
+	stats_param->num_mib_stats = ev->num_mib_stats;
+	stats_param->num_mib_extd_stats = ev->num_mib_extd_stats;
 	stats_param->num_bcn_stats = ev->num_bcn_stats;
 	stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
 							wmi_handle,
@@ -9549,6 +9553,144 @@ static QDF_STATUS extract_chan_stats_tlv(wmi_unified_t wmi_handle,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_MIB_STATS
+/**
+ * extract_mib_stats_tlv() - extract mib stats from event
+ * @wmi_handle: wmi handle
+ * @param evt_buf: pointer to event buffer
+ * @param mib_stats: pointer to hold mib stats
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS extract_mib_stats_tlv(wmi_unified_t wmi_handle,
+					void *evt_buf,
+					struct mib_stats_metrics
+					*mib_stats)
+{
+	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
+	wmi_stats_event_fixed_param *ev_param;
+	uint8_t *data;
+	wmi_mib_stats *ev;
+	wmi_mib_extd_stats *ev_extd;
+
+	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
+	ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param;
+	data = (uint8_t *)param_buf->data;
+
+	ev = (wmi_mib_stats *)(data +
+	      ev_param->num_pdev_stats * sizeof(wmi_pdev_stats) +
+	      ev_param->num_vdev_stats * sizeof(wmi_vdev_stats) +
+	      ev_param->num_peer_stats * sizeof(wmi_peer_stats) +
+	      ev_param->num_bcnflt_stats *
+	      sizeof(wmi_bcnfilter_stats_t) +
+	      ev_param->num_chan_stats * sizeof(wmi_chan_stats));
+
+	qdf_mem_zero(mib_stats, sizeof(*mib_stats));
+
+	mib_stats->mib_counters.tx_frags =
+		ev->tx_mpdu_grp_frag_cnt;
+	mib_stats->mib_counters.group_tx_frames =
+		ev->tx_msdu_grp_frm_cnt;
+	mib_stats->mib_counters.failed_cnt = ev->tx_msdu_fail_cnt;
+	mib_stats->mib_counters.rx_frags = ev->rx_mpdu_frag_cnt;
+	mib_stats->mib_counters.group_rx_frames =
+		ev->rx_msdu_grp_frm_cnt;
+	mib_stats->mib_counters.fcs_error_cnt =
+		ev->rx_mpdu_fcs_err;
+	mib_stats->mib_counters.tx_frames =
+		ev->tx_msdu_frm_cnt;
+	mib_stats->mib_mac_statistics.retry_cnt =
+		ev->tx_msdu_retry_cnt;
+	mib_stats->mib_mac_statistics.frame_dup_cnt =
+		ev->rx_frm_dup_cnt;
+	mib_stats->mib_mac_statistics.rts_success_cnt =
+		ev->tx_rts_success_cnt;
+	mib_stats->mib_mac_statistics.rts_fail_cnt =
+		ev->tx_rts_fail_cnt;
+
+	mib_stats->mib_qos_counters.qos_tx_frag_cnt =
+		 ev->tx_Qos_mpdu_grp_frag_cnt;
+	mib_stats->mib_qos_counters.qos_retry_cnt =
+		ev->tx_Qos_msdu_retry_UP;
+	mib_stats->mib_qos_counters.qos_failed_cnt =
+		ev->tx_Qos_msdu_fail_UP;
+	mib_stats->mib_qos_counters.qos_frame_dup_cnt =
+		ev->rx_Qos_frm_dup_cnt_UP;
+	mib_stats->mib_qos_counters.qos_rts_success_cnt =
+		ev->tx_Qos_rts_success_cnt_UP;
+	mib_stats->mib_qos_counters.qos_rts_fail_cnt =
+		ev->tx_Qos_rts_fail_cnt_UP;
+	mib_stats->mib_qos_counters.qos_rx_frag_cnt =
+		ev->rx_Qos_mpdu_frag_cnt_UP;
+	mib_stats->mib_qos_counters.qos_tx_frame_cnt =
+		ev->tx_Qos_msdu_frm_cnt_UP;
+	mib_stats->mib_qos_counters.qos_discarded_frame_cnt =
+		ev->rx_Qos_msdu_discard_cnt_UP;
+	mib_stats->mib_qos_counters.qos_mpdu_rx_cnt =
+		ev->rx_Qos_mpdu_cnt;
+	mib_stats->mib_qos_counters.qos_retries_rx_cnt =
+		ev->rx_Qos_mpdu_retryBit_cnt;
+
+	mib_stats->mib_rsna_stats.tkip_icv_err =
+		ev->rsna_TKIP_icv_err_cnt;
+	mib_stats->mib_rsna_stats.tkip_replays =
+		ev->rsna_TKIP_replay_err_cnt;
+	mib_stats->mib_rsna_stats.ccmp_decrypt_err =
+		ev->rsna_CCMP_decrypt_err_cnt;
+	mib_stats->mib_rsna_stats.ccmp_replays =
+		ev->rsna_CCMP_replay_err_cnt;
+
+	mib_stats->mib_counters_group3.tx_ampdu_cnt =
+		ev->tx_ampdu_cnt;
+	mib_stats->mib_counters_group3.tx_mpdus_in_ampdu_cnt =
+		ev->tx_mpdu_cnt_in_ampdu;
+	mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt =
+		ev->tx_octets_in_ampdu.upload.high;
+	mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt =
+		mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt << 32;
+	mib_stats->mib_counters_group3.tx_octets_in_ampdu_cnt +=
+		ev->tx_octets_in_ampdu.upload.low;
+
+	mib_stats->mib_counters_group3.ampdu_rx_cnt =
+		ev->rx_ampdu_cnt;
+	mib_stats->mib_counters_group3.mpdu_in_rx_ampdu_cnt =
+		ev->rx_mpdu_cnt_in_ampdu;
+	mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt =
+		ev->rx_octets_in_ampdu.upload.rx_octets_in_ampdu_high;
+	mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt =
+		mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt << 32;
+	mib_stats->mib_counters_group3.rx_octets_in_ampdu_cnt +=
+		ev->rx_octets_in_ampdu.upload.rx_octets_in_ampdu_low;
+
+	if (ev_param->num_mib_extd_stats) {
+		ev_extd = (wmi_mib_extd_stats *)((uint8_t *)ev +
+			   ev_param->num_mib_stats * sizeof(wmi_mib_stats) +
+			   ev_param->num_bcn_stats * sizeof(wmi_bcn_stats) +
+			   ev_param->num_peer_extd_stats *
+			   sizeof(wmi_peer_extd_stats));
+		mib_stats->mib_mac_statistics.multi_retry_cnt =
+			ev_extd->tx_msdu_multi_retry_cnt;
+		mib_stats->mib_mac_statistics.tx_ack_fail_cnt =
+			ev_extd->tx_ack_fail_cnt;
+
+		mib_stats->mib_qos_counters.qos_multi_retry_cnt =
+			ev_extd->tx_qos_msdu_multi_retry_up;
+		mib_stats->mib_qos_counters.tx_qos_ack_fail_cnt_up =
+			ev_extd->tx_qos_ack_fail_cnt_up;
+
+		mib_stats->mib_rsna_stats.cmac_icv_err =
+			ev_extd->rsna_cmac_icv_err_cnt;
+		mib_stats->mib_rsna_stats.cmac_replays =
+			ev_extd->rsna_cmac_replay_err_cnt;
+
+		mib_stats->mib_counters_group3.rx_ampdu_deli_crc_err_cnt =
+			ev_extd->rx_ampdu_deli_crc_err_cnt;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * extract_profile_ctx_tlv() - extract profile context from event
  * @wmi_handle: wmi handle
@@ -12453,6 +12595,9 @@ struct wmi_ops tlv_ops =  {
 	.extract_peer_extd_stats = extract_peer_extd_stats_tlv,
 	.extract_peer_adv_stats = extract_peer_adv_stats_tlv,
 	.extract_chan_stats = extract_chan_stats_tlv,
+#ifdef WLAN_FEATURE_MIB_STATS
+	.extract_mib_stats = extract_mib_stats_tlv,
+#endif
 	.extract_profile_ctx = extract_profile_ctx_tlv,
 	.extract_profile_data = extract_profile_data_tlv,
 	.send_fw_test_cmd = send_fw_test_cmd_tlv,