qcacld-3.0: Send chan load response to AP

If a DUT accept channel load request, the STA should
response with a channel load report with channel
utilization measurement as observed by the measuring
STA.

Change-Id: Ic8faa45e24d7cd296e44828370b1b1088d46ddda
CRs-Fixed: 3580203
This commit is contained in:
Abhinav Kumar
2023-07-26 12:34:33 -07:00
committed by Rahul Choudhary
parent b89f7f0dde
commit f89f0e2de0
14 changed files with 384 additions and 21 deletions

View File

@@ -394,6 +394,19 @@ void wlan_cp_stats_update_chan_info(struct wlan_objmgr_psoc *psoc,
struct channel_status *chan_stat, struct channel_status *chan_stat,
uint8_t vdev_id); uint8_t vdev_id);
/**
* wlan_cp_stats_get_rx_clear_count() - API to get rx clear count for a channel
* @psoc: pointer to psoc
* @vdev_id: vdev id
* @channel: channel for which rx clear count require
* @chan_load: buffer to store rx clear count for a channel
*
* Return: None
*/
void wlan_cp_stats_get_rx_clear_count(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, uint8_t channel,
uint8_t *chan_load);
/** /**
* ucfg_mc_cp_stats_clear_channel_status() - API to clear chan stats * ucfg_mc_cp_stats_clear_channel_status() - API to clear chan stats
* @pdev: pointer to pdev object * @pdev: pointer to pdev object
@@ -506,6 +519,13 @@ void wlan_cp_stats_update_chan_info(struct wlan_objmgr_psoc *psoc,
{ {
} }
static inline
void wlan_cp_stats_get_rx_clear_count(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, uint8_t channel,
uint8_t *chan_load)
{
}
static inline static inline
void ucfg_mc_cp_stats_clear_channel_status(struct wlan_objmgr_pdev *pdev) void ucfg_mc_cp_stats_clear_channel_status(struct wlan_objmgr_pdev *pdev)
{ {

View File

@@ -1048,6 +1048,81 @@ void ucfg_mc_cp_stats_register_lost_link_info_cb(
psoc_cp_stats_priv->legacy_stats_cb = lost_link_cp_stats_info_cb; psoc_cp_stats_priv->legacy_stats_cb = lost_link_cp_stats_info_cb;
} }
#ifdef QCA_SUPPORT_CP_STATS
void wlan_cp_stats_get_rx_clear_count(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, uint8_t channel,
uint8_t *chan_load)
{
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_vdev *vdev;
struct pdev_cp_stats *pdev_cp_stats_priv;
struct per_channel_stats *channel_stats;
struct channel_status *channel_status_list;
uint8_t total_channel;
uint8_t i;
uint32_t rx_clear_count = 0, cycle_count = 0, mac_clk_mhz = 0;
uint64_t clock_freq, time, time_busy;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
WLAN_CP_STATS_ID);
if (!vdev)
return;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
cp_stats_err("pdev object is null");
goto release_ref;
}
pdev_cp_stats_priv = wlan_cp_stats_get_pdev_stats_obj(pdev);
if (!pdev_cp_stats_priv) {
cp_stats_err("pdev cp stats object is null");
goto release_ref;
}
channel_stats = &pdev_cp_stats_priv->pdev_stats->chan_stats;
channel_status_list = channel_stats->channel_status_list;
total_channel = channel_stats->total_channel;
for (i = 0; i < total_channel && i < NUM_CHANNELS; i++) {
if (channel_status_list[i].channel_id == channel) {
rx_clear_count = channel_status_list[i].rx_clear_count;
cycle_count = channel_status_list[i].cycle_count;
mac_clk_mhz = channel_status_list[i].mac_clk_mhz;
break;
}
}
if (i == total_channel) {
cp_stats_debug("no channel found for chan:%d", channel);
goto release_ref;
}
clock_freq = mac_clk_mhz * 1000;
if (clock_freq == 0) {
cp_stats_debug("clock_freq is zero");
goto release_ref;
}
time = qdf_do_div(cycle_count, clock_freq);
if (time == 0) {
cp_stats_debug("time is zero");
goto release_ref;
}
time_busy = qdf_do_div(rx_clear_count, clock_freq);
*chan_load = ((time_busy * 255) / time);
cp_stats_debug("t_chan:%d, chan:%d, rcc:%u, cc:%u, cf:%u, time:%u, time_busy:%u, chan_load:%d",
total_channel, channel, rx_clear_count, cycle_count,
clock_freq, time, time_busy, *chan_load);
release_ref:
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
#endif
#ifdef WLAN_POWER_MANAGEMENT_OFFLOAD #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
static QDF_STATUS static QDF_STATUS
ucfg_mc_cp_stats_suspend_req_handler(struct wlan_objmgr_psoc *psoc) ucfg_mc_cp_stats_suspend_req_handler(struct wlan_objmgr_psoc *psoc)

View File

@@ -1347,6 +1347,22 @@ typedef struct sSirMacBeaconReport {
} tSirMacBeaconReport, *tpSirMacBeaconReport; } tSirMacBeaconReport, *tpSirMacBeaconReport;
/**
* struct chan_load_report - channel load Report Structure
* @op_class: Regulatory Class
* @channel: Channel for which the current report is being sent
* @rrm_scan_tsf: RRM scan start time for this report
* @meas_duration: Scan duration for the current channel
* @chan_load: channel utilization measurement
*/
struct chan_load_report {
uint8_t op_class;
uint8_t channel;
qdf_time_t rrm_scan_tsf;
uint8_t meas_duration;
uint8_t chan_load;
};
typedef struct sSirMacRadioMeasureReport { typedef struct sSirMacRadioMeasureReport {
uint8_t token; uint8_t token;
uint8_t refused; uint8_t refused;
@@ -1354,6 +1370,7 @@ typedef struct sSirMacRadioMeasureReport {
uint8_t type; uint8_t type;
union { union {
tSirMacBeaconReport beaconReport; tSirMacBeaconReport beaconReport;
struct chan_load_report channel_load_report;
} report; } report;
} tSirMacRadioMeasureReport, *tpSirMacRadioMeasureReport; } tSirMacRadioMeasureReport, *tpSirMacRadioMeasureReport;

View File

@@ -86,8 +86,9 @@ enum eWniMsgTypes {
eWNI_SME_BEACON_REPORT_REQ_IND = SIR_SME_MSG_TYPES_BEGIN + 45, eWNI_SME_BEACON_REPORT_REQ_IND = SIR_SME_MSG_TYPES_BEGIN + 45,
eWNI_SME_BEACON_REPORT_RESP_XMIT_IND = SIR_SME_MSG_TYPES_BEGIN + 46, eWNI_SME_BEACON_REPORT_RESP_XMIT_IND = SIR_SME_MSG_TYPES_BEGIN + 46,
eWNI_SME_CHAN_LOAD_REQ_IND = SIR_SME_MSG_TYPES_BEGIN + 47, eWNI_SME_CHAN_LOAD_REQ_IND = SIR_SME_MSG_TYPES_BEGIN + 47,
eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND = SIR_SME_MSG_TYPES_BEGIN + 48,
/* unused SIR_SME_MSG_TYPES_BEGIN + 48, */ /* unused SIR_SME_MSG_TYPES_BEGIN + 49, */
eWNI_SME_FT_AGGR_QOS_REQ = SIR_SME_MSG_TYPES_BEGIN + 52, eWNI_SME_FT_AGGR_QOS_REQ = SIR_SME_MSG_TYPES_BEGIN + 52,
eWNI_SME_FT_AGGR_QOS_RSP = SIR_SME_MSG_TYPES_BEGIN + 53, eWNI_SME_FT_AGGR_QOS_RSP = SIR_SME_MSG_TYPES_BEGIN + 53,

View File

@@ -831,6 +831,19 @@ populate_dot11f_beacon_report(struct mac_context *mac,
tSirMacBeaconReport *pBeaconReport, tSirMacBeaconReport *pBeaconReport,
bool is_last_frame); bool is_last_frame);
/**
* populate_dot11f_chan_load_report() - populate the chan load Report IE
* @mac: pointer to the global MAC context
* @dot11f: pointer to the measurement report structure
* @channel_load_report: pointer to the chan load Report structure
*
* Return: none
*/
void
populate_dot11f_chan_load_report(struct mac_context *mac,
tDot11fIEMeasurementReport *dot11f,
struct chan_load_report *channel_load_report);
/** /**
* \brief Populate a tDot11fIEExtSuppRates * \brief Populate a tDot11fIEExtSuppRates
* *

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2011-2012, 2014-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2011-2012, 2014-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -90,6 +91,17 @@ QDF_STATUS
rrm_process_beacon_report_xmit(struct mac_context *mac_ctx, rrm_process_beacon_report_xmit(struct mac_context *mac_ctx,
tpSirBeaconReportXmitInd beacon_xmit_ind); tpSirBeaconReportXmitInd beacon_xmit_ind);
/**
* rrm_process_chan_load_report_xmit() - process channel load report xmit
* @mac_ctx: Mac context
* @chan_load_ind: channel load xmit structure
*
* Return: None
*/
void
rrm_process_chan_load_report_xmit(struct mac_context *mac_ctx,
struct chan_load_xmit_ind *chan_load_ind);
/** /**
* rrm_get_country_code_from_connected_profile() - get country code * rrm_get_country_code_from_connected_profile() - get country code
* from connected profile * from connected profile

View File

@@ -78,6 +78,34 @@ struct ch_load_ind {
uint16_t meas_duration; uint16_t meas_duration;
}; };
/**
* struct chan_load_xmit_ind - Contains info for channel load xmit indication
* @message_type: message type eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND
* @length: size of struct chan_load_req_ind
* @measurement_idx: measurement index for channel load request
* @peer_addr: MAC address of the BSS
* @dialog_token: dialog token
* @op_class: regulatory class
* @channel: channel number
* @duration: measurement duration in ms
* @chan_load: channel utilization measurement
* @rrm_scan_tsf: time at which driver triggers rrm scan for channel load
* @is_report_success: need to send failure report or not
*/
struct chan_load_xmit_ind {
uint16_t messageType;
uint16_t length;
uint8_t measurement_idx;
struct qdf_mac_addr peer_addr;
uint16_t dialog_token;
uint8_t op_class;
uint8_t channel;
uint16_t duration;
uint8_t chan_load;
qdf_time_t rrm_scan_tsf;
bool is_report_success;
};
typedef struct sSirBeaconReportReqInd { typedef struct sSirBeaconReportReqInd {
uint16_t messageType; /* eWNI_SME_BEACON_REPORT_REQ_IND */ uint16_t messageType; /* eWNI_SME_BEACON_REPORT_REQ_IND */
uint16_t length; uint16_t length;

View File

@@ -1755,6 +1755,7 @@ static void lim_process_messages(struct mac_context *mac_ctx,
case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: case eWNI_SME_CHNG_MCC_BEACON_INTERVAL:
case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
#if defined FEATURE_WLAN_ESE #if defined FEATURE_WLAN_ESE
case eWNI_SME_ESE_ADJACENT_AP_REPORT: case eWNI_SME_ESE_ADJACENT_AP_REPORT:
#endif #endif

View File

@@ -8018,6 +8018,9 @@ static void __lim_process_report_message(struct mac_context *mac,
case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
rrm_process_beacon_report_xmit(mac, pMsg->bodyptr); rrm_process_beacon_report_xmit(mac, pMsg->bodyptr);
break; break;
case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
rrm_process_chan_load_report_xmit(mac, pMsg->bodyptr);
break;
default: default:
pe_err("Invalid msg type: %d", pMsg->type); pe_err("Invalid msg type: %d", pMsg->type);
} }
@@ -8731,6 +8734,7 @@ bool lim_process_sme_req_messages(struct mac_context *mac,
case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND:
__lim_process_report_message(mac, pMsg); __lim_process_report_message(mac, pMsg);
break; break;
case eWNI_SME_FT_AGGR_QOS_REQ: case eWNI_SME_FT_AGGR_QOS_REQ:

View File

@@ -5676,6 +5676,16 @@ lim_send_radio_measure_report_action_frame(struct mac_context *mac,
pRRMReport[i].refused; pRRMReport[i].refused;
frm->MeasurementReport[i].present = 1; frm->MeasurementReport[i].present = 1;
break; break;
case SIR_MAC_RRM_CHANNEL_LOAD_TYPE:
populate_dot11f_chan_load_report(mac,
&frm->MeasurementReport[i],
&pRRMReport[i].report.channel_load_report);
frm->MeasurementReport[i].incapable =
pRRMReport[i].incapable;
frm->MeasurementReport[i].refused =
pRRMReport[i].refused;
frm->MeasurementReport[i].present = 1;
break;
default: default:
frm->MeasurementReport[i].incapable = frm->MeasurementReport[i].incapable =
pRRMReport[i].incapable; pRRMReport[i].incapable;
@@ -5751,14 +5761,12 @@ lim_send_radio_measure_report_action_frame(struct mac_context *mac,
wlan_vdev_get_id(pe_session->vdev)); wlan_vdev_get_id(pe_session->vdev));
} }
pe_nofl_info("TX: %s seq_no:%d dialog_token:%d no. of APs:%d is_last_rpt:%d num_report: %d peer:"QDF_MAC_ADDR_FMT, pe_nofl_info("TX: type:%d seq_no:%d dialog_token:%d no. of APs:%d is_last_rpt:%d num_report:%d peer:"QDF_MAC_ADDR_FMT,
frm->MeasurementReport[0].type == SIR_MAC_RRM_BEACON_TYPE ? frm->MeasurementReport[0].type,
"[802.11 BCN_RPT]" : "[802.11 RRM]",
(pMacHdr->seqControl.seqNumHi << HIGH_SEQ_NUM_OFFSET | (pMacHdr->seqControl.seqNumHi << HIGH_SEQ_NUM_OFFSET |
pMacHdr->seqControl.seqNumLo), pMacHdr->seqControl.seqNumLo),
dialog_token, frm->num_MeasurementReport, dialog_token, frm->num_MeasurementReport,
is_last_report, num_report, is_last_report, num_report, QDF_MAC_ADDR_REF(peer));
QDF_MAC_ADDR_REF(peer));
if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) || if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
pe_session->opmode == QDF_P2P_CLIENT_MODE || pe_session->opmode == QDF_P2P_CLIENT_MODE ||
@@ -5775,7 +5783,7 @@ lim_send_radio_measure_report_action_frame(struct mac_context *mac,
pe_session->peSessionId, qdf_status)); pe_session->peSessionId, qdf_status));
if (QDF_STATUS_SUCCESS != qdf_status) { if (QDF_STATUS_SUCCESS != qdf_status) {
pe_nofl_err("TX: [802.11 RRM] Send FAILED! err_status [%d]", pe_nofl_err("TX: [802.11 RRM] Send FAILED! err_status [%d]",
qdf_status); qdf_status);
status_code = QDF_STATUS_E_FAILURE; status_code = QDF_STATUS_E_FAILURE;
/* Pkt will be freed up by the callback */ /* Pkt will be freed up by the callback */
} }

View File

@@ -1524,6 +1524,95 @@ cleanup:
rrm_cleanup(mac, index); rrm_cleanup(mac, index);
} }
void
rrm_process_chan_load_report_xmit(struct mac_context *mac_ctx,
struct chan_load_xmit_ind *chan_load_ind)
{
tSirMacRadioMeasureReport *report = NULL;
struct chan_load_report *channel_load_report;
tpRRMReq curr_req;
struct pe_session *session_entry;
uint8_t session_id, idx;
struct qdf_mac_addr sessionBssId;
if (!chan_load_ind) {
pe_err("Received chan_load_xmit_ind is NULL in PE");
return;
}
idx = chan_load_ind->measurement_idx;
if (idx >= QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)) {
pe_err("Received measurement_idx is out of range: %u - %zu",
idx,
QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq));
return;
}
curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[idx];
if (!curr_req) {
pe_err("no request pending in PE");
goto end;
}
pe_debug("Received chan load report xmit indication on idx:%d", idx);
sessionBssId = mac_ctx->rrm.rrmSmeContext[idx].sessionBssId;
session_entry = pe_find_session_by_bssid(mac_ctx, sessionBssId.bytes,
&session_id);
if (!session_entry) {
pe_err("NULL session for bssId "QDF_MAC_ADDR_FMT"",
QDF_MAC_ADDR_REF(sessionBssId.bytes));
goto end;
}
if (!chan_load_ind->is_report_success) {
rrm_process_chan_load_request_failure(mac_ctx, session_entry,
sessionBssId.bytes,
eRRM_REFUSED, idx);
return;
}
report = qdf_mem_malloc(sizeof(*report));
if (!report)
goto end;
/* Prepare the channel load report and send it to the peer.*/
report->token = chan_load_ind->dialog_token;
report->refused = 0;
report->incapable = 0;
report->type = SIR_MAC_RRM_CHANNEL_LOAD_TYPE;
channel_load_report = &report[0].report.channel_load_report;
channel_load_report->op_class = chan_load_ind->op_class;
channel_load_report->channel = chan_load_ind->channel;
channel_load_report->rrm_scan_tsf = chan_load_ind->rrm_scan_tsf;
channel_load_report->meas_duration = chan_load_ind->duration;
channel_load_report->chan_load = chan_load_ind->chan_load;
pe_err("send chan load report for bssId:"QDF_MAC_ADDR_FMT" reg_class:%d, channel:%d, measStartTime:%llu, measDuration:%d, chan_load:%d",
QDF_MAC_ADDR_REF(sessionBssId.bytes),
channel_load_report->op_class,
channel_load_report->channel,
channel_load_report->rrm_scan_tsf,
channel_load_report->meas_duration,
channel_load_report->chan_load);
lim_send_radio_measure_report_action_frame(mac_ctx,
curr_req->dialog_token, 1,
true, &report[0],
sessionBssId.bytes,
session_entry);
end:
pe_debug("Measurement done idx:%d", idx);
rrm_cleanup(mac_ctx, idx);
qdf_mem_free(report);
return;
}
/** /**
* rrm_process_chan_load_req() - process channel load request * rrm_process_chan_load_req() - process channel load request
* @mac_ctx: Global pointer to MAC context * @mac_ctx: Global pointer to MAC context
@@ -1870,18 +1959,21 @@ void rrm_cleanup(struct mac_context *mac, uint8_t idx)
tpRRMReq cur_rrm_req = NULL; tpRRMReq cur_rrm_req = NULL;
mac->rrm.rrmPEContext.num_active_request--; mac->rrm.rrmPEContext.num_active_request--;
pe_debug("Beacon report cleanup idx:%d, num_active_request:%d",
idx, mac->rrm.rrmPEContext.num_active_request);
cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx]; cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx];
if (!cur_rrm_req) if (!cur_rrm_req)
return; return;
qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds); if (cur_rrm_req->request.Beacon.reqIes.num) {
cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL; qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds);
cur_rrm_req->request.Beacon.reqIes.num = 0; cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL;
cur_rrm_req->request.Beacon.reqIes.num = 0;
}
qdf_mem_free(cur_rrm_req); qdf_mem_free(cur_rrm_req);
mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL; mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL;
pe_debug("cleanup rrm req idx:%d, num_active_request:%d",
idx, mac->rrm.rrmPEContext.num_active_request);
} }
/** /**

View File

@@ -215,6 +215,7 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg)
CASE_RETURN_STRING(eWNI_SME_NEIGHBOR_REPORT_IND); CASE_RETURN_STRING(eWNI_SME_NEIGHBOR_REPORT_IND);
CASE_RETURN_STRING(eWNI_SME_BEACON_REPORT_REQ_IND); CASE_RETURN_STRING(eWNI_SME_BEACON_REPORT_REQ_IND);
CASE_RETURN_STRING(eWNI_SME_BEACON_REPORT_RESP_XMIT_IND); CASE_RETURN_STRING(eWNI_SME_BEACON_REPORT_RESP_XMIT_IND);
CASE_RETURN_STRING(eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND);
CASE_RETURN_STRING(eWNI_SME_CHAN_LOAD_REQ_IND); CASE_RETURN_STRING(eWNI_SME_CHAN_LOAD_REQ_IND);
CASE_RETURN_STRING(eWNI_SME_FT_AGGR_QOS_REQ); CASE_RETURN_STRING(eWNI_SME_FT_AGGR_QOS_REQ);
CASE_RETURN_STRING(eWNI_SME_FT_AGGR_QOS_RSP); CASE_RETURN_STRING(eWNI_SME_FT_AGGR_QOS_RSP);

View File

@@ -7061,6 +7061,31 @@ QDF_STATUS populate_dot11f_wfatpc(struct mac_context *mac,
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
void
populate_dot11f_chan_load_report(struct mac_context *mac,
tDot11fIEMeasurementReport *dot11f,
struct chan_load_report *channel_load_report)
{
dot11f->report.channel_load_report.op_class =
channel_load_report->op_class;
dot11f->report.channel_load_report.channel =
channel_load_report->channel;
qdf_mem_copy(dot11f->report.channel_load_report.meas_start_time,
&channel_load_report->rrm_scan_tsf,
sizeof(dot11f->report.channel_load_report.meas_start_time));
dot11f->report.channel_load_report.meas_duration =
channel_load_report->meas_duration;
dot11f->report.channel_load_report.chan_load =
channel_load_report->chan_load;
pe_debug("regClass %d chan %d meas_time %d meas_dur %d, chan_load %d",
dot11f->report.channel_load_report.op_class,
dot11f->report.channel_load_report.channel,
channel_load_report->rrm_scan_tsf,
dot11f->report.channel_load_report.meas_duration,
dot11f->report.channel_load_report.chan_load);
}
QDF_STATUS QDF_STATUS
populate_dot11f_beacon_report(struct mac_context *mac, populate_dot11f_beacon_report(struct mac_context *mac,
tDot11fIEMeasurementReport *pDot11f, tDot11fIEMeasurementReport *pDot11f,

View File

@@ -41,6 +41,7 @@
#include <wlan_utility.h> #include <wlan_utility.h>
#include <../../core/src/wlan_cm_vdev_api.h> #include <../../core/src/wlan_cm_vdev_api.h>
#include "rrm_api.h" #include "rrm_api.h"
#include "wlan_cp_stats_mc_ucfg_api.h"
/* Roam score for a neighbor AP will be calculated based on the below /* Roam score for a neighbor AP will be calculated based on the below
* definitions. The calculated roam score will be used to select the * definitions. The calculated roam score will be used to select the
@@ -713,12 +714,58 @@ end:
return qdf_status; return qdf_status;
} }
/**
* sme_rrm_send_chan_load_report_xmit_ind() -Sends the chan load report xmit
* to PE
* @mac: global mac context
* @rrm_sme_ctx: SME rrm context for measurement request
* @vdev_id: vdev id
* @is_report_success: need to send failure report or not
*
* The sme module calls this function once it finish the scan request
* and this function send the chan load report xmit to PE.
*
* Return : None
*/
static void
sme_rrm_send_chan_load_report_xmit_ind(struct mac_context *mac,
tpRrmSMEContext rrm_sme_ctx,
uint8_t vdev_id,
bool is_report_success)
{
uint8_t measurement_index = rrm_sme_ctx->measurement_idx;
struct chan_load_xmit_ind *chan_load_resp;
uint16_t length;
tpRrmSMEContext rrm_ctx = &mac->rrm.rrmSmeContext[measurement_index];
length = sizeof(struct chan_load_xmit_ind);
chan_load_resp = qdf_mem_malloc(length);
if (!chan_load_resp)
return;
chan_load_resp->messageType = eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND;
chan_load_resp->is_report_success = is_report_success;
chan_load_resp->length = length;
chan_load_resp->measurement_idx = measurement_index;
chan_load_resp->dialog_token = rrm_ctx->token;
chan_load_resp->duration = rrm_ctx->duration[0];
chan_load_resp->op_class = rrm_ctx->regClass;
chan_load_resp->channel = rrm_ctx->chan_load_req_info.channel;
chan_load_resp->rrm_scan_tsf = rrm_ctx->chan_load_req_info.rrm_scan_tsf;
wlan_cp_stats_get_rx_clear_count(mac->psoc, vdev_id,
rrm_ctx->chan_load_req_info.channel,
&chan_load_resp->chan_load);
sme_debug("SME Sending CHAN_LOAD_REPORT_RESP_XMIT_IND to PE");
umac_send_mb_message_to_mac(chan_load_resp);
}
static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev, static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev,
struct scan_event *event, void *arg) struct scan_event *event, void *arg)
{ {
struct mac_context *mac_ctx; struct mac_context *mac_ctx;
uint32_t scan_id; uint32_t scan_id;
uint8_t session_id, i; uint8_t vdev_id, i;
eCsrScanStatus scan_status = eCSR_SCAN_FAILURE; eCsrScanStatus scan_status = eCSR_SCAN_FAILURE;
bool success = false; bool success = false;
tpRrmSMEContext smerrmctx; tpRrmSMEContext smerrmctx;
@@ -729,7 +776,7 @@ static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev,
return; return;
} }
session_id = wlan_vdev_get_id(vdev); vdev_id = wlan_vdev_get_id(vdev);
scan_id = event->scan_id; scan_id = event->scan_id;
qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SME, event->type, qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SME, event->type,
@@ -750,10 +797,24 @@ static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev,
return; return;
} }
sme_debug("Scan completed for scan_id:%d measurement_idx:%d", sme_debug("vdev: %d : Scan completed for scan_id:%d idx:%d, type:%d",
scan_id, smerrmctx->measurement_idx); vdev_id, scan_id, smerrmctx->measurement_idx,
sme_rrm_scan_request_callback(mac_ctx, smerrmctx, session_id, smerrmctx->measurement_type);
scan_id, scan_status);
switch (smerrmctx->measurement_type) {
case RRM_CHANNEL_LOAD:
sme_rrm_send_chan_load_report_xmit_ind(mac_ctx, smerrmctx,
vdev_id, true);
break;
case RRM_BEACON_REPORT:
sme_rrm_scan_request_callback(mac_ctx, smerrmctx, vdev_id,
scan_id, scan_status);
break;
default:
sme_err("Unknown measurement_type: %d",
smerrmctx->measurement_type);
break;
}
} }
#define RRM_CHAN_WEIGHT_CHAR_LEN 5 #define RRM_CHAN_WEIGHT_CHAR_LEN 5
@@ -1212,7 +1273,9 @@ error_handle:
qdf_mem_free(req); qdf_mem_free(req);
wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
send_ind: send_ind:
//TODO: Send channel load report xmit indication and free current req sme_rrm_send_chan_load_report_xmit_ind(mac_ctx, sme_rrm_ctx,
vdev_id, false);
rrm_cleanup(mac_ctx, idx);
return status; return status;
} }
@@ -1491,11 +1554,14 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(struct mac_context *mac,
(uint8_t *)&beacon_req->measurementDuration, (uint8_t *)&beacon_req->measurementDuration,
SIR_ESE_MAX_MEAS_IE_REQS); SIR_ESE_MAX_MEAS_IE_REQS);
sme_debug("token: %d randnIntvl: %d msgSource: %d measurementduration %d, rrm_ctx duration %d Meas_mode: %s", sme_rrm_ctx->measurement_type = RRM_BEACON_REPORT;
sme_debug("token: %d randnIntvl: %d msgSource: %d measurementduration %d, rrm_ctx duration %d Meas_mode: %s, type: %d",
sme_rrm_ctx->token, sme_rrm_ctx->randnIntvl, sme_rrm_ctx->token, sme_rrm_ctx->randnIntvl,
sme_rrm_ctx->msgSource, beacon_req->measurementDuration[0], sme_rrm_ctx->msgSource, beacon_req->measurementDuration[0],
sme_rrm_ctx->duration[0], sme_rrm_ctx->duration[0],
sme_rrm_get_meas_mode_string(sme_rrm_ctx->measMode[0])); sme_rrm_get_meas_mode_string(sme_rrm_ctx->measMode[0]),
sme_rrm_ctx->measurement_type);
return sme_rrm_issue_scan_req(mac, beacon_req->measurement_idx); return sme_rrm_issue_scan_req(mac, beacon_req->measurement_idx);