Browse Source

qcacld-3.0: Move get_peer_info into cp_stats component

Move WMI_REQUEST_PEER_STATS_INFO_CMDID related statistics into
cp_stats component.

Change-Id: I636221b0bc0e28180c97cd269440a7c733716a1d
CRs-Fixed: 2680618
Min Liu 4 years ago
parent
commit
f7d6bc2675

+ 13 - 1
Kbuild

@@ -722,7 +722,13 @@ CLD_WMI_ROAM_OBJS +=	$(WMI_DIR)/src/wmi_unified_roam_tlv.o \
 			$(WMI_DIR)/src/wmi_unified_roam_api.o
 endif
 
-CLD_WMI_OBJS :=	$(CLD_WMI_ROAM_OBJS)
+ifeq ($(CONFIG_CP_STATS), y)
+CLD_WMI_MC_CP_STATS_OBJS :=	$(WMI_DIR)/src/wmi_unified_mc_cp_stats_tlv.o \
+				$(WMI_DIR)/src/wmi_unified_mc_cp_stats_api.o
+endif
+
+CLD_WMI_OBJS :=	$(CLD_WMI_ROAM_OBJS) \
+		$(CLD_WMI_MC_CP_STATS_OBJS)
 
 ############ Qca-wifi-host-cmn ############
 QDF_OS_DIR :=	qdf
@@ -1562,6 +1568,11 @@ WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_cfr_tlv.o
 WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_cfr_api.o
 endif
 
+ifeq ($(CONFIG_CP_STATS), y)
+WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_cp_stats_api.o
+WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_cp_stats_tlv.o
+endif
+
 ########### FWLOG ###########
 FWLOG_DIR := $(WLAN_COMMON_ROOT)/utils/fwlog
 
@@ -2553,6 +2564,7 @@ cppflags-$(CONFIG_WLAN_LOGGING_SOCK_SVC) += -DWLAN_LOGGING_SOCK_SVC_ENABLE
 cppflags-$(CONFIG_WLAN_LOGGING_BUFFERS_DYNAMICALLY) += -DWLAN_LOGGING_BUFFERS_DYNAMICALLY
 cppflags-$(CONFIG_WLAN_FEATURE_FILS) += -DWLAN_FEATURE_FILS_SK
 cppflags-$(CONFIG_CP_STATS) += -DQCA_SUPPORT_CP_STATS
+cppflags-$(CONFIG_CP_STATS) += -DQCA_SUPPORT_MC_CP_STATS
 cppflags-$(CONFIG_DCS) += -DDCS_INTERFERENCE_DETECTION
 cppflags-$(CONFIG_FEATURE_INTEROP_ISSUES_AP) += -DWLAN_FEATURE_INTEROP_ISSUES_AP
 cppflags-$(CONFIG_FEATURE_MEMDUMP_ENABLE) += -DWLAN_FEATURE_MEMDUMP_ENABLE

+ 92 - 0
components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h

@@ -28,6 +28,8 @@
 
 #include "wlan_cmn.h"
 #include "qdf_event.h"
+/* For WMI_MAX_CHAINS */
+#include "wmi_unified.h"
 
 #ifdef WLAN_SUPPORT_TWT
 
@@ -53,12 +55,14 @@
  * @TYPE_STATION_STATS: station stats was requested
  * @TYPE_PEER_STATS: peer stats was requested
  * @TYPE_MIB_STATS: MIB stats was requested
+ * @TYPE_PEER_STATS_INFO_EXT: peer stats info ext was requested
  */
 enum stats_req_type {
 	TYPE_CONNECTION_TX_POWER = 0,
 	TYPE_STATION_STATS,
 	TYPE_PEER_STATS,
 	TYPE_MIB_STATS,
+	TYPE_PEER_STATS_INFO_EXT,
 	TYPE_MAX,
 };
 
@@ -184,6 +188,8 @@ struct request_info {
 					     void *cookie);
 		void (*get_mib_stats_cb)(struct stats_event *ev,
 					 void *cookie);
+		void (*get_peer_stats_cb)(struct stats_event *ev,
+					  void *cookie);
 	} u;
 	uint32_t vdev_id;
 	uint32_t pdev_id;
@@ -497,6 +503,40 @@ struct chain_rssi_event {
 	int8_t chain_rssi[MAX_NUM_CHAINS];
 };
 
+/**
+ * struct peer_stats_info_ext_event - peer extended stats info
+ * @peer_macaddr: MAC address
+ * @tx_packets: packets transmitted to this station
+ * @tx_bytes: bytes transmitted to this station
+ * @rx_packets: packets received from this station
+ * @rx_bytes: bytes received from this station
+ * @tx_retries: cumulative retry counts
+ * @tx_failed: the number of failed frames
+ * @tx_succeed: the number of succeed frames
+ * @rssi: the signal strength
+ * @tx_rate: last used tx bitrate (kbps)
+ * @tx_rate_code: last tx rate code (last_tx_rate_code of wmi_peer_stats_info)
+ * @rx_rate: last used rx bitrate (kbps)
+ * @rx_rate_code: last rx rate code (last_rx_rate_code of wmi_peer_stats_info)
+ * @peer_rssi_per_chain: the average value of RSSI (dbm) per chain
+ */
+struct peer_stats_info_ext_event {
+	struct qdf_mac_addr peer_macaddr;
+	uint32_t tx_packets;
+	uint64_t tx_bytes;
+	uint32_t rx_packets;
+	uint64_t rx_bytes;
+	uint32_t tx_retries;
+	uint32_t tx_failed;
+	uint32_t tx_succeed;
+	int32_t rssi;
+	uint32_t tx_rate;
+	uint32_t tx_rate_code;
+	uint32_t rx_rate;
+	uint32_t rx_rate_code;
+	int32_t peer_rssi_per_chain[WMI_MAX_CHAINS];
+};
+
 /**
  * struct stats_event - parameters populated by stats event
  * @num_pdev_stats: num pdev stats
@@ -518,6 +558,8 @@ struct chain_rssi_event {
  * @tx_rate_flags: tx rate flags, (enum tx_rate_info)
  * @last_event: The LSB indicates if the event is the last event or not and the
  *              MSB indicates if this feature is supported by FW or not.
+ * @num_peer_stats_info_ext: number of peer extended stats info
+ * @peer_stats_info_ext: peer extended stats info
  */
 struct stats_event {
 	uint32_t num_pdev_stats;
@@ -541,6 +583,56 @@ struct stats_event {
 	uint32_t rx_rate;
 	enum tx_rate_info tx_rate_flags;
 	uint32_t last_event;
+	uint32_t num_peer_stats_info_ext;
+	struct peer_stats_info_ext_event *peer_stats_info_ext;
+};
+
+/**
+ * struct peer_stats_request_params - peer stats request parameter
+ * @request_type: request type, one peer or all peers of the vdev
+ * @vdev_id: vdev id
+ * @peer_mac_addr: peer mac address, omitted if request type is all peers
+ * @reset_after_request: whether reset stats after request
+ */
+struct peer_stats_request_params {
+	uint32_t request_type;
+	uint32_t vdev_id;
+	uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE];
+	uint32_t reset_after_request;
 };
 
+/**
+ * struct wmi_host_peer_stats_info - WMI peer stats info
+ * @peer_macaddr: peer mac address
+ * @tx_bytes: tx_bytes
+ * @tx_packets: tx packets
+ * @rx_bytes: rx_bytes
+ * @rx_packets: rx packets
+ * @tx_retries: tx retries of MPDU
+ * @tx_failed: tx failed MPDU
+ * @last_tx_rate_code: rate code of the last tx
+ * @last_rx_rate_code: rate code of the last rx
+ * @last_tx_bitrate_kbps: bitrate in bps of the last tx
+ * @last_rx_bitrate_kbps: bitrate in bps of the last rx
+ * @peer_rssi: peer rssi
+ * @tx_succeed: tx succeed MPDU
+ * @peer_rssi_per_chain: peer rssi per chain
+ */
+typedef struct {
+	struct qdf_mac_addr peer_macaddr;
+	uint64_t tx_bytes;
+	uint32_t tx_packets;
+	uint64_t rx_bytes;
+	uint32_t rx_packets;
+	uint32_t tx_retries;
+	uint32_t tx_failed;
+	uint32_t last_tx_rate_code;
+	uint32_t last_rx_rate_code;
+	uint32_t last_tx_bitrate_kbps;
+	uint32_t last_rx_bitrate_kbps;
+	int32_t peer_rssi;
+	uint32_t tx_succeed;
+	int32_t peer_rssi_per_chain[WMI_MAX_CHAINS];
+} wmi_host_peer_stats_info;
+
 #endif /* __WLAN_CP_STATS_MC_DEFS_H__ */

+ 51 - 2
components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c

@@ -584,6 +584,35 @@ static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
 }
 #endif
 
+static void
+tgt_mc_cp_stats_extract_peer_stats_info_ext(struct wlan_objmgr_psoc *psoc,
+					    struct stats_event *ev)
+{
+	QDF_STATUS status;
+	struct request_info last_req = {0};
+	bool pending = false;
+
+	if (!ev->peer_stats_info_ext || ev->num_peer_stats_info_ext == 0) {
+		cp_stats_debug("no peer_stats_info_ext");
+		return;
+	}
+
+	status = ucfg_mc_cp_stats_get_pending_req(psoc,
+						  TYPE_PEER_STATS_INFO_EXT,
+						  &last_req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
+		return;
+	}
+
+	ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS_INFO_EXT,
+					   &last_req, &pending);
+	if (last_req.u.get_peer_stats_cb && pending) {
+		last_req.u.get_peer_stats_cb(ev, last_req.cookie);
+		last_req.u.get_peer_stats_cb = NULL;
+	}
+}
+
 static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc,
 						  struct stats_event *ev)
 {
@@ -915,6 +944,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_MIB_STATS))
 		tgt_mc_cp_stats_extract_mib_stats(psoc, ev);
 
+	if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_PEER_STATS_INFO_EXT))
+		tgt_mc_cp_stats_extract_peer_stats_info_ext(psoc, ev);
+
 	tgt_mc_cp_stats_extract_cca_stats(psoc, ev);
 
 	tgt_mc_cp_send_lost_link_stats(psoc, ev);
@@ -942,12 +974,29 @@ QDF_STATUS tgt_send_mc_cp_stats_req(struct wlan_objmgr_psoc *psoc,
 				    struct request_info *req)
 {
 	struct wlan_lmac_if_cp_stats_tx_ops *tx_ops;
+	QDF_STATUS status;
 
 	tx_ops = target_if_cp_stats_get_tx_ops(psoc);
-	if (!tx_ops || !tx_ops->send_req_stats) {
+	if (!tx_ops) {
 		cp_stats_err("could not get tx_ops");
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
-	return tx_ops->send_req_stats(psoc, type, req);
+	switch (type) {
+	case TYPE_PEER_STATS_INFO_EXT:
+		if (!tx_ops->send_req_peer_stats) {
+			cp_stats_err("could not get send_req_peer_stats");
+			return QDF_STATUS_E_NULL_VALUE;
+		}
+		status = tx_ops->send_req_peer_stats(psoc, req);
+		break;
+	default:
+		if (!tx_ops->send_req_stats) {
+			cp_stats_err("could not get send_req_stats");
+			return QDF_STATUS_E_NULL_VALUE;
+		}
+		status = tx_ops->send_req_stats(psoc, type, req);
+	}
+
+	return status;
 }

+ 1 - 0
components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c

@@ -850,6 +850,7 @@ void ucfg_mc_cp_stats_free_stats_resources(struct stats_event *ev)
 	qdf_mem_free(ev->vdev_summary_stats);
 	qdf_mem_free(ev->vdev_chain_rssi);
 	qdf_mem_free(ev->peer_extended_stats);
+	qdf_mem_free(ev->peer_stats_info_ext);
 	qdf_mem_zero(ev, sizeof(*ev));
 }
 

+ 167 - 0
components/target_if/cp_stats/src/target_if_mc_cp_stats.c

@@ -336,6 +336,8 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev)
 	qdf_mem_free(ev->vdev_chain_rssi);
 	ev->vdev_chain_rssi = NULL;
 	target_if_cp_stats_free_mib_stats(ev);
+	qdf_mem_free(ev->peer_stats_info_ext);
+	ev->peer_stats_info_ext = NULL;
 }
 
 static QDF_STATUS target_if_cp_stats_extract_pdev_stats(
@@ -813,6 +815,130 @@ end:
 	return qdf_status_to_os_return(status);
 }
 
+static QDF_STATUS
+target_if_cp_stats_extract_peer_stats_event(struct wmi_unified *wmi_hdl,
+					    struct stats_event *ev,
+					    uint8_t *data)
+{
+	QDF_STATUS status;
+	wmi_host_stats_event stats_param = {0};
+	struct peer_stats_info_ext_event *peer_stats_info;
+	wmi_host_peer_stats_info stats_info;
+	uint32_t peer_stats_info_size;
+	int i, j;
+
+	status = wmi_extract_peer_stats_param(wmi_hdl, data, &stats_param);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("peer stats param extract failed: %d", status);
+		return status;
+	}
+
+	if (stats_param.num_peer_stats_info_ext == 0) {
+		cp_stats_err("num_peer_stats_info_ext is 0");
+		return status;
+	}
+
+	ev->num_peer_stats_info_ext = stats_param.num_peer_stats_info_ext;
+	peer_stats_info_size = sizeof(*ev->peer_stats_info_ext) *
+			       ev->num_peer_stats_info_ext;
+	ev->peer_stats_info_ext = qdf_mem_malloc(peer_stats_info_size);
+	if (!ev->peer_stats_info_ext) {
+		ev->num_peer_stats_info_ext = 0;
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	peer_stats_info = ev->peer_stats_info_ext;
+	for (i = 0; i < ev->num_peer_stats_info_ext; i++) {
+		status = wmi_extract_peer_stats_info(wmi_hdl, data,
+						     i, &stats_info);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			cp_stats_err("peer stats info extract failed: %d",
+				     status);
+			qdf_mem_free(ev->peer_stats_info_ext);
+			ev->peer_stats_info_ext = NULL;
+			ev->num_peer_stats_info_ext = 0;
+			return status;
+		}
+		qdf_mem_copy(&peer_stats_info->peer_macaddr,
+			     &stats_info.peer_macaddr,
+			     sizeof(peer_stats_info->peer_macaddr));
+		peer_stats_info->tx_packets = stats_info.tx_packets;
+		peer_stats_info->tx_bytes = stats_info.tx_bytes;
+		peer_stats_info->rx_packets = stats_info.rx_packets;
+		peer_stats_info->rx_bytes = stats_info.rx_bytes;
+		peer_stats_info->tx_retries = stats_info.tx_retries;
+		peer_stats_info->tx_failed = stats_info.tx_failed;
+		peer_stats_info->tx_succeed = stats_info.tx_succeed;
+		peer_stats_info->rssi = stats_info.peer_rssi;
+		peer_stats_info->tx_rate = stats_info.last_tx_bitrate_kbps;
+		peer_stats_info->tx_rate_code = stats_info.last_tx_rate_code;
+		peer_stats_info->rx_rate = stats_info.last_rx_bitrate_kbps;
+		peer_stats_info->rx_rate_code = stats_info.last_rx_rate_code;
+		for (j = 0; j < WMI_MAX_CHAINS; j++)
+			peer_stats_info->peer_rssi_per_chain[j] =
+					      stats_info.peer_rssi_per_chain[j];
+		peer_stats_info++;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * target_if_mc_cp_stats_peer_stats_info_event_handler() - function to handle
+ * peer stats info event from firmware.
+ * @scn: scn handle
+ * @data: data buffer for event
+ * @datalen: data length
+ *
+ * Return: status of operation.
+ */
+static int target_if_mc_cp_stats_peer_stats_info_event_handler(ol_scn_t scn,
+							       uint8_t *data,
+							       uint32_t datalen)
+{
+	QDF_STATUS status;
+	struct stats_event ev = {0};
+	struct wlan_objmgr_psoc *psoc;
+	struct wmi_unified *wmi_handle;
+	struct wlan_lmac_if_cp_stats_rx_ops *rx_ops;
+
+	if (!scn || !data) {
+		cp_stats_err("scn: 0x%pK, data: 0x%pK", scn, data);
+		return -EINVAL;
+	}
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		cp_stats_err("null psoc");
+		return -EINVAL;
+	}
+
+	rx_ops = target_if_cp_stats_get_rx_ops(psoc);
+	if (!rx_ops || !rx_ops->process_stats_event) {
+		cp_stats_err("callback not registered");
+		return -EINVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		cp_stats_err("wmi_handle is null");
+		return -EINVAL;
+	}
+
+	status = target_if_cp_stats_extract_peer_stats_event(wmi_handle,
+							     &ev, data);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cp_stats_err("extract event failed");
+		goto end;
+	}
+
+	status = rx_ops->process_stats_event(psoc, &ev);
+
+end:
+	target_if_cp_stats_free_stats_event(&ev);
+
+	return qdf_status_to_os_return(status);
+}
+
 static void target_if_cp_stats_inc_wake_lock_stats(uint32_t reason,
 					struct wake_lock_stats *stats,
 					uint32_t *unspecified_wake_count)
@@ -916,6 +1042,13 @@ target_if_cp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc)
 	if (ret_val)
 		cp_stats_err("Failed to register stats event cb");
 
+	ret_val = wmi_unified_register_event_handler(wmi_handle,
+			    wmi_peer_stats_info_event_id,
+			    target_if_mc_cp_stats_peer_stats_info_event_handler,
+			    WMI_RX_WORK_CTX);
+	if (ret_val)
+		cp_stats_err("Failed to register peer stats info event cb");
+
 	return qdf_status_from_os_return(ret_val);
 }
 
@@ -934,6 +1067,8 @@ target_if_cp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
 		cp_stats_err("wmi_handle is null");
 		return QDF_STATUS_E_INVAL;
 	}
+	wmi_unified_unregister_event_handler(wmi_handle,
+					     wmi_peer_stats_info_event_id);
 	wmi_unified_unregister_event_handler(wmi_handle,
 					     wmi_update_stats_event_id);
 
@@ -1035,6 +1170,36 @@ target_if_cp_stats_register_handlers(struct wlan_objmgr_psoc *psoc)
 	return qdf_status;
 }
 
+/**
+ * target_if_cp_stats_send_peer_stats_req() - API to send peer stats request
+ * to wmi
+ * @psoc: pointer to psoc object
+ * @req: pointer to object containing peer stats request parameters
+ *
+ * Return: status of operation.
+ */
+static QDF_STATUS
+target_if_cp_stats_send_peer_stats_req(struct wlan_objmgr_psoc *psoc,
+				       struct request_info *req)
+
+{
+	struct wmi_unified *wmi_handle;
+	struct peer_stats_request_params param = {0};
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		cp_stats_err("wmi_handle is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	param.request_type = WMI_REQUEST_ONE_PEER_STATS_INFO;
+	param.vdev_id = req->vdev_id;
+	qdf_mem_copy(param.peer_mac_addr, req->peer_mac_addr,
+		     QDF_MAC_ADDR_SIZE);
+	param.reset_after_request = 0;
+
+	return wmi_unified_peer_stats_request_send(wmi_handle, &param);
+}
+
 QDF_STATUS
 target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 {
@@ -1058,6 +1223,8 @@ target_if_cp_stats_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 	cp_stats_tx_ops->inc_wake_lock_stats =
 		target_if_cp_stats_inc_wake_lock_stats;
 	cp_stats_tx_ops->send_req_stats = target_if_cp_stats_send_stats_req;
+	cp_stats_tx_ops->send_req_peer_stats =
+		target_if_cp_stats_send_peer_stats_req;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 100 - 0
components/wmi/inc/wmi_unified_mc_cp_stats_api.h

@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013-2020, 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * DOC: Implement API's specific to control path stats component.
+ */
+
+#ifndef _WMI_UNIFIED_MC_CP_STATS_API_H_
+#define _WMI_UNIFIED_MC_CP_STATS_API_H_
+
+#include <wlan_cp_stats_mc_defs.h>
+
+/**
+ * wmi_extract_per_chain_rssi_stats() - extract rssi stats from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @index: Index into rssi stats
+ * @rssi_stats: Pointer to hold rssi stats
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_extract_per_chain_rssi_stats(wmi_unified_t wmi_handle, void *evt_buf,
+			      uint32_t index,
+			      struct wmi_host_per_chain_rssi_stats *rssi_stats);
+
+/**
+ * wmi_extract_peer_adv_stats() - extract advance (extd2) peer stats from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @peer_adv_stats: Pointer to hold extended peer stats
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_extract_peer_adv_stats(wmi_unified_t wmi_handle, void *evt_buf,
+			   struct wmi_host_peer_adv_stats *peer_adv_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_unified_peer_stats_request_send() - send peer stats request to fw
+ * @wmi_handle: wmi handle
+ * @param: pointer to peer stats request parameters
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_unified_peer_stats_request_send(wmi_unified_t wmi_handle,
+				    struct peer_stats_request_params *param);
+
+/**
+ * wmi_extract_peer_stats_param() - extract all stats count from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @stats_param: Pointer to hold stats count
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_extract_peer_stats_param(wmi_unified_t wmi_handle, void *evt_buf,
+			     wmi_host_stats_event *stats_param);
+
+/**
+ * wmi_extract_peer_stats_info() - extract peer stats info from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @index: Index into beacon stats
+ * @peer_stats_info: Pointer to hold peer stats info
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_extract_peer_stats_info(wmi_unified_t wmi_handle, void *evt_buf,
+			    uint32_t index,
+			    wmi_host_peer_stats_info *peer_stats_info);
+#endif /* _WMI_UNIFIED_MC_CP_STATS_API_H_ */

+ 92 - 0
components/wmi/src/wmi_unified_mc_cp_stats_api.c

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016-2020, 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * DOC: Implement API's specific to cp stats component.
+ */
+
+#include "wmi_unified_priv.h"
+#include "wmi_unified_param.h"
+#include "wmi_unified_mc_cp_stats_api.h"
+
+QDF_STATUS
+wmi_extract_per_chain_rssi_stats(wmi_unified_t wmi_handle, void *evt_buf,
+			       uint32_t index,
+			       struct wmi_host_per_chain_rssi_stats *rssi_stats)
+{
+	if (wmi_handle->ops->extract_per_chain_rssi_stats)
+		return wmi_handle->ops->extract_per_chain_rssi_stats(wmi_handle,
+			evt_buf, index, rssi_stats);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wmi_extract_peer_adv_stats(wmi_unified_t wmi_handle, void *evt_buf,
+			   struct wmi_host_peer_adv_stats *peer_adv_stats)
+{
+	if (wmi_handle->ops->extract_peer_adv_stats)
+		return wmi_handle->ops->extract_peer_adv_stats(wmi_handle,
+			evt_buf, peer_adv_stats);
+
+	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_unified_peer_stats_request_send(wmi_unified_t wmi_handle,
+				    struct peer_stats_request_params *param)
+{
+	if (wmi_handle->ops->send_request_peer_stats_info_cmd)
+		return wmi_handle->ops->send_request_peer_stats_info_cmd(
+							     wmi_handle, param);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wmi_extract_peer_stats_param(wmi_unified_t wmi_handle, void *evt_buf,
+			     wmi_host_stats_event *stats_param)
+{
+	if (wmi_handle->ops->extract_peer_stats_count)
+		return wmi_handle->ops->extract_peer_stats_count(wmi_handle,
+			evt_buf, stats_param);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wmi_extract_peer_stats_info(wmi_unified_t wmi_handle, void *evt_buf,
+			    uint32_t index,
+			    wmi_host_peer_stats_info *peer_stats_info)
+{
+	if (wmi_handle->ops->extract_peer_stats_info)
+		return wmi_handle->ops->extract_peer_stats_info(wmi_handle,
+				evt_buf, index, peer_stats_info);
+
+	return QDF_STATUS_E_FAILURE;
+}

+ 433 - 0
components/wmi/src/wmi_unified_mc_cp_stats_tlv.c

@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2013-2020, 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "osdep.h"
+#include "wmi.h"
+#include "wmi_unified_priv.h"
+#include "wmi_unified_param.h"
+
+/**
+ * extract_per_chain_rssi_stats_tlv() - api to extract rssi stats from event
+ * buffer
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @index: Index into vdev stats
+ * @rssi_stats: Pointer to hold rssi stats
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS
+extract_per_chain_rssi_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
+			       uint32_t index,
+			       struct wmi_host_per_chain_rssi_stats *rssi_stats)
+{
+	uint8_t *data;
+	wmi_rssi_stats *fw_rssi_stats;
+	wmi_per_chain_rssi_stats *rssi_event;
+	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
+
+	if (!evt_buf) {
+		WMI_LOGE("evt_buf is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
+	rssi_event = param_buf->chain_stats;
+
+	if (index >= rssi_event->num_per_chain_rssi_stats) {
+		WMI_LOGE("invalid index");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	data = ((uint8_t *)(&rssi_event[1])) + WMI_TLV_HDR_SIZE;
+	fw_rssi_stats = &((wmi_rssi_stats *)data)[index];
+	if (fw_rssi_stats->vdev_id >= WLAN_UMAC_PDEV_MAX_VDEVS)
+		return QDF_STATUS_E_INVAL;
+
+	rssi_stats->vdev_id = fw_rssi_stats->vdev_id;
+	qdf_mem_copy(rssi_stats->rssi_avg_beacon,
+		     fw_rssi_stats->rssi_avg_beacon,
+		     sizeof(fw_rssi_stats->rssi_avg_beacon));
+	qdf_mem_copy(rssi_stats->rssi_avg_data,
+		     fw_rssi_stats->rssi_avg_data,
+		     sizeof(fw_rssi_stats->rssi_avg_data));
+	qdf_mem_copy(&rssi_stats->peer_macaddr,
+		     &fw_rssi_stats->peer_macaddr,
+		     sizeof(fw_rssi_stats->peer_macaddr));
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * extract_peer_adv_stats_tlv() - extract adv peer stats from event
+ * @param wmi_handle: wmi handle
+ * @param evt_buf: pointer to event buffer
+ * @param index: Index into extended peer stats
+ * @param peer_adv_stats: Pointer to hold adv peer stats
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS extract_peer_adv_stats_tlv(wmi_unified_t wmi_handle,
+					     void *evt_buf,
+					     struct wmi_host_peer_adv_stats
+					     *peer_adv_stats)
+{
+	WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
+	wmi_peer_extd2_stats *adv_stats;
+	int i;
+
+	param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
+
+	adv_stats = param_buf->peer_extd2_stats;
+	if (!adv_stats) {
+		WMI_LOGD("%s: no peer_adv stats in event buffer", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	for (i = 0; i < param_buf->num_peer_extd2_stats; i++) {
+		WMI_MAC_ADDR_TO_CHAR_ARRAY(&adv_stats[i].peer_macaddr,
+					   peer_adv_stats[i].peer_macaddr);
+		peer_adv_stats[i].fcs_count = adv_stats[i].rx_fcs_err;
+		peer_adv_stats[i].rx_bytes =
+				(uint64_t)adv_stats[i].rx_bytes_u32 <<
+				WMI_LOWER_BITS_SHIFT_32 |
+				adv_stats[i].rx_bytes_l32;
+		peer_adv_stats[i].rx_count = adv_stats[i].rx_mpdus;
+	}
+
+	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;
+}
+
+static void wmi_cp_stats_attach_mib_stats_tlv(struct wmi_ops *ops)
+{
+	ops->extract_mib_stats = extract_mib_stats_tlv;
+}
+#else
+static void wmi_cp_stats_attach_mib_stats_tlv(struct wmi_ops *ops)
+{
+}
+#endif /* WLAN_FEATURE_MIB_STATS */
+
+/**
+ * send_request_peer_stats_info_cmd_tlv() - WMI request peer stats function
+ * @wmi_handle: handle to WMI.
+ * @param: pointer to hold peer stats request parameter
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+send_request_peer_stats_info_cmd_tlv(wmi_unified_t wmi_handle,
+				     struct peer_stats_request_params *param)
+{
+	int32_t ret;
+	wmi_request_peer_stats_info_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	uint16_t len = sizeof(wmi_request_peer_stats_info_cmd_fixed_param);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf)
+		return QDF_STATUS_E_NOMEM;
+
+	cmd = (wmi_request_peer_stats_info_cmd_fixed_param *)wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		   WMITLV_TAG_STRUC_wmi_request_peer_stats_info_cmd_fixed_param,
+		   WMITLV_GET_STRUCT_TLVLEN(
+				  wmi_request_peer_stats_info_cmd_fixed_param));
+	cmd->request_type = param->request_type;
+	cmd->vdev_id = param->vdev_id;
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->peer_mac_addr, &cmd->peer_macaddr);
+	cmd->reset_after_request = param->reset_after_request;
+
+	WMI_LOGD("PEER STATS REQ VDEV_ID:%d PEER:%pM TYPE:%d RESET:%d",
+		 cmd->vdev_id, param->peer_mac_addr, cmd->request_type,
+		 cmd->reset_after_request);
+
+	wmi_mtrace(WMI_REQUEST_PEER_STATS_INFO_CMDID, cmd->vdev_id, 0);
+	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+				   WMI_REQUEST_PEER_STATS_INFO_CMDID);
+	if (ret) {
+		WMI_LOGE("Failed to send peer stats request to fw =%d", ret);
+		wmi_buf_free(buf);
+	}
+
+	return qdf_status_from_os_return(ret);
+}
+
+/**
+ * extract_peer_stats_count_tlv() - extract peer stats count from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @stats_param: Pointer to hold stats count
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS
+extract_peer_stats_count_tlv(wmi_unified_t wmi_handle, void *evt_buf,
+			     wmi_host_stats_event *stats_param)
+{
+	WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
+	wmi_peer_stats_info_event_fixed_param *ev_param;
+
+	param_buf = (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)evt_buf;
+	if (!param_buf)
+		return QDF_STATUS_E_FAILURE;
+
+	ev_param = param_buf->fixed_param;
+	if (!ev_param)
+		return QDF_STATUS_E_FAILURE;
+
+	if (!stats_param)
+		return QDF_STATUS_E_FAILURE;
+
+	stats_param->num_peer_stats_info_ext = ev_param->num_peers;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void dump_peer_stats_info(wmi_peer_stats_info *stats)
+{
+	u_int8_t mac[6];
+	int i;
+
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
+	WMI_LOGD("mac %pM", mac);
+	WMI_LOGD("tx_bytes %d %d tx_packets %d %d",
+		 stats->tx_bytes.low_32,
+		 stats->tx_bytes.high_32,
+		 stats->tx_packets.low_32,
+		 stats->tx_packets.high_32);
+	WMI_LOGD("rx_bytes %d %d rx_packets %d %d",
+		 stats->rx_bytes.low_32,
+		 stats->rx_bytes.high_32,
+		 stats->rx_packets.low_32,
+		 stats->rx_packets.high_32);
+	WMI_LOGD("tx_retries %d tx_failed %d",
+		 stats->tx_retries, stats->tx_failed);
+	WMI_LOGD("tx_rate_code %x rx_rate_code %x",
+		 stats->last_tx_rate_code,
+		 stats->last_rx_rate_code);
+	WMI_LOGD("tx_rate %x rx_rate %x",
+		 stats->last_tx_bitrate_kbps,
+		 stats->last_rx_bitrate_kbps);
+	WMI_LOGD("peer_rssi %d", stats->peer_rssi);
+	WMI_LOGD("tx_succeed %d", stats->tx_succeed);
+	for (i = 0; i < WMI_MAX_CHAINS; i++)
+		WMI_LOGD("chain%d_rssi %d", i, stats->peer_rssi_per_chain[i]);
+}
+
+/**
+ * extract_peer_stats_info_tlv() - extract peer stats info from event
+ * @wmi_handle: wmi handle
+ * @evt_buf: pointer to event buffer
+ * @index: Index into vdev stats
+ * @peer_stats_info: Pointer to hold peer stats info
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code
+ */
+static QDF_STATUS
+extract_peer_stats_info_tlv(wmi_unified_t wmi_handle, void *evt_buf,
+			    uint32_t index,
+			    wmi_host_peer_stats_info *peer_stats_info)
+{
+	WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
+	wmi_peer_stats_info_event_fixed_param *ev_param;
+
+	param_buf = (WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)evt_buf;
+	ev_param = param_buf->fixed_param;
+
+	if (index < ev_param->num_peers) {
+		wmi_peer_stats_info *ev = &param_buf->peer_stats_info[index];
+		int i;
+
+		dump_peer_stats_info(ev);
+
+		WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr,
+					   peer_stats_info->peer_macaddr.bytes);
+		peer_stats_info->tx_packets = ev->tx_packets.low_32;
+		peer_stats_info->tx_bytes = ev->tx_bytes.high_32;
+		peer_stats_info->tx_bytes <<= 32;
+		peer_stats_info->tx_bytes += ev->tx_bytes.low_32;
+		peer_stats_info->rx_packets = ev->rx_packets.low_32;
+		peer_stats_info->rx_bytes = ev->rx_bytes.high_32;
+		peer_stats_info->rx_bytes <<= 32;
+		peer_stats_info->rx_bytes += ev->rx_bytes.low_32;
+		peer_stats_info->tx_retries = ev->tx_retries;
+		peer_stats_info->tx_failed = ev->tx_failed;
+		peer_stats_info->tx_succeed = ev->tx_succeed;
+		peer_stats_info->peer_rssi = ev->peer_rssi;
+		peer_stats_info->last_tx_bitrate_kbps =
+						ev->last_tx_bitrate_kbps;
+		peer_stats_info->last_tx_rate_code = ev->last_tx_rate_code;
+		peer_stats_info->last_rx_bitrate_kbps =
+						ev->last_rx_bitrate_kbps;
+		peer_stats_info->last_rx_rate_code = ev->last_rx_rate_code;
+		for (i = 0; i < WMI_MAX_CHAINS; i++)
+			peer_stats_info->peer_rssi_per_chain[i] =
+						     ev->peer_rssi_per_chain[i];
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void wmi_mc_cp_stats_attach_tlv(wmi_unified_t wmi_handle)
+{
+	struct wmi_ops *ops = wmi_handle->ops;
+
+	ops->extract_per_chain_rssi_stats = extract_per_chain_rssi_stats_tlv;
+	ops->extract_peer_adv_stats = extract_peer_adv_stats_tlv;
+	wmi_cp_stats_attach_mib_stats_tlv(ops);
+	ops->send_request_peer_stats_info_cmd =
+		send_request_peer_stats_info_cmd_tlv;
+	ops->extract_peer_stats_count = extract_peer_stats_count_tlv;
+	ops->extract_peer_stats_info = extract_peer_stats_info_tlv;
+}

+ 20 - 9
core/hdd/src/wlan_hdd_station_info.c

@@ -29,6 +29,7 @@
 #include <linux/skbuff.h>
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
+#include <wlan_cfg80211_mc_cp_stats.h>
 #include <wlan_cp_stats_mc_ucfg_api.h>
 #include <wlan_hdd_stats.h>
 #include <wlan_hdd_hostapd.h>
@@ -1219,10 +1220,11 @@ static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
 {
 	struct sk_buff *skb = NULL;
 	uint32_t nl_buf_len;
-	struct sir_peer_info_ext peer_info;
-	bool txrx_rate = true;
+	struct stats_event *stats;
+	bool txrx_rate = false;
 	bool value;
 	QDF_STATUS status;
+	int ret;
 
 	nl_buf_len = NLMSG_HDRLEN;
 	nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
@@ -1236,15 +1238,24 @@ static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
 	status = ucfg_mlme_get_sap_get_peer_info(hdd_ctx->psoc, &value);
 	if (status != QDF_STATUS_SUCCESS)
 		hdd_err("Unable to fetch sap ger peer info");
-	if (!value ||
-	    wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
-		hdd_err("fail to get tx/rx rate");
-		txrx_rate = false;
-	} else {
-		stainfo->tx_rate = peer_info.tx_rate;
-		stainfo->rx_rate = peer_info.rx_rate;
+	if (value) {
+		stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(adapter->vdev,
+								 mac_addr.bytes,
+								 &ret);
+		if (ret || !stats) {
+			hdd_err("fail to get tx/rx rate");
+			wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
+		} else {
+			txrx_rate = true;
+		}
+	}
+
+	if (txrx_rate) {
+		stainfo->tx_rate = stats->peer_stats_info_ext->tx_rate;
+		stainfo->rx_rate = stats->peer_stats_info_ext->rx_rate;
 		nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
 			(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
+		wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
 	}
 
 	/* below info is only valid for HT/VHT mode */

+ 16 - 125
core/hdd/src/wlan_hdd_stats.c

@@ -4195,7 +4195,7 @@ static uint8_t hdd_get_rate_flags(uint32_t rate,
  * Return: None
  */
 static void wlan_hdd_fill_rate_info(struct hdd_fw_txrx_stats *txrx_stats,
-				    struct sir_peer_info_ext *peer_info)
+				    struct peer_stats_info_ext_event *peer_info)
 {
 	uint8_t flags;
 	uint32_t rate_code;
@@ -4280,8 +4280,7 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy,
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hddctx = wiphy_priv(wiphy);
 	struct hdd_station_info *stainfo = NULL;
-	struct qdf_mac_addr macaddr;
-	struct sir_peer_info_ext peer_info;
+	struct stats_event *stats;
 	struct hdd_fw_txrx_stats txrx_stats;
 	int status;
 
@@ -4298,9 +4297,10 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	qdf_mem_copy(macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
-	status = wlan_hdd_get_peer_info(adapter, macaddr, &peer_info);
-	if (status) {
+	stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(adapter->vdev,
+							 mac, &status);
+	if (status || !stats) {
+		wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
 		hdd_put_sta_info_ref(&adapter->sta_info_list, &stainfo, true,
 				     STA_INFO_WLAN_HDD_GET_STATION_REMOTE);
 		hdd_err("fail to get peer info from fw");
@@ -4308,15 +4308,17 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy,
 	}
 
 	qdf_mem_zero(&txrx_stats, sizeof(txrx_stats));
-	txrx_stats.tx_packets = peer_info.tx_packets;
-	txrx_stats.tx_bytes = peer_info.tx_bytes;
-	txrx_stats.rx_packets = peer_info.rx_packets;
-	txrx_stats.rx_bytes = peer_info.rx_bytes;
-	txrx_stats.tx_retries = peer_info.tx_retries;
-	txrx_stats.tx_failed = peer_info.tx_failed;
-	txrx_stats.rssi = peer_info.rssi + WLAN_HDD_TGT_NOISE_FLOOR_DBM;
-	wlan_hdd_fill_rate_info(&txrx_stats, &peer_info);
+	txrx_stats.tx_packets = stats->peer_stats_info_ext->tx_packets;
+	txrx_stats.tx_bytes = stats->peer_stats_info_ext->tx_bytes;
+	txrx_stats.rx_packets = stats->peer_stats_info_ext->rx_packets;
+	txrx_stats.rx_bytes = stats->peer_stats_info_ext->rx_bytes;
+	txrx_stats.tx_retries = stats->peer_stats_info_ext->tx_retries;
+	txrx_stats.tx_failed = stats->peer_stats_info_ext->tx_failed;
+	txrx_stats.rssi = stats->peer_stats_info_ext->rssi
+			+ WLAN_HDD_TGT_NOISE_FLOOR_DBM;
+	wlan_hdd_fill_rate_info(&txrx_stats, stats->peer_stats_info_ext);
 	wlan_hdd_fill_station_info(hddctx->psoc, sinfo, stainfo, &txrx_stats);
+	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
 	hdd_put_sta_info_ref(&adapter->sta_info_list, &stainfo, true,
 			     STA_INFO_WLAN_HDD_GET_STATION_REMOTE);
 
@@ -6006,117 +6008,6 @@ int wlan_hdd_get_link_speed(struct hdd_adapter *adapter, uint32_t *link_speed)
 	return 0;
 }
 
-struct peer_info_priv {
-	struct sir_peer_sta_ext_info peer_sta_ext_info;
-};
-
-/**
- * wlan_hdd_get_peer_info_cb() - get peer info callback
- * @sta_info: pointer of peer information
- * @context: get peer info callback context
- *
- * This function will fill stats info to peer info priv
- *
- */
-static void wlan_hdd_get_peer_info_cb(struct sir_peer_info_ext_resp *sta_info,
-				      void *context)
-{
-	struct osif_request *request;
-	struct peer_info_priv *priv;
-	uint8_t sta_num;
-
-	if ((!sta_info) || (!context)) {
-		hdd_err("Bad param, sta_info [%pK] context [%pK]",
-			sta_info, context);
-		return;
-	}
-
-	if (!sta_info->count) {
-		hdd_err("Fail to get remote peer info");
-		return;
-	}
-
-	if (sta_info->count > MAX_PEER_STA) {
-		hdd_warn("Exceed max peer number %d", sta_info->count);
-		sta_num = MAX_PEER_STA;
-	} else {
-		sta_num = sta_info->count;
-	}
-
-	request = osif_request_get(context);
-	if (!request) {
-		hdd_err("Obsolete request");
-		return;
-	}
-
-	priv = osif_request_priv(request);
-
-	priv->peer_sta_ext_info.sta_num = sta_num;
-	qdf_mem_copy(&priv->peer_sta_ext_info.info,
-		     sta_info->info,
-		     sta_num * sizeof(sta_info->info[0]));
-
-	osif_request_complete(request);
-	osif_request_put(request);
-}
-
-int wlan_hdd_get_peer_info(struct hdd_adapter *adapter,
-			   struct qdf_mac_addr macaddress,
-			   struct sir_peer_info_ext *peer_info_ext)
-{
-	QDF_STATUS status;
-	void *cookie;
-	int ret;
-	struct sir_peer_info_ext_req peer_info_req;
-	struct osif_request *request;
-	struct peer_info_priv *priv;
-	static const struct osif_request_params params = {
-		.priv_size = sizeof(*priv),
-		.timeout_ms = WLAN_WAIT_TIME_STATS,
-	};
-
-	if (!adapter) {
-		hdd_err("adapter is NULL");
-		return -EFAULT;
-	}
-
-	request = osif_request_alloc(&params);
-	if (!request) {
-		hdd_err("Request allocation failure");
-		return -ENOMEM;
-	}
-
-	cookie = osif_request_cookie(request);
-	priv = osif_request_priv(request);
-
-	qdf_mem_copy(&peer_info_req.peer_macaddr, &macaddress,
-		     QDF_MAC_ADDR_SIZE);
-	peer_info_req.sessionid = adapter->vdev_id;
-	peer_info_req.reset_after_request = 0;
-	status = sme_get_peer_info_ext(adapter->hdd_ctx->mac_handle,
-				       &peer_info_req,
-				       cookie,
-				       wlan_hdd_get_peer_info_cb);
-	if (status != QDF_STATUS_SUCCESS) {
-		hdd_err("Unable to retrieve statistics for peer info");
-		ret = -EFAULT;
-	} else {
-		ret = osif_request_wait_for_response(request);
-		if (ret) {
-			hdd_err("SME timed out while retrieving peer info");
-			ret = -EFAULT;
-		} else {
-			/* only support one peer by now */
-			*peer_info_ext = priv->peer_sta_ext_info.info[0];
-			ret = 0;
-		}
-	}
-
-	osif_request_put(request);
-
-	return ret;
-}
-
 int wlan_hdd_get_station_stats(struct hdd_adapter *adapter)
 {
 	int ret = 0;

+ 0 - 13
core/hdd/src/wlan_hdd_stats.h

@@ -461,19 +461,6 @@ int wlan_hdd_get_linkspeed_for_peermac(struct hdd_adapter *adapter,
  */
 int wlan_hdd_get_link_speed(struct hdd_adapter *adapter, uint32_t *link_speed);
 
-/**
- * wlan_hdd_get_peer_info() - get peer info
- * @adapter: hostapd interface
- * @macaddress: request peer mac address
- * @peer_info_ext: one peer extended info retrieved
- *
- * This function will call sme_get_peer_info_ext to get peer info
- *
- * Return: 0 on success, otherwise error value
- */
-int wlan_hdd_get_peer_info(struct hdd_adapter *adapter,
-			   struct qdf_mac_addr macaddress,
-			   struct sir_peer_info_ext *peer_info_ext);
 /**
  * wlan_hdd_get_station_stats() - Get station statistics
  * @adapter: adapter for which statistics are desired

+ 0 - 74
core/mac/inc/sir_api.h

@@ -2536,80 +2536,6 @@ struct link_speed_info {
 	uint32_t estLinkSpeed;  /* Linkspeed from firmware */
 };
 
-/**
- * struct sir_peer_info_ext_req - peer info request struct
- * @peer_macaddr: MAC address
- * @sessionid: vdev id
- * @reset_after_request: fw reset statistics after query
- *
- * peer info request message's struct
- */
-struct sir_peer_info_ext_req {
-	struct qdf_mac_addr peer_macaddr;
-	uint8_t sessionid;
-	uint8_t reset_after_request;
-};
-
-/**
- * struct sir_peer_info_ext - peer info information struct
- *                            (refer to station_info struct in Kernel)
- * @peer_macaddr: MAC address
- * @tx_packets: packets transmitted to this station
- * @tx_bytes: bytes transmitted to this station
- * @rx_packets: packets received from this station
- * @rx_bytes: bytes received from this station
- * @tx_retries: cumulative retry counts
- * @tx_failed: the number of failed frames
- * @tx_succeed: the number of succeed frames
- * @rssi: the signal strength
- * @tx_rate: last used tx bitrate (kbps)
- * @tx_rate_code: last tx rate code (last_tx_rate_code of wmi_peer_stats_info)
- * @rx_rate: last used rx bitrate (kbps)
- * @rx_rate_code: last rx rate code (last_rx_rate_code of wmi_peer_stats_info)
- * @peer_rssi_per_chain: the average value of RSSI (dbm) per chain
- *
- * a station's information
- */
-struct sir_peer_info_ext {
-	struct qdf_mac_addr peer_macaddr;
-	uint32_t tx_packets;
-	uint64_t tx_bytes;
-	uint32_t rx_packets;
-	uint64_t rx_bytes;
-	uint32_t tx_retries;
-	uint32_t tx_failed;
-	uint32_t tx_succeed;
-	int32_t rssi;
-	uint32_t tx_rate;
-	uint32_t tx_rate_code;
-	uint32_t rx_rate;
-	uint32_t rx_rate_code;
-	int32_t peer_rssi_per_chain[WMI_MAX_CHAINS];
-};
-
-/**
- * struct sir_peer_info_ext_resp - all peers' information struct
- * @count: peer's number
- * @info: peer information
- *
- * all station's information
- */
-struct sir_peer_info_ext_resp {
-	uint8_t count;
-	struct sir_peer_info_ext info[0];
-};
-
-/**
- * @sta_num: number of peer station which has valid info
- * @info: peer extended information
- *
- * all SAP peer station's extended information retrieved
- */
-struct sir_peer_sta_ext_info {
-	uint8_t sta_num;
-	struct sir_peer_info_ext info[MAX_PEER_STA];
-};
-
 /**
  * struct sir_isolation_resp - isolation info related structure
  * @isolation_chain0: isolation value for chain 0

+ 1 - 2
core/mac/src/include/sir_params.h

@@ -598,9 +598,8 @@ struct sir_cfg_action_frm_tb_ppdu {
 
 /*
  * Unused SIR_HAL_ITC_MSG_TYPES_BEGIN + 382 to
- * SIR_HAL_ITC_MSG_TYPES_BEGIN + 386
+ * SIR_HAL_ITC_MSG_TYPES_BEGIN + 387
  */
-#define SIR_HAL_GET_PEER_INFO_EXT           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 387)
 
 /* ARP Debug stats */
 #define SIR_HAL_SET_ARP_STATS_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 388)

+ 0 - 17
core/sme/inc/sme_api.h

@@ -2662,23 +2662,6 @@ int sme_set_cck_tx_fir_override(mac_handle_t mac_handle, int vdev_id);
 QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id,
 				uint32_t param_val);
 
-/**
- * sme_get_peer_info_ext() - sme api to get peer ext info
- * @mac_handle: Opaque handle to the global MAC context
- * @req: peer ext info request struct send to wma
- * @context: context of callback function
- * @callbackfn: hdd callback function when receive response
- *
- * This function will send WMA_GET_PEER_INFO_EXT to WMA
- *
- * Return: QDF_STATUS_SUCCESS or non-zero on failure
- */
-QDF_STATUS sme_get_peer_info_ext(mac_handle_t mac_handle,
-		struct sir_peer_info_ext_req *req,
-		void *context,
-		void (*callbackfn)(struct sir_peer_info_ext_resp *param,
-			void *pcontext));
-
 /**
  * sme_get_chain_rssi() - Get chain rssi
  * @mac_handle: Opaque handle to the global MAC context

+ 0 - 4
core/sme/inc/sme_internal.h

@@ -309,10 +309,6 @@ struct sme_context {
 	sme_link_speed_cb link_speed_cb;
 	void *link_speed_context;
 
-	/* get extended peer info callback */
-	void (*pget_peer_info_ext_ind_cb)(struct sir_peer_info_ext_resp *param,
-		void *pcontext);
-	void *pget_peer_info_ext_cb_context;
 	sme_get_isolation_cb get_isolation_cb;
 	void *get_isolation_cb_context;
 #ifdef FEATURE_WLAN_EXTSCAN

+ 0 - 56
core/sme/src/common/sme_api.c

@@ -2177,12 +2177,6 @@ QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg)
 		status = sme_stats_ext_event(mac, pMsg->bodyptr);
 		qdf_mem_free(pMsg->bodyptr);
 		break;
-	case eWNI_SME_GET_PEER_INFO_EXT_IND:
-		if (mac->sme.pget_peer_info_ext_ind_cb)
-			mac->sme.pget_peer_info_ext_ind_cb(pMsg->bodyptr,
-				mac->sme.pget_peer_info_ext_cb_context);
-		qdf_mem_free(pMsg->bodyptr);
-		break;
 	case eWNI_SME_FW_STATUS_IND:
 		status = sme_fw_state_resp(mac);
 		break;
@@ -7842,56 +7836,6 @@ QDF_STATUS sme_get_link_speed(mac_handle_t mac_handle,
 	return status;
 }
 
-QDF_STATUS sme_get_peer_info_ext(mac_handle_t mac_handle,
-		struct sir_peer_info_ext_req *req,
-		void *context,
-		void (*callbackfn)(struct sir_peer_info_ext_resp *param,
-			void *pcontext))
-{
-	QDF_STATUS status;
-	QDF_STATUS qdf_status;
-	struct mac_context *mac = MAC_CONTEXT(mac_handle);
-	struct scheduler_msg message = {0};
-
-	status = sme_acquire_global_lock(&mac->sme);
-	if (QDF_STATUS_SUCCESS == status) {
-		if (!callbackfn) {
-			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
-				"%s: Indication Call back is NULL",
-				__func__);
-			sme_release_global_lock(&mac->sme);
-			return QDF_STATUS_E_FAILURE;
-		}
-
-		mac->sme.pget_peer_info_ext_ind_cb = callbackfn;
-		mac->sme.pget_peer_info_ext_cb_context = context;
-
-		/* serialize the req through MC thread */
-		message.bodyptr =
-			qdf_mem_malloc(sizeof(struct sir_peer_info_ext_req));
-		if (!message.bodyptr) {
-			sme_release_global_lock(&mac->sme);
-			return QDF_STATUS_E_NOMEM;
-		}
-		qdf_mem_copy(message.bodyptr,
-				req,
-				sizeof(struct sir_peer_info_ext_req));
-		message.type = WMA_GET_PEER_INFO_EXT;
-		qdf_status = scheduler_post_message(QDF_MODULE_ID_SME,
-						    QDF_MODULE_ID_WMA,
-						    QDF_MODULE_ID_WMA,
-						    &message);
-		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
-				"%s: Post get rssi msg fail", __func__);
-			qdf_mem_free(message.bodyptr);
-			status = QDF_STATUS_E_FAILURE;
-		}
-		sme_release_global_lock(&mac->sme);
-	}
-	return status;
-}
-
 QDF_STATUS sme_get_isolation(mac_handle_t mac_handle, void *context,
 			     sme_get_isolation_cb callbackfn)
 {

+ 0 - 25
core/wma/inc/wma_internal.h

@@ -1246,18 +1246,6 @@ QDF_STATUS wma_sar_register_event_handlers(WMA_HANDLE handle);
 void wma_process_link_status_req(tp_wma_handle wma,
 				 tAniGetLinkStatus *pGetLinkStatus);
 
-/**
- * wma_get_peer_info_ext() - get peer info
- * @handle: wma interface
- * @peer_info_req: get peer info request information
- *
- * This function will send WMI_REQUEST_PEER_STATS_INFO_CMDID to FW
- *
- * Return: 0 on success, otherwise error value
- */
-QDF_STATUS wma_get_peer_info_ext(WMA_HANDLE handle,
-				struct sir_peer_info_ext_req *peer_info_req);
-
 /**
  * wma_get_isolation() - get antenna isolation
  * @handle: wma interface
@@ -1268,19 +1256,6 @@ QDF_STATUS wma_get_peer_info_ext(WMA_HANDLE handle,
  */
 QDF_STATUS wma_get_isolation(tp_wma_handle wma);
 
-/**
- * wma_peer_info_event_handler() - Handler for WMI_PEER_STATS_INFO_EVENTID
- * @handle: WMA global handle
- * @cmd_param_info: Command event data
- * @len: Length of cmd_param_info
- *
- * This function will handle WMI_PEER_STATS_INFO_EVENTID
- *
- * Return: 0 on success, error code otherwise
- */
-int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
-				   u_int32_t len);
-
 int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf,
 				       uint32_t len);
 

+ 0 - 2
core/wma/inc/wma_types.h

@@ -308,8 +308,6 @@
 #define WMA_DISASSOC_TX_COMP       SIR_HAL_DISASSOC_TX_COMP
 #define WMA_DEAUTH_TX_COMP         SIR_HAL_DEAUTH_TX_COMP
 
-#define WMA_GET_PEER_INFO_EXT      SIR_HAL_GET_PEER_INFO_EXT
-
 #define WMA_GET_ISOLATION          SIR_HAL_GET_ISOLATION
 
 #define WMA_MODEM_POWER_STATE_IND SIR_HAL_MODEM_POWER_STATE_IND

+ 0 - 54
core/wma/src/wma_features.c

@@ -723,60 +723,6 @@ QDF_STATUS wma_get_link_speed(WMA_HANDLE handle,
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wma_get_peer_info_ext(WMA_HANDLE handle,
-				struct sir_peer_info_ext_req *peer_info_req)
-{
-	tp_wma_handle wma_handle = (tp_wma_handle)handle;
-	wmi_request_peer_stats_info_cmd_fixed_param *cmd;
-	wmi_buf_t  wmi_buf;
-	uint32_t  len;
-	uint8_t *buf_ptr;
-
-	if (!wma_handle || !wma_handle->wmi_handle) {
-		wma_err("WMA is closed, can not issue get rssi");
-		return QDF_STATUS_E_INVAL;
-	}
-
-	wma_debug("send WMI_REQUEST_PEER_STATS_INFO_CMDID");
-
-	len  = sizeof(wmi_request_peer_stats_info_cmd_fixed_param);
-	wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
-	if (!wmi_buf)
-		return QDF_STATUS_E_NOMEM;
-
-	buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf);
-
-	cmd = (wmi_request_peer_stats_info_cmd_fixed_param *)buf_ptr;
-	WMITLV_SET_HDR(&cmd->tlv_header,
-		WMITLV_TAG_STRUC_wmi_request_peer_stats_info_cmd_fixed_param,
-		WMITLV_GET_STRUCT_TLVLEN(
-			wmi_request_peer_stats_info_cmd_fixed_param));
-	cmd->vdev_id = peer_info_req->sessionid;
-	cmd->request_type = WMI_REQUEST_ONE_PEER_STATS_INFO;
-	wma_handle->get_one_peer_info = true;
-	WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_info_req->peer_macaddr.bytes,
-			&cmd->peer_macaddr);
-	cmd->reset_after_request = peer_info_req->reset_after_request;
-
-	if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
-				WMI_REQUEST_PEER_STATS_INFO_CMDID)) {
-		wmi_buf_free(wmi_buf);
-		return QDF_STATUS_E_FAILURE;
-	}
-
-	wma_info("vdev_id %d, mac %pM, req_type %x, reset %x",
-		cmd->vdev_id,
-		peer_info_req->peer_macaddr.bytes,
-		cmd->request_type,
-		cmd->reset_after_request);
-
-	qdf_mem_copy(&(wma_handle->peer_macaddr),
-					&(peer_info_req->peer_macaddr),
-					QDF_MAC_ADDR_SIZE);
-
-	return QDF_STATUS_SUCCESS;
-}
-
 QDF_STATUS wma_get_isolation(tp_wma_handle wma)
 {
 	wmi_coex_get_antenna_isolation_cmd_fixed_param *cmd;

+ 0 - 10
core/wma/src/wma_main.c

@@ -3098,12 +3098,6 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc,
 	/* register for fw state response event */
 	wma_register_fw_state_events(wma_handle->wmi_handle);
 
-	/* register for peer info response event */
-	wmi_unified_register_event_handler(wma_handle->wmi_handle,
-					   wmi_peer_stats_info_event_id,
-					   wma_peer_info_event_handler,
-					   WMA_RX_SERIALIZER_CTX);
-
 #ifdef WLAN_POWER_DEBUG
 	/* register for Chip Power stats event */
 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
@@ -8569,10 +8563,6 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg)
 					  (tDisableIntraBssFwd *) msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
-	case WMA_GET_PEER_INFO_EXT:
-		wma_get_peer_info_ext(wma_handle, msg->bodyptr);
-		qdf_mem_free(msg->bodyptr);
-		break;
 	case WMA_GET_ISOLATION:
 		wma_get_isolation(wma_handle);
 		break;

+ 0 - 218
core/wma/src/wma_utils.c

@@ -2937,224 +2937,6 @@ int wma_rso_cmd_status_event_handler(wmi_roam_event_fixed_param *wmi_event)
 	return 0;
 }
 
-/**
- * wma_fill_peer_info() - fill SIR peer info from WMI peer info struct
- * @wma: wma interface
- * @stats_info: WMI peer info pointer
- * @peer_info: SIR peer info pointer
- *
- * This function will fill SIR peer info from WMI peer info struct
- *
- * Return: None
- */
-static void wma_fill_peer_info(tp_wma_handle wma,
-		wmi_peer_stats_info *stats_info,
-		struct sir_peer_info_ext *peer_info)
-{
-	int i;
-
-	peer_info->tx_packets = stats_info->tx_packets.low_32;
-	peer_info->tx_bytes = stats_info->tx_bytes.high_32;
-	peer_info->tx_bytes <<= 32;
-	peer_info->tx_bytes += stats_info->tx_bytes.low_32;
-	peer_info->rx_packets = stats_info->rx_packets.low_32;
-	peer_info->rx_bytes = stats_info->rx_bytes.high_32;
-	peer_info->rx_bytes <<= 32;
-	peer_info->rx_bytes += stats_info->rx_bytes.low_32;
-	peer_info->tx_retries = stats_info->tx_retries;
-	peer_info->tx_failed = stats_info->tx_failed;
-	peer_info->tx_succeed = stats_info->tx_succeed;
-	peer_info->rssi = stats_info->peer_rssi;
-	peer_info->tx_rate = stats_info->last_tx_bitrate_kbps;
-	peer_info->tx_rate_code = stats_info->last_tx_rate_code;
-	peer_info->rx_rate = stats_info->last_rx_bitrate_kbps;
-	peer_info->rx_rate_code = stats_info->last_rx_rate_code;
-	for (i = 0; i < WMI_MAX_CHAINS; i++)
-		peer_info->peer_rssi_per_chain[i] =
-				stats_info->peer_rssi_per_chain[i];
-}
-
-/**
- * wma_peer_info_ext_rsp() - process peer ext info ext
- * @handle: wma interface
- * @buf: wmi event buf pointer
- *
- * This function will send eWNI_SME_GET_PEER_INFO_EXT_IND to SME
- *
- * Return: 0 on success, error code otherwise
- */
-static QDF_STATUS wma_peer_info_ext_rsp(tp_wma_handle wma, u_int8_t *buf)
-{
-	wmi_peer_stats_info_event_fixed_param *event;
-	wmi_peer_stats_info *stats_info;
-	struct sir_peer_info_ext_resp *resp;
-	struct sir_peer_info_ext *peer_info;
-	struct scheduler_msg sme_msg = {0};
-	int i, j = 0;
-	QDF_STATUS qdf_status;
-
-	event = (wmi_peer_stats_info_event_fixed_param *)buf;
-	stats_info = (wmi_peer_stats_info *)(buf +
-			sizeof(wmi_peer_stats_info_event_fixed_param));
-
-	if (wma->get_one_peer_info) {
-		resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
-				sizeof(resp->info[0]));
-		if (!resp)
-			return QDF_STATUS_E_NOMEM;
-
-		resp->count = 0;
-		peer_info = &resp->info[0];
-		for (i = 0; i < event->num_peers; i++) {
-			WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
-					peer_info->peer_macaddr.bytes);
-
-			if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
-					wma->peer_macaddr.bytes,
-					QDF_MAC_ADDR_SIZE)) {
-				wma_fill_peer_info(wma, stats_info, peer_info);
-				resp->count++;
-				break;
-			}
-
-			stats_info = stats_info + 1;
-		}
-	} else {
-		resp = qdf_mem_malloc(sizeof(struct sir_peer_info_ext_resp) +
-				event->num_peers * sizeof(resp->info[0]));
-		if (!resp)
-			return QDF_STATUS_E_NOMEM;
-
-		resp->count = event->num_peers;
-		for (i = 0; i < event->num_peers; i++) {
-			peer_info = &resp->info[j];
-			WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats_info->peer_macaddr,
-					peer_info->peer_macaddr.bytes);
-
-			if (!qdf_mem_cmp(peer_info->peer_macaddr.bytes,
-					wma->myaddr, QDF_MAC_ADDR_SIZE)) {
-				resp->count = resp->count - 1;
-			} else {
-				wma_fill_peer_info(wma, stats_info, peer_info);
-				j++;
-			}
-			stats_info = stats_info + 1;
-		}
-	}
-
-	sme_msg.type = eWNI_SME_GET_PEER_INFO_EXT_IND;
-	sme_msg.bodyptr = resp;
-	sme_msg.bodyval = 0;
-
-	qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
-					    QDF_MODULE_ID_SME,
-					    QDF_MODULE_ID_SME, &sme_msg);
-	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-		wma_err("Fail to post get peer info msg");
-		qdf_mem_free(resp);
-	}
-
-	return qdf_status;
-}
-
-/**
- * dump_peer_stats_info() - dump wmi peer info struct
- * @event: wmi peer info fixed param pointer
- * @peer_stats: wmi peer stats info pointer
- *
- * This function will dump wmi peer info struct
- *
- * Return: None
- */
-static void dump_peer_stats_info(wmi_peer_stats_info_event_fixed_param *event,
-		wmi_peer_stats_info *peer_stats)
-{
-	int i, j;
-	wmi_peer_stats_info *stats = peer_stats;
-	u_int8_t mac[6];
-
-	wma_debug("vdev_id %d, num_peers %d more_data %d",
-		 event->vdev_id,
-		 event->num_peers, event->more_data);
-
-	for (i = 0; i < event->num_peers; i++) {
-		WMI_MAC_ADDR_TO_CHAR_ARRAY(&stats->peer_macaddr, mac);
-		wma_nofl_debug("mac %pM", mac);
-		wma_nofl_debug("tx_bytes %d %d tx_packets %d %d",
-			      stats->tx_bytes.low_32,
-			      stats->tx_bytes.high_32,
-			      stats->tx_packets.low_32,
-			      stats->tx_packets.high_32);
-		wma_nofl_debug("rx_bytes %d %d rx_packets %d %d",
-			      stats->rx_bytes.low_32,
-			      stats->rx_bytes.high_32,
-			      stats->rx_packets.low_32,
-			      stats->rx_packets.high_32);
-		wma_nofl_debug("tx_retries %d tx_failed %d",
-			      stats->tx_retries, stats->tx_failed);
-		wma_nofl_debug("tx_rate_code %x rx_rate_code %x",
-			      stats->last_tx_rate_code,
-			      stats->last_rx_rate_code);
-		wma_nofl_debug("tx_rate %x rx_rate %x",
-			      stats->last_tx_bitrate_kbps,
-			      stats->last_rx_bitrate_kbps);
-		wma_nofl_debug("peer_rssi %d", stats->peer_rssi);
-		wma_nofl_debug("tx_succeed %d", stats->tx_succeed);
-		for (j = 0; j < WMI_MAX_CHAINS; j++)
-			wma_nofl_debug("chain%d_rssi %d", j,
-				      stats->peer_rssi_per_chain[j]);
-
-		stats++;
-	}
-}
-
-int wma_peer_info_event_handler(void *handle, u_int8_t *cmd_param_info,
-				   u_int32_t len)
-{
-	tp_wma_handle wma = (tp_wma_handle) handle;
-	WMI_PEER_STATS_INFO_EVENTID_param_tlvs *param_buf;
-	wmi_peer_stats_info_event_fixed_param *event;
-	u_int32_t buf_size;
-	u_int8_t *buf;
-
-	param_buf =
-		(WMI_PEER_STATS_INFO_EVENTID_param_tlvs *)cmd_param_info;
-	if (!param_buf) {
-		wma_err("Invalid stats event");
-		return -EINVAL;
-	}
-
-	wma_debug("Recv WMI_PEER_STATS_INFO_EVENTID");
-	event = param_buf->fixed_param;
-	if (event->num_peers >
-	    ((WMI_SVC_MSG_MAX_SIZE -
-	      sizeof(wmi_peer_stats_info_event_fixed_param))/
-	      sizeof(wmi_peer_stats_info)) || event->num_peers >
-	      param_buf->num_peer_stats_info) {
-		wma_err("Excess num of peers from fw: %d, num_peer_stats_info:%d",
-			event->num_peers, param_buf->num_peer_stats_info);
-		return -EINVAL;
-	}
-	buf_size = sizeof(wmi_peer_stats_info_event_fixed_param) +
-		sizeof(wmi_peer_stats_info) * event->num_peers;
-	buf = qdf_mem_malloc(buf_size);
-	if (!buf)
-		return -ENOMEM;
-
-	qdf_mem_copy(buf, param_buf->fixed_param,
-			sizeof(wmi_peer_stats_info_event_fixed_param));
-	qdf_mem_copy((buf + sizeof(wmi_peer_stats_info_event_fixed_param)),
-			param_buf->peer_stats_info,
-			sizeof(wmi_peer_stats_info) * event->num_peers);
-	wma_debug("dump peer stats info");
-	dump_peer_stats_info(event, param_buf->peer_stats_info);
-
-	wma_peer_info_ext_rsp(wma, buf);
-	qdf_mem_free(buf);
-
-	return 0;
-}
-
 /**
  * wma_send_link_speed() - send link speed to SME
  * @link_speed: link speed

+ 123 - 0
os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c

@@ -72,6 +72,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);
+	qdf_mem_free(stats->peer_stats_info_ext);
 	wlan_free_mib_stats(stats);
 }
 
@@ -718,6 +719,127 @@ get_mib_stats_fail:
 }
 #endif
 
+/**
+ * get_peer_stats_cb() - get_peer_stats_cb callback function
+ * @ev: peer stats buffer
+ * @cookie: a cookie for the request context
+ *
+ * Return: None
+ */
+static void get_peer_stats_cb(struct stats_event *ev, void *cookie)
+{
+	struct stats_event *priv;
+	struct osif_request *request;
+	uint32_t peer_stats_info_size;
+
+	request = osif_request_get(cookie);
+	if (!request) {
+		osif_err("Obsolete request");
+		return;
+	}
+
+	priv = osif_request_priv(request);
+	peer_stats_info_size = sizeof(*ev->peer_stats_info_ext) *
+			       ev->num_peer_stats_info_ext;
+
+	if (priv->peer_stats_info_ext) {
+		osif_err("invalid context cookie %pK request %pK",
+			 cookie, request);
+		goto peer_stats_cb_fail;
+	}
+
+	priv->peer_stats_info_ext = qdf_mem_malloc(peer_stats_info_size);
+	if (!priv->peer_stats_info_ext)
+		goto peer_stats_cb_fail;
+
+	qdf_mem_copy(priv->peer_stats_info_ext, ev->peer_stats_info_ext,
+		     peer_stats_info_size);
+
+peer_stats_cb_fail:
+	osif_request_complete(request);
+	osif_request_put(request);
+}
+
+struct stats_event *
+wlan_cfg80211_mc_cp_stats_get_peer_stats(struct wlan_objmgr_vdev *vdev,
+					 const uint8_t *mac_addr,
+					 int *errno)
+{
+	void *cookie;
+	QDF_STATUS status;
+	struct stats_event *priv, *out;
+	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,
+	};
+
+	osif_debug("Enter");
+
+	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_peer_stats_cb = get_peer_stats_cb;
+	info.vdev_id = wlan_vdev_get_id(vdev);
+	info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
+	qdf_mem_copy(info.peer_mac_addr, mac_addr, QDF_MAC_ADDR_SIZE);
+	status = ucfg_mc_cp_stats_send_stats_request(vdev,
+						     TYPE_PEER_STATS_INFO_EXT,
+						     &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_peer_stats_fail;
+	}
+
+	*errno = osif_request_wait_for_response(request);
+	if (*errno) {
+		osif_err("wait failed or timed out ret: %d", *errno);
+		goto get_peer_stats_fail;
+	}
+
+	if (!priv->peer_stats_info_ext || priv->num_peer_stats_info_ext == 0) {
+		osif_err("Invalid stats");
+		osif_err("Peer stats info ext %d:%pK",
+			 priv->num_peer_stats_info_ext,
+			 priv->peer_stats_info_ext);
+		*errno = -EINVAL;
+		goto get_peer_stats_fail;
+	}
+
+	out->num_peer_stats_info_ext = priv->num_peer_stats_info_ext;
+	out->peer_stats_info_ext = priv->peer_stats_info_ext;
+	priv->peer_stats_info_ext = NULL;
+	osif_request_put(request);
+
+	osif_debug("Exit");
+
+	return out;
+
+get_peer_stats_fail:
+	osif_request_put(request);
+	wlan_cfg80211_mc_cp_stats_free_stats_event(out);
+
+	osif_debug("Exit");
+
+	return NULL;
+}
+
 void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats)
 {
 	if (!stats)
@@ -730,5 +852,6 @@ void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats)
 	qdf_mem_free(stats->vdev_chain_rssi);
 	qdf_mem_free(stats->peer_adv_stats);
 	wlan_free_mib_stats(stats);
+	qdf_mem_free(stats->peer_stats_info_ext);
 	qdf_mem_free(stats);
 }