qcacld-3.0: Add support for ctrl path stats infrastructure

Implement support for sending new control path stats
infrastructure via WMI_REQUEST_CTRL_PATH_STATS_CMDID and
WMI_CTRL_PATH_STATS_EVENTID in cp stats component. Also add
support for TWT Get statistics through this new method.

Change-Id: I62b3a525cde797cd5b809ca9e8e6c91d5651c6b4
CRs-Fixed: 2851016
This commit is contained in:
Rajasekaran Kalidoss 2020-11-26 21:20:26 +05:30 committed by snandini
parent 3208dfe908
commit ebcefb3044
7 changed files with 610 additions and 9 deletions

5
Kbuild
View File

@ -2036,7 +2036,9 @@ CP_STATS_OBJS := $(CP_MC_STATS_COMPONENT_SRC)/wlan_cp_stats_mc_tgt_api.o \
$(CP_STATS_CORE_SRC)/wlan_cp_stats_obj_mgr_handler.o \
$(CP_STATS_CORE_SRC)/wlan_cp_stats_ol_api.o \
$(CP_MC_STATS_OS_IF_SRC)/wlan_cfg80211_mc_cp_stats.o \
$(CP_STATS_DISPATCHER_SRC)/wlan_cp_stats_utils_api.o
$(CP_STATS_DISPATCHER_SRC)/wlan_cp_stats_utils_api.o \
$(WLAN_COMMON_ROOT)/target_if/cp_stats/src/target_if_cp_stats.o \
$(CP_STATS_DISPATCHER_SRC)/wlan_cp_stats_ucfg_api.o
endif
$(call add-wlan-objs,cp_stats,$(CP_STATS_OBJS))
@ -2652,6 +2654,7 @@ cppflags-$(CONFIG_WLAN_WEXT_SUPPORT_ENABLE) += -DWLAN_WEXT_SUPPORT_ENABLE
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) += -DWLAN_SUPPORT_INFRA_CTRL_PATH_STATS
cppflags-$(CONFIG_CP_STATS) += -DQCA_SUPPORT_CP_STATS
cppflags-$(CONFIG_CP_STATS) += -DQCA_SUPPORT_MC_CP_STATS
cppflags-$(CONFIG_DCS) += -DDCS_INTERFERENCE_DETECTION

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2021 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
@ -31,6 +31,10 @@
/* For WMI_MAX_CHAINS */
#include "wmi_unified.h"
#ifdef QCA_SUPPORT_MC_CP_STATS
#include "wlan_cp_stats_public_structs.h"
#endif
#ifdef WLAN_SUPPORT_TWT
#include <wmi_unified_twt_param.h>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2018, 2021 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
@ -48,14 +48,31 @@ uint8_t target_if_mc_cp_get_mac_id(struct vdev_mlme_obj *vdev_mlme);
* @psoc: pointer to psoc object
* @event: event parameters
*
* Return: QDF_STATUS_SUCCESS on Success, other QDF_STATUS error codes on
* failure
*/
QDF_STATUS
tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev);
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
/**
* tgt_mc_cp_stats_process_infra_stats_event(): API to process event from
* cp stats infrastrucure
* @psoc: pointer to psoc object
* @infra_event: infra cp stats event parameters
*
* Return: status of operation
*/
QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
struct stats_event *event);
QDF_STATUS tgt_mc_cp_stats_process_infra_stats_event(
struct wlan_objmgr_psoc *psoc,
struct infra_cp_stats_event *infra_event);
#endif
/**
* tgt_send_mc_cp_stats_req(): API to send stats request to lmac
* @psoc: pointer to psoc object
* @req: pointer to stats request
*
* Return: status of operation
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021 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
@ -153,6 +153,20 @@ QDF_STATUS ucfg_mc_cp_stats_send_stats_request(struct wlan_objmgr_vdev *vdev,
enum stats_req_type type,
struct request_info *info);
/**
* wlan_cfg80211_mc_twt_get_infra_cp_stats() - send twt get statistic request
* @vdev: pointer to vdev object
* @dialog_id: TWT session dialog id
* @twt_peer_mac: mac address of the peer
* @errno: error code
*
* Return: pointer to infra cp stats event for success or NULL for failure
*/
struct infra_cp_stats_event *
wlan_cfg80211_mc_twt_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
uint32_t dialog_id,
uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE],
int *errno);
/**
* ucfg_mc_cp_stats_get_tx_power() - API to fetch tx_power
* @vdev: pointer to vdev object
@ -184,7 +198,6 @@ bool ucfg_mc_cp_stats_is_req_pending(struct wlan_objmgr_psoc *psoc,
QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *req);
/**
* ucfg_mc_cp_stats_reset_pending_req() - API to reset pending request
* @psoc: pointer to psoc object
@ -213,10 +226,20 @@ QDF_STATUS ucfg_mc_cp_stats_get_pending_req(struct wlan_objmgr_psoc *psoc,
enum stats_req_type type,
struct request_info *info);
/**
* ucfg_mc_infra_cp_stats_free_stats_resources() - API to free buffers within
* infra cp stats_event structure
* @ev: structure whose buffer are to freed
*
* Return: none
*/
void
ucfg_mc_infra_cp_stats_free_stats_resources(struct infra_cp_stats_event *ev);
/**
* ucfg_mc_cp_stats_free_stats_resources() - API to free buffers within stats_event
* structure
* @ev: strcture whose buffer are to freed
* @ev: structure whose buffer are to freed
*
* Return: none
*/

View File

@ -26,10 +26,12 @@
#include "wlan_cp_stats_mc_defs.h"
#include "target_if_cp_stats.h"
#include "wlan_cp_stats_tgt_api.h"
#include "wlan_cp_stats_ucfg_api.h"
#include "wlan_cp_stats_mc_tgt_api.h"
#include <wlan_cp_stats_mc_ucfg_api.h>
#include <wlan_cp_stats_utils_api.h>
#include "../../core/src/wlan_cp_stats_defs.h"
#include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
static bool tgt_mc_cp_stats_is_last_event(struct stats_event *ev,
enum stats_req_type stats_type)
@ -51,10 +53,25 @@ static bool tgt_mc_cp_stats_is_last_event(struct stats_event *ev,
return is_last_event;
}
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
static void
tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
{
rx_ops->cp_stats_rx_ops.process_infra_stats_event =
tgt_mc_cp_stats_process_infra_stats_event;
}
#else
static void
tgt_cp_stats_register_infra_cp_stats_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
{
}
#endif
void tgt_cp_stats_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
{
rx_ops->cp_stats_rx_ops.process_stats_event =
tgt_mc_cp_stats_process_stats_event;
tgt_cp_stats_register_infra_cp_stats_rx_ops(rx_ops);
}
static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
@ -614,6 +631,37 @@ tgt_mc_cp_stats_extract_peer_stats_info_ext(struct wlan_objmgr_psoc *psoc,
}
}
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
#ifdef WLAN_SUPPORT_TWT
static void
tgt_mc_infra_cp_stats_extract_twt_stats(struct wlan_objmgr_psoc *psoc,
struct infra_cp_stats_event *ev)
{
QDF_STATUS status;
get_infra_cp_stats_cb resp_cb;
void *context;
status = wlan_cp_stats_infra_cp_get_context(psoc, &resp_cb, &context);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_get_infra_cp_stats_context failed");
return;
}
cp_stats_debug("num_twt_infra_cp_stats = %d action %d",
ev->num_twt_infra_cp_stats, ev->action);
if (resp_cb)
resp_cb(ev, context);
}
#else
static void
tgt_mc_infra_cp_stats_extract_twt_stats(struct wlan_objmgr_psoc *psoc,
struct infra_cp_stats_event *ev)
{
}
#endif
#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
@ -977,6 +1025,20 @@ static void tgt_mc_cp_send_lost_link_stats(struct wlan_objmgr_psoc *psoc,
psoc_cp_stats_priv->legacy_stats_cb(ev);
}
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
QDF_STATUS tgt_mc_cp_stats_process_infra_stats_event(
struct wlan_objmgr_psoc *psoc,
struct infra_cp_stats_event *infra_event)
{
if (!infra_event)
return QDF_STATUS_E_NULL_VALUE;
tgt_mc_infra_cp_stats_extract_twt_stats(psoc, infra_event);
return QDF_STATUS_SUCCESS;
}
#endif
QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{

View File

@ -87,6 +87,11 @@ qca_wlan_vendor_twt_resume_dialog_policy[QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAX + 1
[QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT] = {.type = NLA_U32 },
};
static const struct nla_policy
qca_wlan_vendor_twt_stats_dialog_policy[QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX + 1] = {
[QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID] = {.type = NLA_U8 },
};
const struct nla_policy
wlan_hdd_wifi_twt_config_policy[
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX + 1] = {
@ -1289,6 +1294,25 @@ static int hdd_twt_setup_session(struct hdd_adapter *adapter,
return ret;
}
/**
* hdd_get_twt_get_stats_event_len() - calculate length of skb
* required for sending twt get statistics command responses.
*
* Return: length of skb
*/
static uint32_t hdd_get_twt_get_stats_event_len(void)
{
uint32_t len = 0;
len += NLMSG_HDRLEN;
/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID */
len += nla_total_size(sizeof(u8));
/* QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS */
len += nla_total_size(sizeof(u8));
return len;
}
/**
* hdd_get_twt_event_len() - calculate length of skb
* required for sending twt terminate, pause and resume
@ -2257,7 +2281,6 @@ static int hdd_twt_resume_session(struct hdd_adapter *adapter,
hdd_sta_ctx->conn_info.conn_state);
return -EINVAL;
}
qdf_mem_copy(params.peer_macaddr, hdd_sta_ctx->conn_info.bssid.bytes,
QDF_MAC_ADDR_SIZE);
params.vdev_id = adapter->vdev_id;
@ -2313,6 +2336,221 @@ static int hdd_twt_resume_session(struct hdd_adapter *adapter,
return ret;
}
static uint32_t get_session_wake_duration(uint32_t dialog_id)
{
return 0;
}
/**
* hdd_twt_pack_get_stats_resp_nlmsg()- Packs and sends twt get stats response
* @reply_skb: pointer to response skb buffer
* @params: Ponter to twt session parameter buffer
* @num_session_stats: number of twt statistics
*
* Return: QDF_STATUS_SUCCESS on success, else other qdf error values
*/
static QDF_STATUS
hdd_twt_pack_get_stats_resp_nlmsg(struct sk_buff *reply_skb,
struct twt_infra_cp_stats_event *params,
uint32_t num_session_stats)
{
struct nlattr *config_attr, *nla_params;
int i, attr;
uint32_t wake_duration;
config_attr = nla_nest_start(reply_skb,
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS);
if (!config_attr) {
hdd_err("get_params nla_nest_start error");
return QDF_STATUS_E_INVAL;
}
for (i = 0; i < num_session_stats; i++) {
nla_params = nla_nest_start(reply_skb, i);
if (!nla_params) {
hdd_err("get_stats nla_nest_start error");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR;
if (nla_put(reply_skb, attr, QDF_MAC_ADDR_SIZE,
params[i].peer_macaddr.bytes)) {
hdd_err("get_stats failed to put mac_addr");
return QDF_STATUS_E_INVAL;
}
hdd_debug("get_stats peer mac_addr " QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(params[i].peer_macaddr.bytes));
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID;
if (nla_put_u8(reply_skb, attr, params[i].dialog_id)) {
hdd_err("get_stats failed to put dialog_id");
return QDF_STATUS_E_INVAL;
}
hdd_debug("%d wake duration %d num sp cycles %d",
params[i].dialog_id, wake_duration,
params[i].num_sp_cycles);
wake_duration = get_session_wake_duration(params[i].dialog_id);
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION;
if (nla_put_u32(reply_skb, attr, wake_duration)) {
hdd_err("get_params failed to put Wake duration");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS;
if (nla_put_u32(reply_skb, attr, params[i].num_sp_cycles)) {
hdd_err("get_params failed to put num_sp_cycles");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION;
if (nla_put_u32(reply_skb, attr, params[i].avg_sp_dur_us)) {
hdd_err("get_params failed to put avg_sp_dur_us");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION;
if (nla_put_u32(reply_skb, attr, params[i].min_sp_dur_us)) {
hdd_err("get_params failed to put min_sp_dur_us");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION;
if (nla_put_u32(reply_skb, attr, params[i].max_sp_dur_us)) {
hdd_err("get_params failed to put max_sp_dur_us");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU;
if (nla_put_u32(reply_skb, attr, params[i].tx_mpdu_per_sp)) {
hdd_err("get_params failed to put tx_mpdu_per_sp");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU;
if (nla_put_u32(reply_skb, attr, params[i].rx_mpdu_per_sp)) {
hdd_err("get_params failed to put rx_mpdu_per_sp");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE;
if (nla_put_u32(reply_skb, attr, params[i].tx_bytes_per_sp)) {
hdd_err("get_params failed to put tx_bytes_per_sp");
return QDF_STATUS_E_INVAL;
}
attr = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE;
if (nla_put_u32(reply_skb, attr, params[i].rx_bytes_per_sp)) {
hdd_err("get_params failed to put rx_bytes_per_sp");
return QDF_STATUS_E_INVAL;
}
nla_nest_end(reply_skb, nla_params);
}
nla_nest_end(reply_skb, config_attr);
return QDF_STATUS_SUCCESS;
}
/**
* hdd_twt_get_session_traffic_stats() - Obtains twt session traffic statistics
* and sends response to the user space
* @adapter: hdd_adapter
* @dialog_id: dialog id of the twt session
* @peer_mac: Mac address of the peer
*
* Return: QDF_STATUS_SUCCESS on success, else other qdf error values
*/
static QDF_STATUS
hdd_twt_request_session_traffic_stats(struct hdd_adapter *adapter,
uint32_t dialog_id, uint8_t *peer_mac)
{
int errno;
int skb_len;
struct sk_buff *reply_skb;
QDF_STATUS status = QDF_STATUS_E_INVAL;
struct infra_cp_stats_event *event;
if (!adapter || !peer_mac)
return status;
event = wlan_cfg80211_mc_twt_get_infra_cp_stats(adapter->vdev,
dialog_id,
peer_mac,
&errno);
if (!event)
return errno;
skb_len = hdd_get_twt_get_stats_event_len();
reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
adapter->hdd_ctx->wiphy,
skb_len);
if (!reply_skb) {
hdd_err("Get stats - alloc reply_skb failed");
return -ENOMEM;
}
status = hdd_twt_pack_get_stats_resp_nlmsg(
reply_skb,
event->twt_infra_cp_stats,
event->num_twt_infra_cp_stats);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Get stats - Failed to pack nl response");
wlan_cfg80211_vendor_free_skb(reply_skb);
return qdf_status_to_os_return(status);
}
return wlan_cfg80211_vendor_cmd_reply(reply_skb);
}
/**
* hdd_twt_get_session_stats() - Parses twt nl attrributes, obtains twt
* session parameters based on dialog_id and returns to user via nl layer
* @adapter: hdd_adapter
* @twt_param_attr: twt nl attributes
*
* Return: 0 on success, negative value on failure
*/
static int hdd_twt_get_session_traffic_stats(struct hdd_adapter *adapter,
struct nlattr *twt_param_attr)
{
struct hdd_station_ctx *hdd_sta_ctx =
WLAN_HDD_GET_STATION_CTX_PTR(adapter);
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX + 1];
int ret, id;
QDF_STATUS qdf_status;
uint32_t dialog_id;
uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
ret = wlan_cfg80211_nla_parse_nested(
tb,
QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX,
twt_param_attr,
qca_wlan_vendor_twt_stats_dialog_policy);
if (ret)
return ret;
id = QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID;
if (tb[id])
dialog_id = (uint32_t)nla_get_u8(tb[id]);
else
dialog_id = 0;
hdd_debug("get_stats dialog_id %d", dialog_id);
qdf_mem_copy(peer_mac,
hdd_sta_ctx->conn_info.bssid.bytes,
QDF_MAC_ADDR_SIZE);
hdd_debug("get_stats peer mac_addr " QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(peer_mac));
qdf_status = hdd_twt_request_session_traffic_stats(adapter,
dialog_id, peer_mac);
return qdf_status_to_os_return(qdf_status);
}
/**
* hdd_twt_notify_pack_nlmsg() - pack the skb with
* twt notify event from firmware
@ -2447,6 +2685,10 @@ static int hdd_twt_configure(struct hdd_adapter *adapter,
case QCA_WLAN_TWT_GET_CAPABILITIES:
ret = hdd_twt_get_capabilities(adapter, twt_param_attr);
break;
case QCA_WLAN_TWT_GET_STATS:
ret = hdd_twt_get_session_traffic_stats(adapter,
twt_param_attr);
break;
default:
hdd_err("Invalid TWT Operation");
ret = -EINVAL;

View File

@ -23,6 +23,7 @@
*/
#include <wlan_cfg80211.h>
#include <wlan_cp_stats_ucfg_api.h>
#include <wlan_cp_stats_mc_defs.h>
#include <wlan_cp_stats_mc_ucfg_api.h>
#include <wlan_cfg80211_mc_cp_stats.h>
@ -50,6 +51,41 @@ static void wlan_free_mib_stats(struct stats_event *stats)
}
#endif
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
#ifdef WLAN_SUPPORT_TWT
static void wlan_cfg80211_infra_cp_stats_twt_dealloc(void *priv)
{
struct infra_cp_stats_event *stats = priv;
qdf_mem_free(stats->twt_infra_cp_stats);
stats->twt_infra_cp_stats = NULL;
}
#else
static void wlan_cfg80211_infra_cp_stats_twt_dealloc(void *priv)
{
}
#endif /* WLAN_SUPPORT_TWT */
/**
* wlan_cfg80211_mc_infra_cp_stats_dealloc() - callback to free priv
* allocations for infra cp stats
* @priv: Pointer to priv data statucture
*
* Return: None
*/
static inline
void wlan_cfg80211_mc_infra_cp_stats_dealloc(void *priv)
{
struct infra_cp_stats_event *stats = priv;
if (!stats) {
osif_err("infar_cp_stats is NULL");
return;
}
wlan_cfg80211_infra_cp_stats_twt_dealloc(priv);
}
#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
/**
* wlan_cfg80211_mc_cp_stats_dealloc() - callback to free priv
* allocations for stats
@ -522,6 +558,220 @@ station_stats_cb_fail:
osif_request_put(request);
}
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
#ifdef WLAN_SUPPORT_TWT
static void get_twt_infra_cp_stats(struct infra_cp_stats_event *ev,
struct infra_cp_stats_event *priv)
{
priv->num_twt_infra_cp_stats = ev->num_twt_infra_cp_stats;
priv->twt_infra_cp_stats->dialog_id = ev->twt_infra_cp_stats->dialog_id;
priv->twt_infra_cp_stats->status = ev->twt_infra_cp_stats->status;
priv->twt_infra_cp_stats->num_sp_cycles =
ev->twt_infra_cp_stats->num_sp_cycles;
priv->twt_infra_cp_stats->avg_sp_dur_us =
ev->twt_infra_cp_stats->avg_sp_dur_us;
priv->twt_infra_cp_stats->min_sp_dur_us =
ev->twt_infra_cp_stats->min_sp_dur_us;
priv->twt_infra_cp_stats->max_sp_dur_us =
ev->twt_infra_cp_stats->max_sp_dur_us;
priv->twt_infra_cp_stats->tx_mpdu_per_sp =
ev->twt_infra_cp_stats->tx_mpdu_per_sp;
priv->twt_infra_cp_stats->rx_mpdu_per_sp =
ev->twt_infra_cp_stats->rx_mpdu_per_sp;
priv->twt_infra_cp_stats->tx_bytes_per_sp =
ev->twt_infra_cp_stats->tx_bytes_per_sp;
priv->twt_infra_cp_stats->rx_bytes_per_sp =
ev->twt_infra_cp_stats->rx_bytes_per_sp;
}
static void
wlan_cfg80211_mc_infra_cp_free_twt_stats(struct infra_cp_stats_event *stats)
{
qdf_mem_free(stats->twt_infra_cp_stats);
}
#else
static void get_twt_infra_cp_stats(struct infra_cp_stats_event *ev,
struct infra_cp_stats_event *priv)
{
}
static void
wlan_cfg80211_mc_infra_cp_free_twt_stats(struct infra_cp_stats_event *stats)
{
}
#endif /* WLAN_SUPPORT_TWT */
static inline void
wlan_cfg80211_mc_infra_cp_stats_free_stats_event(
struct infra_cp_stats_event *stats)
{
if (!stats)
return;
wlan_cfg80211_mc_infra_cp_free_twt_stats(stats);
qdf_mem_free(stats);
}
/**
* infra_cp_stats_response_cb() - callback function to handle stats event
* @ev: stats event buffer
* @cookie: a cookie for the request context
*
* Return: None
*/
static inline
void infra_cp_stats_response_cb(struct infra_cp_stats_event *ev,
void *cookie)
{
struct infra_cp_stats_event *priv;
struct osif_request *request;
request = osif_request_get(cookie);
if (!request) {
osif_err("Obsolete request");
return;
}
priv = osif_request_priv(request);
priv->action = ev->action;
priv->request_id = ev->request_id;
priv->status = ev->status;
get_twt_infra_cp_stats(ev, priv);
osif_request_complete(request);
osif_request_put(request);
}
#ifdef WLAN_SUPPORT_TWT
/*Infra limits Add comment here*/
#define MAX_TWT_STAT_VDEV_ENTRIES 1
#define MAX_TWT_STAT_MAC_ADDR_ENTRIES 1
struct infra_cp_stats_event *
wlan_cfg80211_mc_twt_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
uint32_t dialog_id,
uint8_t twt_peer_mac[QDF_MAC_ADDR_SIZE],
int *errno)
{
void *cookie;
QDF_STATUS status;
struct infra_cp_stats_event *priv, *out;
struct twt_infra_cp_stats_event *twt_event;
struct wlan_objmgr_peer *peer;
struct osif_request *request;
struct infra_cp_stats_cmd_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_infra_cp_stats_dealloc,
};
osif_debug("Enter");
out = qdf_mem_malloc(sizeof(*out));
if (!out) {
*errno = -ENOMEM;
return NULL;
}
out->twt_infra_cp_stats =
qdf_mem_malloc(sizeof(*out->twt_infra_cp_stats));
if (!out->twt_infra_cp_stats) {
*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);
priv->twt_infra_cp_stats =
qdf_mem_malloc(sizeof(*priv->twt_infra_cp_stats));
if (!priv->twt_infra_cp_stats) {
*errno = -ENOMEM;
return NULL;
}
twt_event = priv->twt_infra_cp_stats;
info.request_cookie = cookie;
info.stats_id = TYPE_REQ_CTRL_PATH_TWT_STAT;
info.action = ACTION_REQ_CTRL_PATH_STAT_GET;
info.infra_cp_stats_resp_cb = infra_cp_stats_response_cb;
info.num_pdev_ids = 0;
info.num_vdev_ids = MAX_TWT_STAT_VDEV_ENTRIES;
info.vdev_id[0] = wlan_vdev_get_id(vdev);
info.num_mac_addr_list = MAX_TWT_STAT_MAC_ADDR_ENTRIES;
qdf_mem_copy(&info.peer_mac_addr[0], twt_peer_mac, QDF_MAC_ADDR_SIZE);
info.dialog_id = dialog_id;
info.num_pdev_ids = 0;
peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID);
if (!peer) {
osif_err("peer is null");
*errno = -EINVAL;
goto get_twt_stats_fail;
}
wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID);
status = ucfg_infra_cp_stats_register_resp_cb(wlan_vdev_get_psoc(vdev),
&info);
if (QDF_IS_STATUS_ERROR(status)) {
osif_err("Failed to register resp callback: %d", status);
*errno = qdf_status_to_os_return(status);
goto get_twt_stats_fail;
}
status = ucfg_send_infra_cp_stats_request(vdev, &info);
if (QDF_IS_STATUS_ERROR(status)) {
osif_err("Failed to send twt stats request status: %d",
status);
*errno = qdf_status_to_os_return(status);
goto get_twt_stats_fail;
}
*errno = osif_request_wait_for_response(request);
if (*errno) {
osif_err("wait failed or timed out ret: %d", *errno);
goto get_twt_stats_fail;
}
out->num_twt_infra_cp_stats = priv->num_twt_infra_cp_stats;
out->request_id = priv->request_id;
out->twt_infra_cp_stats->dialog_id = twt_event->dialog_id;
out->twt_infra_cp_stats->status = twt_event->status;
out->twt_infra_cp_stats->num_sp_cycles = twt_event->num_sp_cycles;
out->twt_infra_cp_stats->avg_sp_dur_us = twt_event->avg_sp_dur_us;
out->twt_infra_cp_stats->min_sp_dur_us = twt_event->min_sp_dur_us;
out->twt_infra_cp_stats->max_sp_dur_us = twt_event->max_sp_dur_us;
out->twt_infra_cp_stats->tx_mpdu_per_sp = twt_event->tx_mpdu_per_sp;
out->twt_infra_cp_stats->rx_mpdu_per_sp = twt_event->rx_mpdu_per_sp;
out->twt_infra_cp_stats->tx_bytes_per_sp = twt_event->tx_bytes_per_sp;
out->twt_infra_cp_stats->rx_bytes_per_sp = twt_event->rx_bytes_per_sp;
osif_request_put(request);
osif_debug("Exit");
return out;
get_twt_stats_fail:
osif_request_put(request);
wlan_cfg80211_mc_infra_cp_stats_free_stats_event(out);
osif_debug("Exit");
return NULL;
}
#endif
#endif /* WLAN_SUPPORT_INFRA_CTRL_PATH_STATS */
struct stats_event *
wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev,
int *errno)