qcacld-3.0: Add support to handle RRM sta stats req

Add support to handle RRM Station statistics request (type == 7)
from AP. Based on the received group id, collect the corresponding
stats and send the RRM station statistics response to AP.

Send Report with incapable/Refused bit in below cases:
a.) Meas duration > threshold which is 10 seconds
b.) Groupid apart from 0, 1 or 10.
c.) Failure to start Timer.
d.) Response not received from FW for previous request.
e.) Another RRM STA STATS Request in progress.
f.) Another CP stats request in progress.

Change-Id: If93e9c51363daf9704a14df5822c8f7bfbd4b216
CRs-Fixed: 3583973
This commit is contained in:
Sheenam Monga
2023-08-08 23:31:46 +05:30
zatwierdzone przez Rahul Choudhary
rodzic f89f0e2de0
commit 7aa3e49d6d
18 zmienionych plików z 847 dodań i 10 usunięć

Wyświetl plik

@@ -672,8 +672,8 @@ 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;
get_infra_cp_stats_cb resp_cb = NULL;
void *context = NULL;
status = wlan_cp_stats_infra_cp_get_context(psoc, &resp_cb, &context);
if (QDF_IS_STATUS_ERROR(status)) {

Wyświetl plik

@@ -285,6 +285,8 @@ typedef struct sLimTimers {
/* SAE authentication related timer */
TX_TIMER sae_auth_timer;
/* RRM sta stats response related timer */
TX_TIMER rrm_sta_stats_resp_timer;
/* ********************TIMER SECTION ENDS************************************************** */
/* ALL THE FIELDS BELOW THIS CAN BE ZEROED OUT in lim_initialize */
/* **************************************************************************************** */

Wyświetl plik

@@ -1363,6 +1363,102 @@ struct chan_load_report {
uint8_t chan_load;
};
/**
* sta_statistics_group_id - RRM STA STATISTICS TYPE related Refer IEEE
* P802.11-REVme/D2.1, January 2023, Table 9-144
* @STA_STAT_GROUP_ID_COUNTER_STATS: group id for counter stats
* @STA_STAT_GROUP_ID_MAC_STATS: group id for mac stats
* @STA_STAT_GROUP_ID_QOS_STATS: group id for qos stats
* @STA_STAT_GROUP_ID_DELAY_STATS: group id delay stats
*/
enum sta_statistics_group_id {
STA_STAT_GROUP_ID_COUNTER_STATS = 0,
STA_STAT_GROUP_ID_MAC_STATS = 1,
STA_STAT_GROUP_ID_QOS_STATS = 2,
STA_STAT_GROUP_ID_DELAY_STATS = 10,
};
/**
* counter_stats - structure to hold stats of group id 0
* @transmitted_fragment_count: transmitted fragment count
* @group_transmitted_frame_count: group transmitted frame count
* @failed_count: failed count
* @group_received_frame_count: group received frame count
* @fcs_error_count: face error count
* @transmitted_frame_count: transmitted frame count
* @received_fragment_count: received fragment count
*/
struct counter_stats {
uint32_t transmitted_fragment_count;
uint32_t group_transmitted_frame_count;
uint32_t failed_count;
uint32_t group_received_frame_count;
uint32_t fcs_error_count;
uint32_t transmitted_frame_count;
uint32_t received_fragment_count;
};
/**
* mac_stats - struct to hold group id 1 stats
* @retry_count: retry count
* @multiple_retry_count: multiple retry count
* @frame_duplicate_count: frame duplicate count
* @rts_success_count: rts success count
* @rts_failure_count: rts failure count
* @ack_failure_count: ack failure count
*/
struct mac_stats {
uint32_t retry_count;
uint32_t multiple_retry_count;
uint32_t frame_duplicate_count;
uint32_t rts_success_count;
uint32_t rts_failure_count;
uint32_t ack_failure_count;
};
/**
* struct access_delay_stats - struct for group id 10 stats
* @ap_average_access_delay: ap average access delay
* @average_access_delay_besteffort: access delay best effort
* @average_access_delay_background: average access delay background
* @average_access_delay_video: average access delay video
* @average_access_delay_voice: average access delay voice
* station_count: station count
* channel_utilization: channel utilization
*/
struct access_delay_stats {
uint8_t ap_average_access_delay;
uint8_t average_access_delay_besteffort;
uint8_t average_access_delay_background;
uint8_t average_access_delay_video;
uint8_t average_access_delay_voice;
uint16_t station_count;
uint8_t channel_utilization;
};
/**
* union stats_group_data - stats data for provided group id
* @counter stats - stats for group id 0
* @mac_stats - stats for group id 1
*/
union stats_group_data {
struct counter_stats counter_stats;
struct mac_stats mac_stats;
struct access_delay_stats access_delay_stats;
};
/**
* struct statistics_report - To store sta statistics report
* @meas_duration: measurement duration
* @group id: stats group id
* @group stats: stats data
*/
struct statistics_report {
uint8_t meas_duration;
uint8_t group_id;
union stats_group_data group_stats;
};
typedef struct sSirMacRadioMeasureReport {
uint8_t token;
uint8_t refused;
@@ -1371,6 +1467,7 @@ typedef struct sSirMacRadioMeasureReport {
union {
tSirMacBeaconReport beaconReport;
struct chan_load_report channel_load_report;
struct statistics_report statistics_report;
} report;
} tSirMacRadioMeasureReport, *tpSirMacRadioMeasureReport;

Wyświetl plik

@@ -823,7 +823,7 @@ populate_dot11f_ext_supp_rates(struct mac_context *mac,
* @pBeaconReport: Pointer to the Beacon Report structure
* @is_last_frame: is the current report last or more reports to follow
*
* Return: Ret Status
* Return: QDF Status
*/
QDF_STATUS
populate_dot11f_beacon_report(struct mac_context *mac,
@@ -844,6 +844,19 @@ populate_dot11f_chan_load_report(struct mac_context *mac,
tDot11fIEMeasurementReport *dot11f,
struct chan_load_report *channel_load_report);
/**
* populate_dot11f_rrm_sta_stats_report() - Populate RRM STA STATS Report IE
* @mac: Pointer to the global MAC context
* @pdot11f: Pointer to the measurement report structure
* @statistics_report: Pointer to the RRM STA STATS Report structure
*
* Return: QDF Status
*/
QDF_STATUS
populate_dot11f_rrm_sta_stats_report(
struct mac_context *mac, tDot11fIEMeasurementReport *pdot11f,
struct statistics_report *statistics_report);
/**
* \brief Populate a tDot11fIEExtSuppRates
*

Wyświetl plik

@@ -709,7 +709,7 @@ enum halmsgtype {
#define SIR_LIM_WPS_OVERLAP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1D)
#define SIR_LIM_FT_PREAUTH_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x1E)
/* currently unused (SIR_LIM_TIMEOUT_MSG_START + 0x24) */
#define SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x24)
/* currently unused (SIR_LIM_TIMEOUT_MSG_START + 0x25) */
#define SIR_LIM_DISASSOC_ACK_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x26)

Wyświetl plik

@@ -133,4 +133,44 @@ QDF_STATUS rrm_reject_req(tpSirMacRadioMeasureReport *radiomes_report,
uint8_t measurement_type);
void lim_update_rrm_capability(struct mac_context *mac_ctx);
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
/**
* rrm_send_sta_stats_req - Send RRM STA STATS request
* @mac: mac context
* @session: pe session
* @peer_mac: peer mac
*
* Return: QDF_STATUS
*/
QDF_STATUS
rrm_send_sta_stats_req(struct mac_context *mac,
struct pe_session *session,
tSirMacAddr peer_mac);
#else
static inline QDF_STATUS
rrm_send_sta_stats_req(struct mac_context *mac,
struct pe_session *session,
tSirMacAddr peer_mac)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif
/**
* rrm_process_rrm_sta_stats_request_failure: send RRM STA Stats report with
* failure
* @mac: mac context
* @pe_session: pe session
* @peer: peer mac
* @status: failure status
* @index: index of report
*
* Return: void
*/
void
rrm_process_rrm_sta_stats_request_failure(struct mac_context *mac,
struct pe_session *pe_session,
tSirMacAddr peer,
tRrmRetStatus status, uint8_t index);
#endif

Wyświetl plik

@@ -259,6 +259,22 @@ typedef struct sRRMCaps {
uint8_t reserved:4;
} tRRMCaps, *tpRRMCaps;
/**
* struct rrm_sta_stats - RRM sta stats structure
* @rrm_report: rrm_report
* @peer: peer address
* @index: current req index
* @rrm_sta_stats_res_count: sta stats response count
* @vdev_id: vdev_id
*/
struct rrm_sta_stats {
tSirMacRadioMeasureReport rrm_report;
tSirMacAddr peer;
uint8_t index;
uint8_t rrm_sta_stats_res_count;
uint8_t vdev_id;
};
typedef struct sRrmPEContext {
uint8_t rrmEnable;
/*
@@ -279,6 +295,7 @@ typedef struct sRrmPEContext {
tpRRMReq pCurrentReq[MAX_MEASUREMENT_REQUEST];
uint32_t beacon_rpt_chan_list[MAX_NUM_CHANNELS];
uint8_t beacon_rpt_chan_num;
struct rrm_sta_stats rrm_sta_stats;
} tRrmPEContext, *tpRrmPEContext;
/* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */

Wyświetl plik

@@ -1855,6 +1855,7 @@ static void lim_process_messages(struct mac_context *mac_ctx,
case SIR_LIM_DISASSOC_ACK_TIMEOUT:
case SIR_LIM_AUTH_RETRY_TIMEOUT:
case SIR_LIM_AUTH_SAE_TIMEOUT:
case SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT:
/* These timeout messages are handled by MLM sub module */
lim_process_mlm_req_messages(mac_ctx, msg);
break;

Wyświetl plik

@@ -43,12 +43,15 @@
#include "wlan_mlme_public_struct.h"
#include "../../core/src/vdev_mgr_ops.h"
#include "wlan_pmo_ucfg_api.h"
#include "wlan_cp_stats_utils_api.h"
#include "wlan_objmgr_vdev_obj.h"
#include <wlan_cm_api.h>
#include <lim_mlo.h>
#include "wlan_mlo_mgr_peer.h"
#include <son_api.h>
#include "wifi_pos_pasn_api.h"
#include "rrm_api.h"
#include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
static void lim_process_mlm_auth_req(struct mac_context *, uint32_t *);
static void lim_process_mlm_assoc_req(struct mac_context *, uint32_t *);
@@ -96,6 +99,75 @@ static void lim_fill_status_code(uint8_t frame_type,
}
}
void lim_process_rrm_sta_stats_rsp_timeout(struct mac_context *mac)
{
struct pe_session *session;
tSirMacRadioMeasureReport rrm_report;
QDF_STATUS status;
uint8_t index;
tpRRMReq pcurrent_req = NULL;
tRrmRetStatus rrm_status;
session = pe_find_session_by_session_id(mac,
mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId);
if (!session) {
pe_err("Session does not exist for given session id %d",
mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId);
rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
return;
}
pe_warn("STA STATS RSP timeout vdev_id %d", session->vdev_id);
index = mac->rrm.rrmPEContext.rrm_sta_stats.index;
pcurrent_req = mac->rrm.rrmPEContext.pCurrentReq[index];
if (!pcurrent_req) {
pe_err("Current request is NULL for index %d", index);
qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
return;
}
if (!mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count) {
pe_err("response not received for previous req");
rrm_status = eRRM_INCAPABLE;
goto err;
}
rrm_report = mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
switch (rrm_report.report.statistics_report.group_id) {
/*
* For Counter stats and Mac stats some stats will be received
* via FW and some via DP. So, same handling is required for both
* cases.
*/
case STA_STAT_GROUP_ID_COUNTER_STATS:
case STA_STAT_GROUP_ID_MAC_STATS:
status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
if (QDF_IS_STATUS_ERROR(status))
pe_err("failed to deregister callback %d", status);
status =
rrm_send_sta_stats_req(
mac, session,
mac->rrm.rrmPEContext.rrm_sta_stats.peer);
if (QDF_IS_STATUS_ERROR(status)) {
pe_err("fail to send stats req");
rrm_status = eRRM_FAILURE;
goto err;
}
break;
case STA_STAT_GROUP_ID_DELAY_STATS:
/* TOdo: fetch from scan ie */
break;
}
return;
err:
rrm_process_rrm_sta_stats_request_failure(
mac, session, mac->rrm.rrmPEContext.rrm_sta_stats.peer,
rrm_status, mac->rrm.rrmPEContext.rrm_sta_stats.index);
rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
}
void lim_process_sae_auth_timeout(struct mac_context *mac_ctx)
{
struct pe_session *session;
@@ -194,6 +266,9 @@ void lim_process_mlm_req_messages(struct mac_context *mac_ctx,
case SIR_LIM_AUTH_SAE_TIMEOUT:
lim_process_sae_auth_timeout(mac_ctx);
break;
case SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT:
lim_process_rrm_sta_stats_rsp_timeout(mac_ctx);
break;
case LIM_MLM_TSPEC_REQ:
default:
break;

Wyświetl plik

@@ -5686,6 +5686,16 @@ lim_send_radio_measure_report_action_frame(struct mac_context *mac,
pRRMReport[i].refused;
frm->MeasurementReport[i].present = 1;
break;
case SIR_MAC_RRM_STA_STATISTICS_TYPE:
populate_dot11f_rrm_sta_stats_report(
mac, &frm->MeasurementReport[i],
&pRRMReport[i].report.statistics_report);
frm->MeasurementReport[i].incapable =
pRRMReport[i].incapable;
frm->MeasurementReport[i].refused =
pRRMReport[i].refused;
frm->MeasurementReport[i].present = 1;
break;
default:
frm->MeasurementReport[i].incapable =
pRRMReport[i].incapable;

Wyświetl plik

@@ -49,6 +49,12 @@
*/
#define LIM_AUTH_SAE_TIMER_MS 5000
/*
* STA stats resp timer of 10secs. This is required for duration of RRM
* STA STATS report response from report request.
*/
#define LIM_RRM_STA_STATS_RSP_TIMER_MS 10000
static bool lim_create_non_ap_timers(struct mac_context *mac)
{
uint32_t cfgValue;
@@ -235,10 +241,21 @@ uint32_t lim_create_timers(struct mac_context *mac)
goto err_timer;
}
if ((tx_timer_create(mac,
&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
"STA STATS RSP timer",
lim_timer_handler,
SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT,
SYS_MS_TO_TICKS(LIM_RRM_STA_STATS_RSP_TIMER_MS), 0,
TX_NO_ACTIVATE)) != TX_SUCCESS) {
pe_err("could not create STA STATS RSP Timer");
goto err_timer;
}
return TX_SUCCESS;
err_timer:
lim_delete_timers_host_roam(mac);
tx_timer_delete(&mac->lim.lim_timers.rrm_sta_stats_resp_timer);
tx_timer_delete(&mac->lim.lim_timers.gLimDeauthAckTimer);
tx_timer_delete(&mac->lim.lim_timers.gLimDisassocAckTimer);
tx_timer_delete(&mac->lim.lim_timers.gLimUpdateOlbcCacheTimer);
@@ -677,6 +694,21 @@ void lim_deactivate_and_change_timer(struct mac_context *mac, uint32_t timerId)
pe_err("unable to change SAE auth timer");
break;
case eLIM_RRM_STA_STATS_RSP_TIMER:
if (tx_timer_deactivate
(&mac->lim.lim_timers.rrm_sta_stats_resp_timer)
!= TX_SUCCESS)
pe_err("Unable to deactivate STA STATS RSP timer");
/* Change timer to reactivate it in future */
val = SYS_MS_TO_TICKS(LIM_RRM_STA_STATS_RSP_TIMER_MS);
if (tx_timer_change(
&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
val, 0) != TX_SUCCESS)
pe_err("unable to change STA STATS RSP timer");
break;
default:
/* Invalid timerId. Log error */

Wyświetl plik

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2011-2014, 2016-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 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
@@ -55,7 +55,8 @@ enum limtimertype {
eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER,
eLIM_INSERT_SINGLESHOT_NOA_TIMER,
eLIM_AUTH_RETRY_TIMER,
eLIM_AUTH_SAE_TIMER
eLIM_AUTH_SAE_TIMER,
eLIM_RRM_STA_STATS_RSP_TIMER
};
#define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT 500

Wyświetl plik

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023 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
@@ -64,6 +64,7 @@ static uint8_t *__lim_trace_get_timer_string(uint16_t timerId)
CASE_RETURN_STRING(eLIM_DEAUTH_ACK_TIMER);
CASE_RETURN_STRING(eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
CASE_RETURN_STRING(eLIM_AUTH_RETRY_TIMER);
CASE_RETURN_STRING(eLIM_RRM_STA_STATS_RSP_TIMER);
default:
return "UNKNOWN";
break;

Wyświetl plik

@@ -1624,6 +1624,15 @@ void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
*/
void lim_process_sae_auth_timeout(struct mac_context *mac_ctx);
/**
* lim_process_rrm_sta_stats_rsp_timeout() - This function is called to process
* sta stats response timeout
* @mac_ctx: Pointer to Global MAC structure
*
* @Return: None
*/
void lim_process_rrm_sta_stats_rsp_timeout(struct mac_context *mac_ctx);
/**
* lim_send_frame() - API to send frame
* @mac_ctx Pointer to Global MAC structure

Wyświetl plik

@@ -496,8 +496,13 @@ void lim_deactivate_timers(struct mac_context *mac_ctx)
/* Cleanup as if SAE auth timer expired */
lim_timer_handler(mac_ctx, SIR_LIM_AUTH_SAE_TIMEOUT);
}
tx_timer_deactivate(&lim_timer->sae_auth_timer);
if (tx_timer_running(&lim_timer->rrm_sta_stats_resp_timer)) {
pe_err("sta stats resp timer running call the timeout API");
lim_timer_handler(mac_ctx, SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT);
}
tx_timer_deactivate(&lim_timer->rrm_sta_stats_resp_timer);
}
void lim_deactivate_timers_for_vdev(struct mac_context *mac_ctx,
@@ -663,6 +668,7 @@ void lim_cleanup_mlm(struct mac_context *mac_ctx)
tx_timer_delete(&lim_timer->gLimDeauthAckTimer);
tx_timer_delete(&lim_timer->sae_auth_timer);
tx_timer_delete(&lim_timer->rrm_sta_stats_resp_timer);
mac_ctx->lim.gLimTimersCreated = 0;
}

Wyświetl plik

@@ -45,6 +45,15 @@
#include "rrm_api.h"
#include "wlan_lmac_if_def.h"
#include "wlan_reg_services_api.h"
#include "wlan_cp_stats_utils_api.h"
#include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
#include "../../core/src/wlan_cp_stats_defs.h"
#include "cdp_txrx_host_stats.h"
#define MAX_CTRL_STAT_VDEV_ENTRIES 1
#define MAX_CTRL_STAT_MAC_ADDR_ENTRIES 1
#define MAX_RMM_STA_STATS_REQUESTED 2
#define MAX_MEAS_DURATION_FOR_STA_STATS 10
/* Max passive scan dwell for wide band rrm scan, in milliseconds */
#define RRM_SCAN_MAX_DWELL_TIME 110
@@ -611,6 +620,506 @@ wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
#endif
#define ABS(x) ((x < 0) ? -x : x)
#ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
/**
* rrm_update_mac_cp_stats: update stats of rrm structure of mac
* @ev: cp stats event
* @mac_ctx: mac context
*
* Return: None
*/
static inline void
rrm_update_mac_cp_stats(struct infra_cp_stats_event *ev,
struct mac_context *mac_ctx)
{
tpSirMacRadioMeasureReport rrm_report;
struct counter_stats *counter_stats;
struct group_id_0 ev_counter_stats;
struct mac_stats *mac_stats;
struct group_id_1 ev_mac_stats;
rrm_report = &mac_ctx->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
counter_stats =
&rrm_report->report.statistics_report.group_stats.counter_stats;
mac_stats =
&rrm_report->report.statistics_report.group_stats.mac_stats;
ev_counter_stats = ev->sta_stats->group.counter_stats;
ev_mac_stats = ev->sta_stats->group.mac_stats;
switch (rrm_report->report.statistics_report.group_id) {
/*
* Assign count diff in mac rrm sta stats report.
* For first event callback stats will be same as
* send by FW because memset is done for mac rrm sta
* stats before sending rrm sta stats request to FW and
* for second request stats will be the diff of stats send
* by FW and previous stats.
*/
case STA_STAT_GROUP_ID_COUNTER_STATS:
counter_stats->group_transmitted_frame_count =
ev_counter_stats.group_transmitted_frame_count -
counter_stats->group_transmitted_frame_count;
counter_stats->failed_count =
ev_counter_stats.failed_count -
counter_stats->failed_count;
counter_stats->group_received_frame_count =
ev_counter_stats.group_received_frame_count -
counter_stats->group_received_frame_count;
counter_stats->fcs_error_count =
ev_counter_stats.fcs_error_count -
counter_stats->fcs_error_count;
counter_stats->transmitted_frame_count =
ev_counter_stats.transmitted_frame_count -
counter_stats->transmitted_frame_count;
break;
case STA_STAT_GROUP_ID_MAC_STATS:
mac_stats->rts_success_count =
ev_mac_stats.rts_success_count -
mac_stats->rts_success_count;
mac_stats->rts_failure_count =
ev_mac_stats.rts_failure_count -
mac_stats->rts_failure_count;
mac_stats->ack_failure_count =
ev_mac_stats.ack_failure_count -
mac_stats->ack_failure_count;
break;
default:
pe_debug("group id not supported");
}
pe_nofl_debug("counter stats: group frame count ( tx %d rx %d ) failed_count %d fcs_error %d tx frame count %d mac stats: rts success count %d rts fail count %d ack fail count %d",
counter_stats->group_transmitted_frame_count,
counter_stats->group_received_frame_count,
counter_stats->failed_count,
counter_stats->fcs_error_count,
counter_stats->transmitted_frame_count,
mac_stats->rts_success_count,
mac_stats->rts_failure_count,
mac_stats->ack_failure_count);
}
/**
* rmm_sta_stats_response_cb: RRM sta stats response callback
* @ev: cp stats event
* @cookie: NULL
*
* Return: None
*/
static inline
void rmm_sta_stats_response_cb(struct infra_cp_stats_event *ev, void *cookie)
{
struct mac_context *mac;
struct pe_session *session;
uint8_t vdev_id, index;
QDF_STATUS status;
tpRRMReq pcurrent_req;
tSirMacRadioMeasureReport *rrm_report;
mac = cds_get_context(QDF_MODULE_ID_PE);
if (!mac)
return;
index = mac->rrm.rrmPEContext.rrm_sta_stats.index;
/* Deregister callback registered in request */
status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
if (QDF_IS_STATUS_ERROR(status))
pe_err("failed to deregister callback %d", status);
pcurrent_req = mac->rrm.rrmPEContext.pCurrentReq[index];
if (!pcurrent_req) {
pe_err("Current request is NULL");
qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
return;
}
vdev_id = mac->rrm.rrmPEContext.rrm_sta_stats.vdev_id;
session = pe_find_session_by_vdev_id(mac, vdev_id);
if (!session) {
pe_err("Session does not exist for given vdev id %d", vdev_id);
rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
return;
}
rrm_report = &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
rrm_update_mac_cp_stats(ev, mac);
/* Update resp counter for every response to find second resp*/
mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count++;
/* Send current stats if meas duration is 0. */
if (mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count ==
MAX_RMM_STA_STATS_REQUESTED ||
!rrm_report->report.statistics_report.meas_duration) {
lim_send_radio_measure_report_action_frame(
mac, pcurrent_req->dialog_token, 1, true,
&mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report,
mac->rrm.rrmPEContext.rrm_sta_stats.peer, session);
rrm_cleanup(mac, index);
}
}
/**
* rrm_update_vdev_stats: Update RRM stats from DP
* @rrm_report: RRM Measurement Report
* @vdev_id: vdev_id
*
* Return: QDF STATUS
*/
static QDF_STATUS
rrm_update_vdev_stats(tpSirMacRadioMeasureReport rrm_report, uint8_t vdev_id)
{
struct cdp_vdev_stats *stats;
QDF_STATUS status;
struct counter_stats *counter_stats;
struct mac_stats *mac_stats;
counter_stats =
&rrm_report->report.statistics_report.group_stats.counter_stats;
mac_stats =
&rrm_report->report.statistics_report.group_stats.mac_stats;
stats = qdf_mem_malloc(sizeof(*stats));
if (!stats)
return QDF_STATUS_E_NOMEM;
status =
cdp_host_get_vdev_stats(cds_get_context(QDF_MODULE_ID_SOC),
vdev_id, stats, true);
if (QDF_IS_STATUS_ERROR(status)) {
pe_err("Failed to get stats %d", status);
qdf_mem_free(stats);
return QDF_STATUS_E_FAILURE;
}
pe_nofl_debug("counter stats count: fragment (tx: %d rx: %d) mac stats count: retry : %d multiple retry: %d frame duplicate %d",
stats->tx.fragment_count, stats->rx.fragment_count,
stats->tx.retry_count, stats->tx.multiple_retry_count,
stats->rx.duplicate_count);
switch (rrm_report->report.statistics_report.group_id) {
case STA_STAT_GROUP_ID_COUNTER_STATS:
counter_stats->transmitted_fragment_count =
stats->tx.fragment_count -
counter_stats->transmitted_fragment_count;
counter_stats->received_fragment_count =
stats->rx.fragment_count -
counter_stats->received_fragment_count;
break;
case STA_STAT_GROUP_ID_MAC_STATS:
mac_stats->retry_count =
stats->tx.retry_count - mac_stats->retry_count;
mac_stats->multiple_retry_count =
stats->tx.multiple_retry_count -
mac_stats->multiple_retry_count;
mac_stats->frame_duplicate_count =
stats->rx.duplicate_count -
mac_stats->frame_duplicate_count;
break;
}
qdf_mem_free(stats);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
rrm_send_sta_stats_req(struct mac_context *mac,
struct pe_session *session,
tSirMacAddr peer_mac)
{
struct infra_cp_stats_cmd_info info = {0};
get_infra_cp_stats_cb resp_cb = NULL;
void *context;
QDF_STATUS status;
tpSirMacRadioMeasureReport report;
status = wlan_cp_stats_infra_cp_get_context(mac->psoc, &resp_cb,
&context);
if (resp_cb) {
pe_err("another request already in progress");
return QDF_STATUS_E_FAILURE;
}
info.request_cookie = NULL;
info.stats_id = TYPE_REQ_CTRL_PATH_RRM_STA_STAT;
info.action = ACTION_REQ_CTRL_PATH_STAT_GET;
info.infra_cp_stats_resp_cb = rmm_sta_stats_response_cb;
info.num_pdev_ids = 0;
info.num_vdev_ids = MAX_CTRL_STAT_VDEV_ENTRIES;
info.vdev_id[0] = wlan_vdev_get_id(session->vdev);
info.num_mac_addr_list = MAX_CTRL_STAT_MAC_ADDR_ENTRIES;
info.num_pdev_ids = 0;
/*
* FW doesn't send vdev id in response path.
* So, vdev id will be used to get session
* in callback.
*/
mac->rrm.rrmPEContext.rrm_sta_stats.vdev_id =
wlan_vdev_get_id(session->vdev);
qdf_mem_copy(&info.peer_mac_addr[0], peer_mac, QDF_MAC_ADDR_SIZE);
report = &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
status = rrm_update_vdev_stats(report, wlan_vdev_get_id(session->vdev));
if (QDF_IS_STATUS_ERROR(status)) {
pe_err("Failed to register resp callback: %d", status);
return status;
}
status = wlan_cp_stats_infra_cp_register_resp_cb(mac->psoc, &info);
if (QDF_IS_STATUS_ERROR(status)) {
pe_err("Failed to register resp callback: %d", status);
return status;
}
status = wlan_cp_stats_send_infra_cp_req(mac->psoc, &info);
if (QDF_IS_STATUS_ERROR(status)) {
pe_err("Failed to send stats request status: %d", status);
goto get_stats_fail;
}
return QDF_STATUS_SUCCESS;
get_stats_fail:
status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
if (QDF_IS_STATUS_ERROR(status))
pe_err("failed to deregister callback %d", status);
return status;
}
#endif
/**
* rrm_process_sta_stats_report_req: Process RRM sta stats request
* @mac: mac context
* @pCurrentReq: Current RRM request
* @pStaStatsReq: RRM Measurement Request
* @pe_session: pe session
*
* Return: rrm status
*/
static tRrmRetStatus
rrm_process_sta_stats_report_req(struct mac_context *mac,
tpRRMReq pCurrentReq,
tDot11fIEMeasurementRequest *sta_stats_req,
struct pe_session *pe_session)
{
QDF_STATUS status;
uint8_t meas_duration = 1;
struct rrm_sta_stats *rrm_sta_statistics;
if (sta_stats_req->measurement_request.sta_stats.meas_duration >
MAX_MEAS_DURATION_FOR_STA_STATS) {
pe_err("Dropping req measurement duration > threshold %d",
sta_stats_req->measurement_request.sta_stats.meas_duration);
return eRRM_INCAPABLE;
}
if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)
sta_stats_req->measurement_request.sta_stats.peer_mac_addr)) {
pe_err("Dropping req: broadcast address not supported");
return eRRM_INCAPABLE;
}
rrm_sta_statistics = &mac->rrm.rrmPEContext.rrm_sta_stats;
if (sta_stats_req->measurement_request.sta_stats.meas_duration)
meas_duration =
sta_stats_req->measurement_request.sta_stats.meas_duration;
rrm_sta_statistics->rrm_report.token = pCurrentReq->token;
rrm_sta_statistics->rrm_report.type = pCurrentReq->type;
rrm_sta_statistics->rrm_report.refused = 0;
rrm_sta_statistics->rrm_report.incapable = 0;
rrm_sta_statistics->rrm_report.report.statistics_report.group_id =
sta_stats_req->measurement_request.sta_stats.group_identity;
rrm_sta_statistics->rrm_report.report.statistics_report.meas_duration
= sta_stats_req->measurement_request.sta_stats.meas_duration;
switch (sta_stats_req->measurement_request.sta_stats.group_identity) {
case STA_STAT_GROUP_ID_COUNTER_STATS:
case STA_STAT_GROUP_ID_MAC_STATS:
status =
rrm_send_sta_stats_req(
mac, pe_session,
sta_stats_req->measurement_request.sta_stats.peer_mac_addr);
if (!QDF_IS_STATUS_SUCCESS(status))
return eRRM_REFUSED;
mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId =
pe_session->peSessionId;
/*
* Start timer of 1 sec even if meas duration is 0.
* To get stats from FW.
*/
tx_timer_change(&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
SYS_MS_TO_TICKS(meas_duration * 1000), 0);
/* Activate sta stats resp timer */
if (tx_timer_activate(
&mac->lim.lim_timers.rrm_sta_stats_resp_timer) !=
TX_SUCCESS) {
pe_err("failed to start sta stats timer");
return eRRM_REFUSED;
}
break;
case STA_STAT_GROUP_ID_DELAY_STATS:
/* TODO: update access delay from scan IE */
default:
pe_nofl_err("group id %d not supported",
sta_stats_req->measurement_request.sta_stats.group_identity);
return eRRM_INCAPABLE;
}
return eRRM_SUCCESS;
}
void
rrm_process_rrm_sta_stats_request_failure(struct mac_context *mac,
struct pe_session *pe_session,
tSirMacAddr peer,
tRrmRetStatus status, uint8_t index)
{
tpSirMacRadioMeasureReport p_report = NULL;
tpRRMReq p_current_req = mac->rrm.rrmPEContext.pCurrentReq[index];
if (!p_current_req) {
pe_err("Current request is NULL");
return;
}
p_report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
if (!p_report)
return;
p_report->token = p_current_req->token;
p_report->type = SIR_MAC_RRM_STA_STATISTICS_TYPE;
pe_debug("Measurement index:%d status %d token %d", index, status,
p_report->token);
switch (status) {
case eRRM_FAILURE: /* fallthrough */
case eRRM_REFUSED:
p_report->refused = 1;
break;
case eRRM_INCAPABLE:
p_report->incapable = 1;
break;
default:
pe_err("Invalid RRM status, failed to send report");
qdf_mem_free(p_report);
return;
}
lim_send_radio_measure_report_action_frame(mac,
p_current_req->dialog_token,
1, true,
p_report, peer,
pe_session);
qdf_mem_free(p_report);
}
/**
* rrm_check_other_sta_sats_req_in_progress: To check if any other sta stats req
* in progress
* @rrm_req: measurement request
*
* To avoid any conflict between multiple sta stats request at time of callback
* response from FW handle one sta stats request at a time.
*
* Return: true/false
*/
static bool
rrm_check_other_sta_sats_req_in_progress(
tDot11fRadioMeasurementRequest *rrm_req)
{
uint8_t count = 0, i = 0;
for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
if (rrm_req->MeasurementRequest[i].measurement_type ==
SIR_MAC_RRM_STA_STATISTICS_TYPE)
count++;
if (count > 1)
return true;
}
return false;
}
/**
* rrm_process_sta_stats_req: Process RRM sta stats request
* @mac: mac context
* @session_entry: pe session
* @radiomes_report: measurement report
* @rrm_req: measurement request
* @num_report: no of reports
* @index: index of request
*
* Return: QDF_STATUS
*/
static
QDF_STATUS rrm_process_sta_stats_req(
struct mac_context *mac, tSirMacAddr peer,
struct pe_session *session_entry,
tpSirMacRadioMeasureReport *radiomes_report,
tDot11fRadioMeasurementRequest *rrm_req,
uint8_t *num_report, int index)
{
tRrmRetStatus rrm_status = eRRM_SUCCESS;
tpRRMReq curr_req;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (index >= MAX_MEASUREMENT_REQUEST) {
status = rrm_reject_req(radiomes_report,
rrm_req, num_report, index,
rrm_req->MeasurementRequest[0].
measurement_type);
return status;
}
if (rrm_check_other_sta_sats_req_in_progress(rrm_req)) {
pe_debug("another sta stats request already in progress");
return QDF_STATUS_E_FAILURE;
}
curr_req = qdf_mem_malloc(sizeof(*curr_req));
if (!curr_req) {
mac->rrm.rrmPEContext.pCurrentReq[index] = NULL;
qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
return QDF_STATUS_E_NOMEM;
}
curr_req->dialog_token = rrm_req->DialogToken.token;
curr_req->token =
rrm_req->MeasurementRequest[index].measurement_token;
curr_req->measurement_idx = index;
curr_req->type = rrm_req->MeasurementRequest[index].measurement_type;
qdf_mem_set(&mac->rrm.rrmPEContext.rrm_sta_stats,
sizeof(mac->rrm.rrmPEContext.rrm_sta_stats), 0);
mac->rrm.rrmPEContext.rrm_sta_stats.index = index;
mac->rrm.rrmPEContext.pCurrentReq[index] = curr_req;
mac->rrm.rrmPEContext.num_active_request++;
qdf_mem_copy(mac->rrm.rrmPEContext.rrm_sta_stats.peer,
peer,
QDF_MAC_ADDR_SIZE);
pe_debug("Processing sta stats Report req %d num_active_req:%d",
index, mac->rrm.rrmPEContext.num_active_request);
rrm_status = rrm_process_sta_stats_report_req(mac, curr_req,
&rrm_req->MeasurementRequest[index], session_entry);
if (eRRM_SUCCESS != rrm_status)
goto failure;
return QDF_STATUS_SUCCESS;
failure:
rrm_process_rrm_sta_stats_request_failure(
mac, session_entry, peer, rrm_status, index);
rrm_cleanup(mac, index);
return QDF_STATUS_E_FAILURE;
}
/* -------------------------------------------------------------------- */
/**
* rrm_get_max_meas_duration() - calculate max measurement duration for a
@@ -1849,6 +2358,12 @@ rrm_process_radio_measurement_request(struct mac_context *mac_ctx,
if (QDF_IS_STATUS_ERROR(status))
return status;
break;
case SIR_MAC_RRM_STA_STATISTICS_TYPE:
status = rrm_process_sta_stats_req(mac_ctx, peer,
session_entry, &report,
rrm_req, &num_report,
i);
break;
case SIR_MAC_RRM_LCI_TYPE:
case SIR_MAC_RRM_LOCATION_CIVIC_TYPE:
case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE:
@@ -1958,17 +2473,25 @@ void rrm_cleanup(struct mac_context *mac, uint8_t idx)
{
tpRRMReq cur_rrm_req = NULL;
mac->rrm.rrmPEContext.num_active_request--;
if (mac->rrm.rrmPEContext.num_active_request)
mac->rrm.rrmPEContext.num_active_request--;
cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx];
if (!cur_rrm_req)
return;
if (cur_rrm_req->request.Beacon.reqIes.num) {
qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds);
cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL;
cur_rrm_req->request.Beacon.reqIes.num = 0;
}
if (cur_rrm_req->type == SIR_MAC_RRM_STA_STATISTICS_TYPE) {
pe_debug("deactivate rrm sta stats timer");
lim_deactivate_and_change_timer(mac,
eLIM_RRM_STA_STATS_RSP_TIMER);
qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
}
qdf_mem_free(cur_rrm_req);
mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL;

Wyświetl plik

@@ -588,6 +588,7 @@ uint8_t *mac_trace_get_lim_msg_string(uint16_t lim_msg)
CASE_RETURN_STRING(SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT);
CASE_RETURN_STRING(SIR_LIM_AUTH_RETRY_TIMEOUT);
CASE_RETURN_STRING(SIR_LIM_AUTH_SAE_TIMEOUT);
CASE_RETURN_STRING(SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT);
CASE_RETURN_STRING(SIR_LIM_MSG_TYPES_END);
CASE_RETURN_STRING(LIM_MLM_SCAN_REQ);
CASE_RETURN_STRING(LIM_MLM_SCAN_CNF);

Wyświetl plik

@@ -7086,6 +7086,15 @@ populate_dot11f_chan_load_report(struct mac_context *mac,
dot11f->report.channel_load_report.chan_load);
}
QDF_STATUS
populate_dot11f_rrm_sta_stats_report(
struct mac_context *mac, tDot11fIEMeasurementReport *pdot11f,
struct statistics_report *statistics_report)
{
/* TODO: populate measurement report */
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_beacon_report(struct mac_context *mac,
tDot11fIEMeasurementReport *pDot11f,