qcacld-3.0: Add support for MLO LL_STATS
As part of MLO stats feature, add support to process link layer stats for all MLO vdevs and store them in the corresponding adapters. Change-Id: Ia6d731c94eaa3a355a9deae61d07dd06c5d412bd CRs-Fixed: 3181021
This commit is contained in:

committed by
Madan Koyyalamudi

parent
5e5a18dc60
commit
5e19348a66
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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
|
||||
@@ -30,6 +31,7 @@
|
||||
#include "qdf_event.h"
|
||||
/* For WMI_MAX_CHAINS */
|
||||
#include "wmi_unified.h"
|
||||
#include "wlan_mlo_mgr_cmn.h"
|
||||
|
||||
#ifdef QCA_SUPPORT_MC_CP_STATS
|
||||
#include "wlan_cp_stats_public_structs.h"
|
||||
@@ -228,6 +230,7 @@ struct medium_assess_data {
|
||||
* @vdev_id: vdev_id of request
|
||||
* @pdev_id: pdev_id of request
|
||||
* @peer_mac_addr: peer mac address
|
||||
* @ml_vdev_info: mlo_stats_vdev_params structure
|
||||
*/
|
||||
struct request_info {
|
||||
void *cookie;
|
||||
@@ -250,6 +253,9 @@ struct request_info {
|
||||
uint32_t vdev_id;
|
||||
uint32_t pdev_id;
|
||||
uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE];
|
||||
#ifdef WLAN_FEATURE_11BE_MLO
|
||||
struct mlo_stats_vdev_params ml_vdev_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1319,6 +1319,7 @@ struct hdd_adapter {
|
||||
#endif
|
||||
#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
|
||||
struct hdd_mlo_adapter_info mlo_adapter_info;
|
||||
struct wifi_interface_stats ll_iface_stats;
|
||||
#endif
|
||||
#ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
|
||||
void *set_mac_addr_req_ctx;
|
||||
|
@@ -1006,6 +1006,42 @@ static void hdd_link_layer_process_peer_stats(struct hdd_adapter *adapter,
|
||||
cfg80211_vendor_cmd_reply(vendor_event);
|
||||
}
|
||||
|
||||
#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
|
||||
/**
|
||||
* hdd_cache_ll_iface_stats() - Caches ll_stats received from fw to adapter
|
||||
* @hdd_ctx: Pointer to hdd_context
|
||||
* @if_stat: Pointer to stats data
|
||||
*
|
||||
* After receiving Link Layer Interface statistics from FW. This function
|
||||
* converts the firmware data to the NL data and caches them to the adapter.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void
|
||||
hdd_cache_ll_iface_stats(struct hdd_context *hdd_ctx,
|
||||
struct wifi_interface_stats *if_stat)
|
||||
{
|
||||
struct hdd_adapter *adapter;
|
||||
|
||||
adapter = hdd_get_adapter_by_vdev(hdd_ctx, if_stat->vdev_id);
|
||||
/*
|
||||
* There is no need for wlan_hdd_validate_context here. This is a NB
|
||||
* operation that will come with DSC synchronization. This ensures that
|
||||
* no driver transition will take place as long as this operation is
|
||||
* not complete. Thus the need to check validity of hdd_context is not
|
||||
* required.
|
||||
*/
|
||||
hdd_nofl_debug("Copying iface stats into the adapter");
|
||||
adapter->ll_iface_stats = *if_stat;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
hdd_cache_ll_iface_stats(struct hdd_context *hdd_ctx,
|
||||
struct wifi_interface_stats *if_stat)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_link_layer_process_iface_stats() - This function is called after
|
||||
* @adapter: Pointer to device adapter
|
||||
@@ -1026,6 +1062,10 @@ hdd_link_layer_process_iface_stats(struct hdd_adapter *adapter,
|
||||
struct sk_buff *vendor_event;
|
||||
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
|
||||
if (if_stat->vdev_id != adapter->vdev_id) {
|
||||
hdd_cache_ll_iface_stats(hdd_ctx, if_stat);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* There is no need for wlan_hdd_validate_context here. This is a NB
|
||||
* operation that will come with DSC synchronization. This ensures that
|
||||
@@ -1483,6 +1523,12 @@ static void hdd_process_ll_stats(tSirLLStatsResults *results,
|
||||
}
|
||||
qdf_mem_copy(stats->result, results->results,
|
||||
sizeof(struct wifi_interface_stats));
|
||||
|
||||
/* Firmware doesn't send peerstats event if no peers are
|
||||
* connected. HDD should not wait for any peerstats in
|
||||
* this case and return the status to middleware after
|
||||
* receiving iface stats
|
||||
*/
|
||||
if (!results->num_peers)
|
||||
priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
|
||||
priv->request_bitmap &= ~stats->result_param_id;
|
||||
@@ -1589,6 +1635,38 @@ static void hdd_debugfs_process_ll_stats(struct hdd_adapter *adapter,
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
wlan_hdd_update_ll_stats_request_bitmap(struct hdd_context *hdd_ctx,
|
||||
struct osif_request *request,
|
||||
tSirLLStatsResults *results)
|
||||
{
|
||||
struct hdd_ll_stats_priv *priv = osif_request_priv(request);
|
||||
bool is_mlo_link;
|
||||
|
||||
/* The radio stats event is expected at the last, for MLO ll_stats */
|
||||
if (priv->request_bitmap != WMI_LINK_STATS_RADIO &&
|
||||
results->paramId == WMI_LINK_STATS_RADIO) {
|
||||
hdd_err("req_id %d resp_id %u req_bitmap 0x%x resp_bitmap 0x%x",
|
||||
priv->request_id, results->rspId,
|
||||
priv->request_bitmap, results->paramId);
|
||||
QDF_DEBUG_PANIC("Out of order event received for MLO_LL_STATS");
|
||||
}
|
||||
|
||||
is_mlo_link = wlan_vdev_mlme_get_is_mlo_link(hdd_ctx->psoc,
|
||||
results->ifaceId);
|
||||
/* In case of MLO Connection, set the request_bitmap */
|
||||
if (is_mlo_link && results->paramId == WMI_LINK_STATS_IFACE) {
|
||||
/* The radio stats are received at the last, hence set
|
||||
* the request_bitmap for MLO link vdev iface stats.
|
||||
*/
|
||||
if (!(priv->request_bitmap & results->paramId))
|
||||
priv->request_bitmap |= results->paramId;
|
||||
|
||||
hdd_nofl_debug("MLO_LL_STATS set request_bitmap = 0x%x",
|
||||
priv->request_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
void wlan_hdd_cfg80211_link_layer_stats_callback(hdd_handle_t hdd_handle,
|
||||
int indication_type,
|
||||
tSirLLStatsResults *results,
|
||||
@@ -1629,12 +1707,14 @@ void wlan_hdd_cfg80211_link_layer_stats_callback(hdd_handle_t hdd_handle,
|
||||
return;
|
||||
}
|
||||
|
||||
adapter = hdd_get_adapter_by_vdev(hdd_ctx, priv->vdev_id);
|
||||
adapter = hdd_get_adapter_by_vdev(hdd_ctx, results->ifaceId);
|
||||
if (!adapter) {
|
||||
hdd_err("invalid vdev %d", priv->vdev_id);
|
||||
hdd_err("invalid vdev %d", results->ifaceId);
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_hdd_update_ll_stats_request_bitmap(hdd_ctx, request,
|
||||
results);
|
||||
if (results->rspId == DEBUGFS_LLSTATS_REQID) {
|
||||
hdd_debugfs_process_ll_stats(adapter, results, request);
|
||||
} else {
|
||||
@@ -1945,12 +2025,48 @@ static void cache_station_stats_cb(struct stats_event *ev, void *cookie)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_11BE_MLO
|
||||
static QDF_STATUS
|
||||
wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter)
|
||||
wlan_hdd_get_mlo_vdev_params(struct hdd_adapter *adapter,
|
||||
struct request_info *req_info,
|
||||
tSirLLStatsGetReq *req)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc = adapter->hdd_ctx->psoc;
|
||||
struct mlo_stats_vdev_params *info = &req_info->ml_vdev_info;
|
||||
int i;
|
||||
uint32_t bmap = 0;
|
||||
QDF_STATUS status;
|
||||
|
||||
req->is_mlo_req = wlan_vdev_mlme_get_is_mlo_vdev(psoc,
|
||||
adapter->vdev_id);
|
||||
status = mlo_get_mlstats_vdev_params(psoc, info, adapter->vdev_id);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return status;
|
||||
for (i = 0; i < info->ml_vdev_count; i++)
|
||||
bmap |= (1 << info->ml_vdev_id[i]);
|
||||
req->mlo_vdev_id_bitmap = bmap;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static QDF_STATUS
|
||||
wlan_hdd_get_mlo_vdev_params(struct hdd_adapter *adapter,
|
||||
struct request_info *req_info,
|
||||
tSirLLStatsGetReq *req)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static QDF_STATUS
|
||||
wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter,
|
||||
tSirLLStatsGetReq *req)
|
||||
{
|
||||
struct wlan_objmgr_peer *peer;
|
||||
struct request_info info = {0};
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct wlan_objmgr_psoc *psoc = adapter->hdd_ctx->psoc;
|
||||
bool is_mlo_vdev = false;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!adapter->hdd_ctx->is_get_station_clubbed_in_ll_stats_req)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
@@ -1968,6 +2084,15 @@ wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter)
|
||||
info.cookie = adapter;
|
||||
info.u.get_station_stats_cb = cache_station_stats_cb;
|
||||
info.vdev_id = adapter->vdev_id;
|
||||
is_mlo_vdev = wlan_vdev_mlme_get_is_mlo_vdev(psoc, adapter->vdev_id);
|
||||
if (is_mlo_vdev) {
|
||||
status = wlan_hdd_get_mlo_vdev_params(adapter, &info, req);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
hdd_err("unable to get vdev params for mlo stats");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
|
||||
peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_STATS_ID);
|
||||
if (!peer) {
|
||||
@@ -2036,7 +2161,8 @@ static QDF_STATUS wlan_hdd_stats_request_needed(struct hdd_adapter *adapter)
|
||||
|
||||
#else
|
||||
static QDF_STATUS
|
||||
wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter)
|
||||
wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter,
|
||||
tSirLLStatsGetReq *req)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -2072,7 +2198,7 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter,
|
||||
|
||||
hdd_enter_dev(adapter->dev);
|
||||
|
||||
status = wlan_hdd_set_station_stats_request_pending(adapter);
|
||||
status = wlan_hdd_set_station_stats_request_pending(adapter, req);
|
||||
if (status == QDF_STATUS_E_ALREADY)
|
||||
return qdf_status_to_os_return(status);
|
||||
|
||||
|
@@ -28,6 +28,9 @@
|
||||
#define WLAN_HDD_STATS_H
|
||||
|
||||
#include "wlan_hdd_main.h"
|
||||
#ifdef WLAN_FEATURE_11BE_MLO
|
||||
#include "wlan_mlo_mgr_cmn.h"
|
||||
#endif
|
||||
|
||||
#define INVALID_MCS_IDX 255
|
||||
#define MAX_HT_MCS_IDX 8
|
||||
|
@@ -2916,6 +2916,8 @@ typedef struct {
|
||||
uint32_t reqId;
|
||||
uint8_t staId;
|
||||
uint32_t paramIdMask;
|
||||
bool is_mlo_req;
|
||||
uint32_t mlo_vdev_id_bitmap;
|
||||
} tSirLLStatsGetReq, *tpSirLLStatsGetReq;
|
||||
|
||||
typedef struct {
|
||||
@@ -3141,6 +3143,7 @@ struct wifi_peer_info {
|
||||
* @ac_stats: per-Access Category statistics
|
||||
* @num_offload_stats: @offload_stats record count
|
||||
* @offload_stats: per-offload statistics
|
||||
* @vdev_id: vdev id
|
||||
*
|
||||
* Statistics corresponding to 2nd most LSB in wifi statistics bitmap
|
||||
* for getting statistics
|
||||
@@ -3155,6 +3158,7 @@ struct wifi_interface_stats {
|
||||
wmi_wmm_ac_stats ac_stats[WIFI_AC_MAX];
|
||||
uint32_t num_offload_stats;
|
||||
wmi_iface_offload_stats offload_stats[WMI_OFFLOAD_STATS_TYPE_MAX];
|
||||
uint8_t vdev_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -2614,6 +2614,46 @@ wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_11BE_MLO
|
||||
static QDF_STATUS
|
||||
wma_update_params_for_mlo_stats(tp_wma_handle wma,
|
||||
const tpSirLLStatsGetReq getReq,
|
||||
struct ll_stats_get_params *cmd)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
uint8_t *mld_addr;
|
||||
|
||||
cmd->is_mlo_req = getReq->is_mlo_req;
|
||||
|
||||
vdev = wma->interfaces[getReq->staId].vdev;
|
||||
if (!vdev) {
|
||||
wma_err("Failed to get vdev for vdev_%d", getReq->staId);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
if (getReq->is_mlo_req) {
|
||||
cmd->vdev_id_bitmap = getReq->mlo_vdev_id_bitmap;
|
||||
mld_addr = wlan_vdev_mlme_get_mldaddr(vdev);
|
||||
if (!mld_addr) {
|
||||
wma_err("Failed to get mld_macaddr for vdev_%d",
|
||||
getReq->staId);
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
qdf_mem_copy(cmd->mld_macaddr.bytes, mld_addr,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static QDF_STATUS
|
||||
wma_update_params_for_mlo_stats(tp_wma_handle wma,
|
||||
const tpSirLLStatsGetReq getReq,
|
||||
struct ll_stats_get_params *cmd)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
|
||||
const tpSirLLStatsGetReq getReq)
|
||||
{
|
||||
@@ -2621,6 +2661,7 @@ QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
|
||||
uint8_t *addr;
|
||||
struct ll_stats_get_params cmd = {0};
|
||||
int ret;
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!getReq || !wma) {
|
||||
wma_err("input pointer is NULL");
|
||||
@@ -2647,6 +2688,13 @@ QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma,
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
qdf_mem_copy(cmd.peer_macaddr.bytes, addr, QDF_MAC_ADDR_SIZE);
|
||||
|
||||
status = wma_update_params_for_mlo_stats(wma, getReq, &cmd);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
wma_err("Failed to update params for mlo_stats");
|
||||
return status;
|
||||
}
|
||||
|
||||
ret = wma_send_ll_stats_get_cmd(wma, &cmd);
|
||||
if (ret) {
|
||||
wma_err("Failed to send get link stats request");
|
||||
@@ -2807,6 +2855,9 @@ int wma_unified_link_iface_stats_event_handler(void *handle,
|
||||
iface_offload_stats++;
|
||||
}
|
||||
|
||||
/* Copying vdev_id info into the iface_stat for MLO*/
|
||||
iface_stat->vdev_id = fixed_param->vdev_id;
|
||||
|
||||
/* call hdd callback with Link Layer Statistics
|
||||
* vdev_id/ifacId in link_stats_results will be
|
||||
* used to retrieve the correct HDD context
|
||||
|
Reference in New Issue
Block a user