diff --git a/Kbuild b/Kbuild index cd55e72b865c..cc08c944b125 100644 --- a/Kbuild +++ b/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 diff --git a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h index 0cf54d33580b..f38077ebccf9 100644 --- a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h +++ b/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__ */ diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 7b0606a4bef3..dae38ecc1d09 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/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; } diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index f669c8a4c7f3..b128892f444a 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/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)); } diff --git a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c index 90aa692ac18f..cf5a62994e1d 100644 --- a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/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, ¶m); +} + 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; } diff --git a/components/wmi/inc/wmi_unified_mc_cp_stats_api.h b/components/wmi/inc/wmi_unified_mc_cp_stats_api.h new file mode 100644 index 000000000000..552df77ecb1a --- /dev/null +++ b/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 + +/** + * 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_ */ diff --git a/components/wmi/src/wmi_unified_mc_cp_stats_api.c b/components/wmi/src/wmi_unified_mc_cp_stats_api.c new file mode 100644 index 000000000000..78660151e80b --- /dev/null +++ b/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; +} diff --git a/components/wmi/src/wmi_unified_mc_cp_stats_tlv.c b/components/wmi/src/wmi_unified_mc_cp_stats_tlv.c new file mode 100644 index 000000000000..c2153706b0e0 --- /dev/null +++ b/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 = ¶m_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; +} diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c index cff6f024cada..9ef342102b86 100644 --- a/core/hdd/src/wlan_hdd_station_info.c +++ b/core/hdd/src/wlan_hdd_station_info.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -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 */ diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index a87ca7aba02e..2f929d251e8c 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/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(¶ms); - 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; diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index 7fff71d19ce0..2abdfd5f7d91 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/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 diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 3b09b203d5b4..6972d7d83f61 100644 --- a/core/mac/inc/sir_api.h +++ b/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 diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 0e9825bec023..fe595f6b3f52 100644 --- a/core/mac/src/include/sir_params.h +++ b/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) diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index cd4e76150959..43f9303b6f06 100644 --- a/core/sme/inc/sme_api.h +++ b/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 diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 498069dc650e..670cb06c2119 100644 --- a/core/sme/inc/sme_internal.h +++ b/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 diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index dc887e541574..8cfebf2c6782 100644 --- a/core/sme/src/common/sme_api.c +++ b/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) { diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 114d826c82ea..31a594f74fac 100644 --- a/core/wma/inc/wma_internal.h +++ b/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); diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index eccd14340126..32ef0aca7bdf 100644 --- a/core/wma/inc/wma_types.h +++ b/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 diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 6d3791090dd9..3b3db367b55c 100644 --- a/core/wma/src/wma_features.c +++ b/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; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 713398f3ed45..7d4697d39cb6 100644 --- a/core/wma/src/wma_main.c +++ b/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; diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 78fa54d93c66..4163d57b244f 100644 --- a/core/wma/src/wma_utils.c +++ b/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 diff --git a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index bd880a2a1e94..a2f7dbcfb5c7 100644 --- a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/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(¶ms); + 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); }