1 /*
2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**=========================================================================
21
22 \file rrm_api.c
23
24 \brief implementation for PE RRM APIs
25
26 ========================================================================*/
27
28 /* $Header$ */
29
30
31 /*--------------------------------------------------------------------------
32 Include Files
33 ------------------------------------------------------------------------*/
34 #include "cds_api.h"
35 #include "wni_api.h"
36 #include "sir_api.h"
37 #include "ani_global.h"
38 #include "wni_cfg.h"
39 #include "lim_types.h"
40 #include "lim_utils.h"
41 #include "lim_send_sme_rsp_messages.h"
42 #include "parser_api.h"
43 #include "lim_send_messages.h"
44 #include "rrm_global.h"
45 #include "rrm_api.h"
46 #include "wlan_lmac_if_def.h"
47 #include "wlan_reg_services_api.h"
48 #include "wlan_cp_stats_utils_api.h"
49 #include "../../core/src/wlan_cp_stats_obj_mgr_handler.h"
50 #include "../../core/src/wlan_cp_stats_defs.h"
51 #include "cdp_txrx_host_stats.h"
52 #include "utils_mlo.h"
53 #include "wlan_mlo_mgr_sta.h"
54 #include <wlan_policy_mgr_ll_sap.h>
55
56 #define MAX_CTRL_STAT_VDEV_ENTRIES 1
57 #define MAX_CTRL_STAT_MAC_ADDR_ENTRIES 1
58 #define MAX_RMM_STA_STATS_REQUESTED 2
59 #define MIN_MEAS_DURATION_FOR_STA_STATS 10
60
61 /* Max passive scan dwell for wide band rrm scan, in milliseconds */
62 #define RRM_SCAN_MAX_DWELL_TIME 110
63
64 /**
65 * rrm_cache_mgmt_tx_power() - Store Tx power for management frames.
66 * @mac: pointer to mac context
67 * @txPower: TX power
68 * @pe_session: per vdev pe context
69 *
70 * Return: None
71 */
72 void
rrm_cache_mgmt_tx_power(struct mac_context * mac,int8_t txPower,struct pe_session * pe_session)73 rrm_cache_mgmt_tx_power(struct mac_context *mac, int8_t txPower,
74 struct pe_session *pe_session)
75 {
76 pe_debug("Cache Mgmt Tx Power: %d", txPower);
77
78 if (!pe_session)
79 mac->rrm.rrmPEContext.txMgmtPower = txPower;
80 else
81 pe_session->txMgmtPower = txPower;
82 }
83
84 /**
85 * rrm_get_mgmt_tx_power() - Get the Tx power for management frames.
86 * @mac: pointer to mac context
87 * @pe_session: per vdev pe context
88 *
89 * Return: TX power
90 */
rrm_get_mgmt_tx_power(struct mac_context * mac,struct pe_session * pe_session)91 int8_t rrm_get_mgmt_tx_power(struct mac_context *mac, struct pe_session *pe_session)
92 {
93 if (!pe_session)
94 return mac->rrm.rrmPEContext.txMgmtPower;
95
96 pe_debug("tx mgmt pwr %d", pe_session->txMgmtPower);
97
98 return pe_session->txMgmtPower;
99 }
100
101 /**
102 * rrm_send_set_max_tx_power_req() - Send WMA_SET_MAX_TX_POWER_REQ message
103 * to change the max tx power.
104 * @mac: pointer to mac context
105 * @txPower: TX power to be set
106 * @pe_session: per vdev pe context
107 *
108 * Return: None
109 */
110 QDF_STATUS
rrm_send_set_max_tx_power_req(struct mac_context * mac,int8_t txPower,struct pe_session * pe_session)111 rrm_send_set_max_tx_power_req(struct mac_context *mac, int8_t txPower,
112 struct pe_session *pe_session)
113 {
114 tpMaxTxPowerParams pMaxTxParams;
115 QDF_STATUS retCode = QDF_STATUS_SUCCESS;
116 struct scheduler_msg msgQ = {0};
117
118 if (!pe_session) {
119 pe_err("Invalid parameters");
120 return QDF_STATUS_E_FAILURE;
121 }
122 pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams));
123 if (!pMaxTxParams)
124 return QDF_STATUS_E_NOMEM;
125 /* Allocated memory for pMaxTxParams...will be freed in other module */
126 pMaxTxParams->power = txPower;
127 qdf_mem_copy(pMaxTxParams->bssId.bytes, pe_session->bssId,
128 QDF_MAC_ADDR_SIZE);
129 qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes,
130 pe_session->self_mac_addr,
131 QDF_MAC_ADDR_SIZE);
132
133 msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
134 msgQ.reserved = 0;
135 msgQ.bodyptr = pMaxTxParams;
136 msgQ.bodyval = 0;
137
138 pe_debug("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL",
139 txPower);
140
141 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type));
142 retCode = wma_post_ctrl_msg(mac, &msgQ);
143 if (QDF_STATUS_SUCCESS != retCode) {
144 pe_err("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X",
145 retCode);
146 qdf_mem_free(pMaxTxParams);
147 return retCode;
148 }
149 return retCode;
150 }
151
152 /**
153 * rrm_set_max_tx_power_rsp() - Process WMA_SET_MAX_TX_POWER_RSP message
154 * @mac: pointer to mac context
155 * @limMsgQ: pointer to scheduler message
156 *
157 * Return: None
158 */
rrm_set_max_tx_power_rsp(struct mac_context * mac,struct scheduler_msg * limMsgQ)159 QDF_STATUS rrm_set_max_tx_power_rsp(struct mac_context *mac,
160 struct scheduler_msg *limMsgQ)
161 {
162 QDF_STATUS retCode = QDF_STATUS_SUCCESS;
163 tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr;
164 struct pe_session *pe_session;
165 uint8_t sessionId, i;
166
167 if (qdf_is_macaddr_broadcast(&pMaxTxParams->bssId)) {
168 for (i = 0; i < mac->lim.maxBssId; i++) {
169 if (mac->lim.gpSession[i].valid == true) {
170 pe_session = &mac->lim.gpSession[i];
171 rrm_cache_mgmt_tx_power(mac, pMaxTxParams->power,
172 pe_session);
173 }
174 }
175 } else {
176 pe_session = pe_find_session_by_bssid(mac,
177 pMaxTxParams->bssId.bytes,
178 &sessionId);
179 if (!pe_session) {
180 retCode = QDF_STATUS_E_FAILURE;
181 } else {
182 rrm_cache_mgmt_tx_power(mac, pMaxTxParams->power,
183 pe_session);
184 }
185 }
186
187 qdf_mem_free(limMsgQ->bodyptr);
188 limMsgQ->bodyptr = NULL;
189 return retCode;
190 }
191
192 /**
193 * rrm_calculate_and_fill_rcpi() - calculates and fills RCPI value
194 * @rcpi: pointer to hold calculated RCPI value
195 * @cur_rssi: value of current RSSI
196 *
197 * @return None
198 */
rrm_calculate_and_fill_rcpi(uint8_t * rcpi,int8_t cur_rssi)199 static void rrm_calculate_and_fill_rcpi(uint8_t *rcpi, int8_t cur_rssi)
200 {
201 /* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */
202 if (cur_rssi <= RCPI_LOW_RSSI_VALUE)
203 *rcpi = 0;
204 else if ((cur_rssi > RCPI_LOW_RSSI_VALUE) && (cur_rssi <= 0))
205 *rcpi = CALCULATE_RCPI(cur_rssi);
206 else
207 *rcpi = RCPI_MAX_VALUE;
208 }
209
210 /**
211 * rrm_process_link_measurement_request() - Processes the Link measurement
212 * request and send the report.
213 * @mac: pointer to mac context
214 * @pRxPacketInfo: pointer to packet info structure
215 * @pLinkReq: pointer to the Link request frame structure.
216 * @pe_session: session entry.
217 *
218 * Return: None
219 */
220 QDF_STATUS
rrm_process_link_measurement_request(struct mac_context * mac,uint8_t * pRxPacketInfo,tDot11fLinkMeasurementRequest * pLinkReq,struct pe_session * pe_session)221 rrm_process_link_measurement_request(struct mac_context *mac,
222 uint8_t *pRxPacketInfo,
223 tDot11fLinkMeasurementRequest *pLinkReq,
224 struct pe_session *pe_session)
225 {
226 tSirMacLinkReport LinkReport = {0};
227 tpSirMacMgmtHdr pHdr;
228 int8_t currentRSSI = 0;
229 struct vdev_mlme_obj *mlme_obj;
230 struct wlan_lmac_if_reg_tx_ops *tx_ops;
231 uint8_t ap_pwr_constraint = 0;
232
233 pe_debug("Received Link measurement request");
234
235 if (!pRxPacketInfo || !pLinkReq || !pe_session) {
236 pe_err("Invalid parameters - Ignoring the request");
237 return QDF_STATUS_E_FAILURE;
238 }
239 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
240
241 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
242 if (!mlme_obj) {
243 pe_err("vdev component object is NULL");
244 return QDF_STATUS_E_INVAL;
245 }
246
247 /*
248 * STA LPI + SAP VLP is supported. For this STA should operate in VLP
249 * power level of the SAP.
250 * If STA is operating in VLP power of SAP, do not update STA power.
251 */
252 if (wlan_reg_is_ext_tpc_supported(mac->psoc) &&
253 !pe_session->sta_follows_sap_power) {
254 ap_pwr_constraint = mlme_obj->reg_tpc_obj.ap_constraint_power;
255 mlme_obj->reg_tpc_obj.ap_constraint_power =
256 pLinkReq->MaxTxPower.maxTxPower;
257 /* Set is_power_constraint_abs to true to calculate tpc power */
258 mlme_obj->reg_tpc_obj.is_power_constraint_abs = true;
259 lim_calculate_tpc(mac, pe_session);
260
261 LinkReport.txPower =
262 mlme_obj->reg_tpc_obj.chan_power_info[0].tx_power;
263 /** If hardware limit received from FW is non zero, use it
264 * to limit the link tx power.
265 */
266 if (mlme_obj->mgmt.generic.tx_pwrlimit) {
267 LinkReport.txPower =
268 QDF_MIN(LinkReport.txPower,
269 mlme_obj->mgmt.generic.tx_pwrlimit);
270 pe_debug("HW power limit: %d, Link tx power: %d",
271 mlme_obj->mgmt.generic.tx_pwrlimit,
272 LinkReport.txPower);
273 }
274 if (LinkReport.txPower < MIN_TX_PWR_CAP)
275 LinkReport.txPower = MIN_TX_PWR_CAP;
276 else if (LinkReport.txPower > MAX_TX_PWR_CAP)
277 LinkReport.txPower = MAX_TX_PWR_CAP;
278
279 if (pLinkReq->MaxTxPower.maxTxPower != ap_pwr_constraint) {
280 tx_ops = wlan_reg_get_tx_ops(mac->psoc);
281
282 if (tx_ops->set_tpc_power)
283 tx_ops->set_tpc_power(mac->psoc,
284 pe_session->vdev_id,
285 &mlme_obj->reg_tpc_obj);
286 }
287 } else if (!pe_session->sta_follows_sap_power) {
288 mlme_obj->reg_tpc_obj.reg_max[0] =
289 pe_session->def_max_tx_pwr;
290 mlme_obj->reg_tpc_obj.ap_constraint_power =
291 pLinkReq->MaxTxPower.maxTxPower;
292
293 LinkReport.txPower = lim_get_max_tx_power(mac, mlme_obj);
294
295 /** If firmware updated max tx power is non zero, respond to
296 * rrm link measurement request with min of firmware updated
297 * ap tx power and max power derived from lim_get_max_tx_power
298 * API.
299 */
300 if (mlme_obj && mlme_obj->mgmt.generic.tx_pwrlimit)
301 LinkReport.txPower = QDF_MIN(LinkReport.txPower,
302 mlme_obj->mgmt.generic.tx_pwrlimit);
303
304 if ((LinkReport.txPower != (uint8_t)pe_session->maxTxPower) &&
305 (QDF_STATUS_SUCCESS ==
306 rrm_send_set_max_tx_power_req(mac, LinkReport.txPower,
307 pe_session))) {
308 pe_warn("Local: %d", pe_session->maxTxPower);
309 pe_session->maxTxPower = LinkReport.txPower;
310 }
311 }
312 pe_warn_rl("Link Request Tx Pwr: %d Link Report Tx Pwr: %d",
313 pLinkReq->MaxTxPower.maxTxPower, LinkReport.txPower);
314
315 LinkReport.dialogToken = pLinkReq->DialogToken.token;
316 LinkReport.rxAntenna = 0;
317 LinkReport.txAntenna = 0;
318 currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo);
319
320 pe_info_rl("Received Link report frame with %d", currentRSSI);
321
322 rrm_calculate_and_fill_rcpi(&LinkReport.rcpi, currentRSSI);
323 LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo);
324
325 pe_debug("Sending Link report frame");
326
327 return lim_send_link_report_action_frame(mac, &LinkReport, pHdr->sa,
328 pe_session);
329 }
330
331 /**
332 * rrm_process_neighbor_report_response() - Processes the Neighbor Report
333 * response from the peer AP.
334 * @mac: pointer to mac context
335 * @pNeighborRep: pointer to the Neighbor report frame structure.
336 * @pe_session: session entry.
337 *
338 * Return: None
339 */
340 QDF_STATUS
rrm_process_neighbor_report_response(struct mac_context * mac,tDot11fNeighborReportResponse * pNeighborRep,struct pe_session * pe_session)341 rrm_process_neighbor_report_response(struct mac_context *mac,
342 tDot11fNeighborReportResponse *pNeighborRep,
343 struct pe_session *pe_session)
344 {
345 QDF_STATUS status = QDF_STATUS_SUCCESS;
346 tpSirNeighborReportInd pSmeNeighborRpt = NULL;
347 uint16_t length;
348 uint8_t i;
349 struct scheduler_msg mmhMsg = {0};
350
351 if (!pNeighborRep || !pe_session) {
352 pe_err("Invalid parameters");
353 return status;
354 }
355
356 pe_debug("Neighbor report response received");
357
358 /* Dialog token */
359 if (mac->rrm.rrmPEContext.DialogToken !=
360 pNeighborRep->DialogToken.token) {
361 pe_err("Dialog token mismatch in the received Neighbor report");
362 return QDF_STATUS_E_FAILURE;
363 }
364 if (pNeighborRep->num_NeighborReport == 0) {
365 pe_err("No neighbor report in the frame...Dropping it");
366 return QDF_STATUS_E_FAILURE;
367 }
368 pe_debug("RRM:received num neighbor reports: %d",
369 pNeighborRep->num_NeighborReport);
370 if (pNeighborRep->num_NeighborReport > MAX_SUPPORTED_NEIGHBOR_RPT)
371 pNeighborRep->num_NeighborReport = MAX_SUPPORTED_NEIGHBOR_RPT;
372 length = (sizeof(tSirNeighborReportInd)) +
373 (sizeof(tSirNeighborBssDescription) *
374 (pNeighborRep->num_NeighborReport - 1));
375
376 /* Prepare the request to send to SME. */
377 pSmeNeighborRpt = qdf_mem_malloc(length);
378 if (!pSmeNeighborRpt)
379 return QDF_STATUS_E_NOMEM;
380
381 /* Allocated memory for pSmeNeighborRpt...will be freed by other module */
382
383 for (i = 0; i < pNeighborRep->num_NeighborReport; i++) {
384 pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof(tSirNeighborBssDescription); /*+ any optional ies */
385 qdf_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId,
386 pNeighborRep->NeighborReport[i].bssid,
387 sizeof(tSirMacAddr));
388 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
389 fApPreauthReachable =
390 pNeighborRep->NeighborReport[i].APReachability;
391 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
392 fSameSecurityMode =
393 pNeighborRep->NeighborReport[i].Security;
394 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
395 fSameAuthenticator =
396 pNeighborRep->NeighborReport[i].KeyScope;
397 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
398 fCapSpectrumMeasurement =
399 pNeighborRep->NeighborReport[i].SpecMgmtCap;
400 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
401 fCapQos = pNeighborRep->NeighborReport[i].QosCap;
402 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
403 fCapApsd = pNeighborRep->NeighborReport[i].apsd;
404 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
405 fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm;
406 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
407 fCapDelayedBlockAck =
408 pNeighborRep->NeighborReport[i].DelayedBA;
409 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
410 fCapImmediateBlockAck =
411 pNeighborRep->NeighborReport[i].ImmBA;
412 pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
413 fMobilityDomain =
414 pNeighborRep->NeighborReport[i].MobilityDomain;
415
416 if (!wlan_reg_is_6ghz_supported(mac->psoc) &&
417 (wlan_reg_is_6ghz_op_class(mac->pdev,
418 pNeighborRep->NeighborReport[i].
419 regulatoryClass))) {
420 pe_err("channel belongs to 6 ghz spectrum, abort");
421 qdf_mem_free(pSmeNeighborRpt);
422 return QDF_STATUS_E_FAILURE;
423 }
424
425 pSmeNeighborRpt->sNeighborBssDescription[i].regClass =
426 pNeighborRep->NeighborReport[i].regulatoryClass;
427 pSmeNeighborRpt->sNeighborBssDescription[i].channel =
428 pNeighborRep->NeighborReport[i].channel;
429 pSmeNeighborRpt->sNeighborBssDescription[i].phyType =
430 pNeighborRep->NeighborReport[i].PhyType;
431 }
432
433 pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND;
434 pSmeNeighborRpt->length = length;
435 pSmeNeighborRpt->measurement_idx = DEFAULT_RRM_IDX;
436 pSmeNeighborRpt->sessionId = pe_session->smeSessionId;
437 pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport;
438 qdf_mem_copy(pSmeNeighborRpt->bssId, pe_session->bssId,
439 sizeof(tSirMacAddr));
440
441 /* Send request to SME. */
442 mmhMsg.type = pSmeNeighborRpt->messageType;
443 mmhMsg.bodyptr = pSmeNeighborRpt;
444 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
445 pe_session->peSessionId, mmhMsg.type));
446 lim_sys_process_mmh_msg_api(mac, &mmhMsg);
447
448 return status;
449
450 }
451
452 /**
453 * rrm_process_neighbor_report_req() - Create a Neighbor report request
454 * and send it to peer.
455 * @mac: pointer to mac context
456 * @pNeighborReq: Neighbor report request params
457 *
458 * Return: None
459 */
460 QDF_STATUS
rrm_process_neighbor_report_req(struct mac_context * mac,tpSirNeighborReportReqInd pNeighborReq)461 rrm_process_neighbor_report_req(struct mac_context *mac,
462 tpSirNeighborReportReqInd pNeighborReq)
463 {
464 QDF_STATUS status = QDF_STATUS_SUCCESS;
465 tSirMacNeighborReportReq NeighborReportReq;
466 struct pe_session *pe_session;
467 uint8_t sessionId;
468
469 if (!pNeighborReq) {
470 pe_err("NeighborReq is NULL");
471 return QDF_STATUS_E_FAILURE;
472 }
473 pe_session = pe_find_session_by_bssid(mac, pNeighborReq->bssId,
474 &sessionId);
475 if (!pe_session) {
476 pe_err("session does not exist for given bssId");
477 return QDF_STATUS_E_FAILURE;
478 }
479
480 pe_debug("SSID present: %d", pNeighborReq->noSSID);
481
482 qdf_mem_zero(&NeighborReportReq, sizeof(tSirMacNeighborReportReq));
483
484 NeighborReportReq.dialogToken = ++mac->rrm.rrmPEContext.DialogToken;
485 NeighborReportReq.ssid_present = !pNeighborReq->noSSID;
486 if (NeighborReportReq.ssid_present) {
487 qdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID,
488 sizeof(tSirMacSSid));
489 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
490 QDF_TRACE_LEVEL_DEBUG,
491 (uint8_t *) NeighborReportReq.ssid.ssId,
492 NeighborReportReq.ssid.length);
493 }
494
495 status =
496 lim_send_neighbor_report_request_frame(mac, &NeighborReportReq,
497 pNeighborReq->bssId,
498 pe_session);
499
500 return status;
501 }
502
rrm_get_country_code_from_connected_profile(struct mac_context * mac,uint8_t vdev_id,uint8_t * country_code)503 void rrm_get_country_code_from_connected_profile(struct mac_context *mac,
504 uint8_t vdev_id,
505 uint8_t *country_code)
506 {
507 QDF_STATUS status;
508
509 status = wlan_cm_get_country_code(mac->pdev, vdev_id, country_code);
510
511 pe_debug("Country info from bcn:%c%c 0x%x", country_code[0],
512 country_code[1], country_code[2]);
513
514 if (QDF_IS_STATUS_ERROR(status))
515 qdf_mem_zero(country_code, REG_ALPHA2_LEN + 1);
516
517 if (!country_code[0]) {
518 wlan_reg_read_current_country(mac->psoc, country_code);
519 country_code[2] = OP_CLASS_GLOBAL;
520 pe_debug("Current country info %c%c 0x%x", country_code[0],
521 country_code[1], country_code[2]);
522 }
523 }
524
525 #ifdef CONNECTIVITY_DIAG_EVENT
526 /**
527 * wlan_diag_log_beacon_rpt_req_event() - Send Beacon Report Request logging
528 * event.
529 * @token: Dialog token
530 * @mode: Measurement mode
531 * @op_class: operating class
532 * @chan: channel number
533 * @req_mode: Request mode
534 * @duration: The duration over which the Beacon report was measured
535 * @pe_session: pe session pointer
536 */
537 static void
wlan_diag_log_beacon_rpt_req_event(uint8_t token,uint8_t mode,uint8_t op_class,uint8_t chan,uint8_t req_mode,uint32_t duration,struct pe_session * pe_session)538 wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
539 uint8_t op_class, uint8_t chan,
540 uint8_t req_mode, uint32_t duration,
541 struct pe_session *pe_session)
542 {
543 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt);
544
545 qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
546
547 wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(pe_session->vdev);
548 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
549 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
550
551 wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_REQ_EVENT;
552 wlan_diag_event.version = DIAG_BCN_RPT_VERSION_2;
553
554 if (mlo_is_mld_sta(pe_session->vdev))
555 wlan_diag_event.band =
556 wlan_convert_freq_to_diag_band(pe_session->curr_op_freq);
557
558 wlan_diag_event.meas_token = token;
559 wlan_diag_event.mode = mode;
560 wlan_diag_event.op_class = op_class;
561 wlan_diag_event.chan = chan;
562 wlan_diag_event.duration = duration;
563 wlan_diag_event.req_mode = req_mode;
564
565 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_BCN_RPT);
566 }
567 #else
568 static void
wlan_diag_log_beacon_rpt_req_event(uint8_t token,uint8_t mode,uint8_t op_class,uint8_t chan,uint8_t req_mode,uint32_t duration,struct pe_session * pe_session)569 wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
570 uint8_t op_class, uint8_t chan,
571 uint8_t req_mode, uint32_t duration,
572 struct pe_session *pe_session)
573 {
574 }
575 #endif
576
577 #define ABS(x) ((x < 0) ? -x : x)
578
579 #ifdef WLAN_SUPPORT_INFRA_CTRL_PATH_STATS
580 /**
581 * rrm_update_mac_cp_stats: update stats of rrm structure of mac
582 * @ev: cp stats event
583 * @mac_ctx: mac context
584 *
585 * Return: None
586 */
587 static inline void
rrm_update_mac_cp_stats(struct infra_cp_stats_event * ev,struct mac_context * mac_ctx)588 rrm_update_mac_cp_stats(struct infra_cp_stats_event *ev,
589 struct mac_context *mac_ctx)
590 {
591 tpSirMacRadioMeasureReport rrm_report;
592 struct counter_stats *counter_stats;
593 struct group_id_0 ev_counter_stats;
594 struct mac_stats *mac_stats;
595 struct group_id_1 ev_mac_stats;
596
597 rrm_report = &mac_ctx->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
598
599 counter_stats =
600 &rrm_report->report.statistics_report.group_stats.counter_stats;
601 mac_stats =
602 &rrm_report->report.statistics_report.group_stats.mac_stats;
603
604 ev_counter_stats = ev->sta_stats->group.counter_stats;
605 ev_mac_stats = ev->sta_stats->group.mac_stats;
606
607 switch (rrm_report->report.statistics_report.group_id) {
608 /*
609 * Assign count diff in mac rrm sta stats report.
610 * For first event callback stats will be same as
611 * send by FW because memset is done for mac rrm sta
612 * stats before sending rrm sta stats request to FW and
613 * for second request stats will be the diff of stats send
614 * by FW and previous stats.
615 */
616 case STA_STAT_GROUP_ID_COUNTER_STATS:
617 counter_stats->failed_count =
618 ev_counter_stats.failed_count -
619 counter_stats->failed_count;
620 counter_stats->group_received_frame_count =
621 ev_counter_stats.group_received_frame_count -
622 counter_stats->group_received_frame_count;
623 counter_stats->fcs_error_count =
624 ev_counter_stats.fcs_error_count -
625 counter_stats->fcs_error_count;
626 counter_stats->transmitted_frame_count =
627 ev_counter_stats.transmitted_frame_count -
628 counter_stats->transmitted_frame_count;
629 break;
630 case STA_STAT_GROUP_ID_MAC_STATS:
631 mac_stats->rts_success_count =
632 ev_mac_stats.rts_success_count -
633 mac_stats->rts_success_count;
634 mac_stats->rts_failure_count =
635 ev_mac_stats.rts_failure_count -
636 mac_stats->rts_failure_count;
637 mac_stats->ack_failure_count =
638 ev_mac_stats.ack_failure_count -
639 mac_stats->ack_failure_count;
640 break;
641 default:
642 pe_debug("group id not supported");
643 }
644 pe_nofl_debug("counter stats: group rx frame count %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",
645 counter_stats->group_received_frame_count,
646 counter_stats->failed_count,
647 counter_stats->fcs_error_count,
648 counter_stats->transmitted_frame_count,
649 mac_stats->rts_success_count,
650 mac_stats->rts_failure_count,
651 mac_stats->ack_failure_count);
652 }
653
654 /**
655 * rmm_sta_stats_response_cb: RRM sta stats response callback
656 * @ev: cp stats event
657 * @cookie: NULL
658 *
659 * Return: None
660 */
661 static inline
rmm_sta_stats_response_cb(struct infra_cp_stats_event * ev,void * cookie)662 void rmm_sta_stats_response_cb(struct infra_cp_stats_event *ev, void *cookie)
663 {
664 struct mac_context *mac;
665 struct pe_session *session;
666 uint8_t vdev_id, index;
667 QDF_STATUS status;
668 tpRRMReq pcurrent_req;
669 tSirMacRadioMeasureReport *rrm_report;
670
671 mac = cds_get_context(QDF_MODULE_ID_PE);
672 if (!mac)
673 return;
674 index = mac->rrm.rrmPEContext.rrm_sta_stats.index;
675
676 /* Deregister callback registered in request */
677 status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
678 if (QDF_IS_STATUS_ERROR(status))
679 pe_err("failed to deregister callback %d", status);
680
681 pcurrent_req = mac->rrm.rrmPEContext.pCurrentReq[index];
682 if (!pcurrent_req) {
683 pe_err("Current request is NULL");
684 qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
685 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
686 return;
687 }
688
689 vdev_id = mac->rrm.rrmPEContext.rrm_sta_stats.vdev_id;
690 session = pe_find_session_by_vdev_id(mac, vdev_id);
691 if (!session) {
692 pe_err("Session does not exist for given vdev id %d", vdev_id);
693 rrm_cleanup(mac, mac->rrm.rrmPEContext.rrm_sta_stats.index);
694 return;
695 }
696
697 rrm_report = &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
698 rrm_update_mac_cp_stats(ev, mac);
699
700 /* Update resp counter for every response to find second resp*/
701 mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count++;
702 /* Send current stats if meas duration is 0. */
703 if (mac->rrm.rrmPEContext.rrm_sta_stats.rrm_sta_stats_res_count ==
704 MAX_RMM_STA_STATS_REQUESTED ||
705 !rrm_report->report.statistics_report.meas_duration) {
706 lim_send_radio_measure_report_action_frame(
707 mac, pcurrent_req->dialog_token, 1, true,
708 &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report,
709 mac->rrm.rrmPEContext.rrm_sta_stats.peer, session);
710
711 rrm_cleanup(mac, index);
712 }
713 }
714
715 /**
716 * rrm_update_vdev_stats: Update RRM stats from DP
717 * @rrm_report: RRM Measurement Report
718 * @vdev_id: vdev_id
719 *
720 * Return: QDF STATUS
721 */
722 static QDF_STATUS
rrm_update_vdev_stats(tpSirMacRadioMeasureReport rrm_report,uint8_t vdev_id)723 rrm_update_vdev_stats(tpSirMacRadioMeasureReport rrm_report, uint8_t vdev_id)
724 {
725 struct cdp_vdev_stats *stats;
726 QDF_STATUS status;
727 struct counter_stats *counter_stats;
728 struct mac_stats *mac_stats;
729
730 counter_stats =
731 &rrm_report->report.statistics_report.group_stats.counter_stats;
732 mac_stats =
733 &rrm_report->report.statistics_report.group_stats.mac_stats;
734
735 stats = qdf_mem_malloc(sizeof(*stats));
736 if (!stats)
737 return QDF_STATUS_E_NOMEM;
738
739 status =
740 cdp_host_get_vdev_stats(cds_get_context(QDF_MODULE_ID_SOC),
741 vdev_id, stats, true);
742 if (QDF_IS_STATUS_ERROR(status)) {
743 pe_err("Failed to get stats %d", status);
744 qdf_mem_free(stats);
745 return QDF_STATUS_E_FAILURE;
746 }
747
748 pe_nofl_debug("counter stats count: fragment (tx: %d rx: %d) group tx: %llu mac stats count: retry : %d multiple retry: %d frame duplicate %d",
749 stats->tx.fragment_count, stats->rx.fragment_count,
750 stats->tx.mcast.num, stats->tx.retry_count,
751 stats->tx.multiple_retry_count,
752 stats->rx.duplicate_count);
753
754 switch (rrm_report->report.statistics_report.group_id) {
755 case STA_STAT_GROUP_ID_COUNTER_STATS:
756 counter_stats->transmitted_fragment_count =
757 stats->tx.fragment_count -
758 counter_stats->transmitted_fragment_count;
759 counter_stats->received_fragment_count =
760 stats->rx.fragment_count -
761 counter_stats->received_fragment_count;
762 counter_stats->group_transmitted_frame_count =
763 stats->tx.mcast.num -
764 counter_stats->group_transmitted_frame_count;
765 break;
766 case STA_STAT_GROUP_ID_MAC_STATS:
767 mac_stats->retry_count =
768 stats->tx.retry_count - mac_stats->retry_count;
769 mac_stats->multiple_retry_count =
770 stats->tx.multiple_retry_count -
771 mac_stats->multiple_retry_count;
772 mac_stats->frame_duplicate_count =
773 stats->rx.duplicate_count -
774 mac_stats->frame_duplicate_count;
775 break;
776 }
777 qdf_mem_free(stats);
778
779 return QDF_STATUS_SUCCESS;
780 }
781
782 QDF_STATUS
rrm_send_sta_stats_req(struct mac_context * mac,struct pe_session * session,tSirMacAddr peer_mac)783 rrm_send_sta_stats_req(struct mac_context *mac,
784 struct pe_session *session,
785 tSirMacAddr peer_mac)
786 {
787 struct infra_cp_stats_cmd_info info = {0};
788 get_infra_cp_stats_cb resp_cb = NULL;
789 void *context;
790 QDF_STATUS status;
791 tpSirMacRadioMeasureReport report;
792
793 status = wlan_cp_stats_infra_cp_get_context(mac->psoc, &resp_cb,
794 &context);
795 if (resp_cb) {
796 pe_err("another request already in progress");
797 return QDF_STATUS_E_FAILURE;
798 }
799
800 info.request_cookie = NULL;
801 info.stats_id = TYPE_REQ_CTRL_PATH_RRM_STA_STAT;
802 info.action = ACTION_REQ_CTRL_PATH_STAT_GET;
803 info.infra_cp_stats_resp_cb = rmm_sta_stats_response_cb;
804 info.num_pdev_ids = 0;
805 info.num_vdev_ids = MAX_CTRL_STAT_VDEV_ENTRIES;
806 info.vdev_id[0] = wlan_vdev_get_id(session->vdev);
807 info.num_mac_addr_list = MAX_CTRL_STAT_MAC_ADDR_ENTRIES;
808 info.num_pdev_ids = 0;
809 /*
810 * FW doesn't send vdev id in response path.
811 * So, vdev id will be used to get session
812 * in callback.
813 */
814 mac->rrm.rrmPEContext.rrm_sta_stats.vdev_id =
815 wlan_vdev_get_id(session->vdev);
816 qdf_mem_copy(&info.peer_mac_addr[0], peer_mac, QDF_MAC_ADDR_SIZE);
817 report = &mac->rrm.rrmPEContext.rrm_sta_stats.rrm_report;
818
819 status = rrm_update_vdev_stats(report, wlan_vdev_get_id(session->vdev));
820 if (QDF_IS_STATUS_ERROR(status)) {
821 pe_err("Failed to register resp callback: %d", status);
822 return status;
823 }
824
825 status = wlan_cp_stats_infra_cp_register_resp_cb(mac->psoc, &info);
826 if (QDF_IS_STATUS_ERROR(status)) {
827 pe_err("Failed to register resp callback: %d", status);
828 return status;
829 }
830
831 status = wlan_cp_stats_send_infra_cp_req(mac->psoc, &info);
832 if (QDF_IS_STATUS_ERROR(status)) {
833 pe_err("Failed to send stats request status: %d", status);
834 goto get_stats_fail;
835 }
836
837 return QDF_STATUS_SUCCESS;
838
839 get_stats_fail:
840 status = wlan_cp_stats_infra_cp_deregister_resp_cb(mac->psoc);
841 if (QDF_IS_STATUS_ERROR(status))
842 pe_err("failed to deregister callback %d", status);
843 return status;
844 }
845 #endif
846
847 /* -------------------------------------------------------------------- */
848 /**
849 * rrm_get_max_meas_duration() - calculate max measurement duration for a
850 * rrm req
851 * @mac: global mac context
852 * @pe_session: per vdev pe context
853 *
854 * Return: max measurement duration
855 */
rrm_get_max_meas_duration(struct mac_context * mac,struct pe_session * pe_session)856 static uint16_t rrm_get_max_meas_duration(struct mac_context *mac,
857 struct pe_session *pe_session)
858 {
859 int8_t max_dur;
860 uint16_t max_meas_dur, sign;
861
862 /*
863 * The logic here is to check the measurement duration passed in the
864 * beacon request. Following are the cases handled.
865 * Case 1: If measurement duration received in the beacon request is
866 * greater than the max measurement duration advertised in the RRM
867 * capabilities(Assoc Req), and Duration Mandatory bit is set to 1,
868 * REFUSE the beacon request.
869 * Case 2: If measurement duration received in the beacon request is
870 * greater than the max measurement duration advertised in the RRM
871 * capabilities(Assoc Req), and Duration Mandatory bit is set to 0,
872 * perform measurement for the duration advertised in the
873 * RRM capabilities
874 * maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
875 */
876 max_dur = mac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
877 sign = (max_dur < 0) ? 1 : 0;
878 max_dur = (1L << ABS(max_dur));
879 if (!sign)
880 max_meas_dur =
881 max_dur * pe_session->beaconParams.beaconInterval;
882 else
883 max_meas_dur =
884 pe_session->beaconParams.beaconInterval / max_dur;
885
886 return max_meas_dur;
887 }
888
889 /**
890 * rrm_process_sta_stats_report_req: Process RRM sta stats request
891 * @mac: mac context
892 * @pCurrentReq: Current RRM request
893 * @sta_stats_req: RRM Measurement Request
894 * @pe_session: pe session
895 *
896 * Return: rrm status
897 */
898 static tRrmRetStatus
rrm_process_sta_stats_report_req(struct mac_context * mac,tpRRMReq pCurrentReq,tDot11fIEMeasurementRequest * sta_stats_req,struct pe_session * pe_session)899 rrm_process_sta_stats_report_req(struct mac_context *mac,
900 tpRRMReq pCurrentReq,
901 tDot11fIEMeasurementRequest *sta_stats_req,
902 struct pe_session *pe_session)
903 {
904 QDF_STATUS status;
905 uint16_t meas_duration = MIN_MEAS_DURATION_FOR_STA_STATS;
906 uint8_t max_meas_duration;
907 struct rrm_sta_stats *rrm_sta_statistics;
908
909 max_meas_duration = rrm_get_max_meas_duration(mac, pe_session);
910
911 /*
912 * Keep timer value atleast of 10 ms even if measurement duration
913 * provided in meas request is < 10 ms because FW takes some time to
914 * calculate and respond stats.
915 * Start timer of 10 ms even if meas duration is 0.
916 * To get stats from FW.
917 */
918 if (sta_stats_req->measurement_request.sta_stats.meas_duration >
919 MIN_MEAS_DURATION_FOR_STA_STATS)
920 meas_duration =
921 sta_stats_req->measurement_request.sta_stats.meas_duration;
922
923 if (meas_duration > max_meas_duration) {
924 if (sta_stats_req->durationMandatory) {
925 pe_nofl_err("Dropping the req: duration mandatory & max duration > meas duration");
926 return eRRM_REFUSED;
927 }
928 meas_duration = max_meas_duration;
929 }
930 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)
931 sta_stats_req->measurement_request.sta_stats.peer_mac_addr)) {
932 pe_err("Dropping req: broadcast address not supported");
933 return eRRM_INCAPABLE;
934 }
935
936 rrm_sta_statistics = &mac->rrm.rrmPEContext.rrm_sta_stats;
937
938 rrm_sta_statistics->rrm_report.token = pCurrentReq->token;
939 rrm_sta_statistics->rrm_report.type = pCurrentReq->type;
940 rrm_sta_statistics->rrm_report.refused = 0;
941 rrm_sta_statistics->rrm_report.incapable = 0;
942 rrm_sta_statistics->rrm_report.report.statistics_report.group_id =
943 sta_stats_req->measurement_request.sta_stats.group_identity;
944 rrm_sta_statistics->rrm_report.report.statistics_report.meas_duration
945 = sta_stats_req->measurement_request.sta_stats.meas_duration;
946
947 switch (sta_stats_req->measurement_request.sta_stats.group_identity) {
948 case STA_STAT_GROUP_ID_COUNTER_STATS:
949 case STA_STAT_GROUP_ID_MAC_STATS:
950 status =
951 rrm_send_sta_stats_req(
952 mac, pe_session,
953 sta_stats_req->measurement_request.sta_stats.peer_mac_addr);
954 if (!QDF_IS_STATUS_SUCCESS(status))
955 return eRRM_REFUSED;
956 mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId =
957 pe_session->peSessionId;
958 tx_timer_change(&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
959 SYS_MS_TO_TICKS(meas_duration), 0);
960 /* Activate sta stats resp timer */
961 if (tx_timer_activate(
962 &mac->lim.lim_timers.rrm_sta_stats_resp_timer) !=
963 TX_SUCCESS) {
964 pe_err("failed to start sta stats timer");
965 return eRRM_REFUSED;
966 }
967 break;
968 case STA_STAT_GROUP_ID_DELAY_STATS:
969 /* TODO: update access delay from scan IE */
970 default:
971 pe_nofl_err("group id %d not supported",
972 sta_stats_req->measurement_request.sta_stats.group_identity);
973 return eRRM_INCAPABLE;
974 }
975 return eRRM_SUCCESS;
976 }
977
978 void
rrm_process_rrm_sta_stats_request_failure(struct mac_context * mac,struct pe_session * pe_session,tSirMacAddr peer,tRrmRetStatus status,uint8_t index)979 rrm_process_rrm_sta_stats_request_failure(struct mac_context *mac,
980 struct pe_session *pe_session,
981 tSirMacAddr peer,
982 tRrmRetStatus status, uint8_t index)
983 {
984 tpSirMacRadioMeasureReport p_report = NULL;
985 tpRRMReq p_current_req = mac->rrm.rrmPEContext.pCurrentReq[index];
986
987 if (!p_current_req) {
988 pe_err("Current request is NULL");
989 return;
990 }
991
992 p_report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
993 if (!p_report)
994 return;
995 p_report->token = p_current_req->token;
996 p_report->type = SIR_MAC_RRM_STA_STATISTICS_TYPE;
997
998 pe_debug("Measurement index:%d status %d token %d", index, status,
999 p_report->token);
1000
1001 switch (status) {
1002 case eRRM_FAILURE: /* fallthrough */
1003 case eRRM_REFUSED:
1004 p_report->refused = 1;
1005 break;
1006 case eRRM_INCAPABLE:
1007 p_report->incapable = 1;
1008 break;
1009 default:
1010 pe_err("Invalid RRM status, failed to send report");
1011 qdf_mem_free(p_report);
1012 return;
1013 }
1014
1015 lim_send_radio_measure_report_action_frame(mac,
1016 p_current_req->dialog_token,
1017 1, true,
1018 p_report, peer,
1019 pe_session);
1020
1021 qdf_mem_free(p_report);
1022 }
1023
1024 /**
1025 * rrm_check_other_sta_sats_req_in_progress: To check if any other sta stats req
1026 * in progress
1027 * @rrm_req: measurement request
1028 *
1029 * To avoid any conflict between multiple sta stats request at time of callback
1030 * response from FW handle one sta stats request at a time.
1031 *
1032 * Return: true/false
1033 */
1034 static bool
rrm_check_other_sta_sats_req_in_progress(tDot11fRadioMeasurementRequest * rrm_req)1035 rrm_check_other_sta_sats_req_in_progress(
1036 tDot11fRadioMeasurementRequest *rrm_req)
1037 {
1038 uint8_t count = 0, i = 0;
1039
1040 for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
1041 if (rrm_req->MeasurementRequest[i].measurement_type ==
1042 SIR_MAC_RRM_STA_STATISTICS_TYPE)
1043 count++;
1044 if (count > 1)
1045 return true;
1046 }
1047 return false;
1048 }
1049
1050 /**
1051 * rrm_process_sta_stats_req: Process RRM sta stats request
1052 * @mac: mac context
1053 * @peer: peer mac
1054 * @session_entry: pe session
1055 * @radiomes_report: measurement report
1056 * @rrm_req: measurement request
1057 * @num_report: no of reports
1058 * @index: index of request
1059 *
1060 * Return: QDF_STATUS
1061 */
1062 static
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)1063 QDF_STATUS rrm_process_sta_stats_req(
1064 struct mac_context *mac, tSirMacAddr peer,
1065 struct pe_session *session_entry,
1066 tpSirMacRadioMeasureReport *radiomes_report,
1067 tDot11fRadioMeasurementRequest *rrm_req,
1068 uint8_t *num_report, int index)
1069 {
1070 tRrmRetStatus rrm_status = eRRM_SUCCESS;
1071 tpRRMReq curr_req;
1072 QDF_STATUS status = QDF_STATUS_SUCCESS;
1073
1074 if (index >= MAX_MEASUREMENT_REQUEST) {
1075 status = rrm_reject_req(radiomes_report,
1076 rrm_req, num_report, index,
1077 rrm_req->MeasurementRequest[0].
1078 measurement_type);
1079 return status;
1080 }
1081
1082 if (rrm_check_other_sta_sats_req_in_progress(rrm_req)) {
1083 pe_debug("another sta stats request already in progress");
1084 return QDF_STATUS_E_FAILURE;
1085 }
1086
1087 curr_req = qdf_mem_malloc(sizeof(*curr_req));
1088 if (!curr_req) {
1089 mac->rrm.rrmPEContext.pCurrentReq[index] = NULL;
1090 qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
1091 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
1092 return QDF_STATUS_E_NOMEM;
1093 }
1094
1095 curr_req->dialog_token = rrm_req->DialogToken.token;
1096 curr_req->token =
1097 rrm_req->MeasurementRequest[index].measurement_token;
1098 curr_req->measurement_idx = index;
1099 curr_req->type = rrm_req->MeasurementRequest[index].measurement_type;
1100
1101
1102 qdf_mem_set(&mac->rrm.rrmPEContext.rrm_sta_stats,
1103 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats), 0);
1104
1105 mac->rrm.rrmPEContext.rrm_sta_stats.index = index;
1106 mac->rrm.rrmPEContext.pCurrentReq[index] = curr_req;
1107 mac->rrm.rrmPEContext.num_active_request++;
1108 qdf_mem_copy(mac->rrm.rrmPEContext.rrm_sta_stats.peer,
1109 peer,
1110 QDF_MAC_ADDR_SIZE);
1111
1112 pe_debug("Processing sta stats Report req %d num_active_req:%d",
1113 index, mac->rrm.rrmPEContext.num_active_request);
1114
1115 rrm_status = rrm_process_sta_stats_report_req(mac, curr_req,
1116 &rrm_req->MeasurementRequest[index], session_entry);
1117 if (eRRM_SUCCESS != rrm_status)
1118 goto failure;
1119
1120 return QDF_STATUS_SUCCESS;
1121 failure:
1122 rrm_process_rrm_sta_stats_request_failure(
1123 mac, session_entry, peer, rrm_status, index);
1124
1125 rrm_cleanup(mac, index);
1126 return QDF_STATUS_E_FAILURE;
1127 }
1128
1129 /**
1130 * rrm_process_beacon_report_req() - Processes the Beacon report request
1131 * from the peer AP
1132 * @mac: pointer to mac context
1133 * @pCurrentReq: pointer to the current Req comtext
1134 * @pBeaconReq: pointer to the beacon report request IE from the peer
1135 * @pe_session: session entry
1136 *
1137 * Return: None
1138 */
1139 static tRrmRetStatus
rrm_process_beacon_report_req(struct mac_context * mac,tpRRMReq pCurrentReq,tDot11fIEMeasurementRequest * pBeaconReq,struct pe_session * pe_session)1140 rrm_process_beacon_report_req(struct mac_context *mac,
1141 tpRRMReq pCurrentReq,
1142 tDot11fIEMeasurementRequest *pBeaconReq,
1143 struct pe_session *pe_session)
1144 {
1145 struct scheduler_msg mmh_msg = {0};
1146 tpSirBeaconReportReqInd psbrr;
1147 uint8_t num_rpt, idx_rpt;
1148 uint16_t measDuration, maxMeasduration;
1149 tDot11fIEAPChannelReport *ie_ap_chan_rpt;
1150 uint8_t tmp_idx, buf_left, buf_cons;
1151 uint16_t ch_ctr = 0;
1152 char ch_buf[RRM_CH_BUF_LEN];
1153 char *tmp_buf = NULL;
1154 uint8_t country[WNI_CFG_COUNTRY_CODE_LEN];
1155 uint8_t req_mode;
1156 uint8_t i;
1157
1158 if (!pe_session) {
1159 pe_err("pe_session is NULL");
1160 return eRRM_INCAPABLE;
1161 }
1162
1163 if (wlan_policy_mgr_get_ll_lt_sap_vdev_id(mac->psoc) != WLAN_INVALID_VDEV_ID) {
1164 pe_debug("RX: [802.11 BCN_RPT] reject req as ll_lt_sap is present");
1165 return eRRM_REFUSED;
1166 }
1167
1168 if (pBeaconReq->measurement_request.Beacon.rrm_reporting.present &&
1169 (pBeaconReq->measurement_request.Beacon.rrm_reporting.reporting_condition != 0)) {
1170 /* Repeated measurement is not supported. This means number of repetitions should be zero.(Already checked) */
1171 /* All test case in VoWifi(as of version 0.36) use zero for number of repetitions. */
1172 /* Beacon reporting should not be included in request if number of repetitons is zero. */
1173 /* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */
1174
1175 pe_nofl_err("RX: [802.11 BCN_RPT] Dropping req: Reporting condition included is not zero");
1176 return eRRM_INCAPABLE;
1177 }
1178
1179 maxMeasduration = rrm_get_max_meas_duration(mac, pe_session);
1180 if( pBeaconReq->measurement_request.Beacon.meas_mode ==
1181 eSIR_PASSIVE_SCAN)
1182 maxMeasduration += 10;
1183
1184 measDuration = pBeaconReq->measurement_request.Beacon.meas_duration;
1185
1186 pe_nofl_rl_info("RX: [802.11 BCN_RPT] seq:%d SSID:" QDF_SSID_FMT " BSSID:" QDF_MAC_ADDR_FMT " Token:%d op_class:%d ch:%d meas_mode:%d meas_duration:%d max_meas_dur: %d",
1187 mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
1188 QDF_SSID_REF(
1189 pBeaconReq->measurement_request.Beacon.SSID.num_ssid,
1190 pBeaconReq->measurement_request.Beacon.SSID.ssid),
1191 QDF_MAC_ADDR_REF(
1192 pBeaconReq->measurement_request.Beacon.BSSID),
1193 pBeaconReq->measurement_token,
1194 pBeaconReq->measurement_request.Beacon.regClass,
1195 pBeaconReq->measurement_request.Beacon.channel,
1196 pBeaconReq->measurement_request.Beacon.meas_mode,
1197 measDuration, maxMeasduration);
1198
1199 req_mode = (pBeaconReq->parallel << 0) | (pBeaconReq->enable << 1) |
1200 (pBeaconReq->request << 2) | (pBeaconReq->report << 3) |
1201 (pBeaconReq->durationMandatory << 4);
1202
1203 wlan_diag_log_beacon_rpt_req_event(pBeaconReq->measurement_token,
1204 pBeaconReq->measurement_request.Beacon.meas_mode,
1205 pBeaconReq->measurement_request.Beacon.regClass,
1206 pBeaconReq->measurement_request.Beacon.channel,
1207 req_mode, measDuration, pe_session);
1208
1209 if (measDuration == 0 &&
1210 pBeaconReq->measurement_request.Beacon.meas_mode !=
1211 eSIR_BEACON_TABLE) {
1212 pe_nofl_err("RX: [802.11 BCN_RPT] Invalid measurement duration");
1213 return eRRM_REFUSED;
1214 }
1215
1216 if (maxMeasduration < measDuration) {
1217 if (pBeaconReq->durationMandatory) {
1218 pe_nofl_err("RX: [802.11 BCN_RPT] Dropping the req: duration mandatory & maxduration > measduration");
1219 return eRRM_REFUSED;
1220 }
1221 measDuration = maxMeasduration;
1222 }
1223
1224 pe_debug("measurement duration %d", measDuration);
1225
1226 /* Cache the data required for sending report. */
1227 pCurrentReq->request.Beacon.reportingDetail =
1228 pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
1229 present ? pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
1230 reportingDetail : BEACON_REPORTING_DETAIL_ALL_FF_IE;
1231
1232 if (pBeaconReq->measurement_request.Beacon.
1233 last_beacon_report_indication.present) {
1234 pCurrentReq->request.Beacon.last_beacon_report_indication =
1235 pBeaconReq->measurement_request.Beacon.
1236 last_beacon_report_indication.last_fragment;
1237 pe_debug("RX: [802.11 BCN_RPT] Last Bcn Report in the req: %d",
1238 pCurrentReq->request.Beacon.last_beacon_report_indication);
1239 } else {
1240 pCurrentReq->request.Beacon.last_beacon_report_indication = 0;
1241 pe_debug("RX: [802.11 BCN_RPT] Last Bcn rpt ind not present");
1242 }
1243
1244 if (pBeaconReq->measurement_request.Beacon.RequestedInfo.present) {
1245 if (!pBeaconReq->measurement_request.Beacon.RequestedInfo.
1246 num_requested_eids) {
1247 pe_debug("RX: [802.11 BCN_RPT]: Requested num of EID is 0");
1248 return eRRM_FAILURE;
1249 }
1250 pCurrentReq->request.Beacon.reqIes.pElementIds =
1251 qdf_mem_malloc(sizeof(uint8_t) *
1252 pBeaconReq->measurement_request.Beacon.
1253 RequestedInfo.num_requested_eids);
1254 if (!pCurrentReq->request.Beacon.reqIes.pElementIds)
1255 return eRRM_FAILURE;
1256
1257 pCurrentReq->request.Beacon.reqIes.num =
1258 pBeaconReq->measurement_request.Beacon.RequestedInfo.
1259 num_requested_eids;
1260 qdf_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds,
1261 pBeaconReq->measurement_request.Beacon.
1262 RequestedInfo.requested_eids,
1263 pCurrentReq->request.Beacon.reqIes.num);
1264 for (i = 0; i < pCurrentReq->request.Beacon.reqIes.num; i++)
1265 pe_debug("RX: [802.11 BCN_RPT]:Requested EID is %d",
1266 pBeaconReq->measurement_request.Beacon.RequestedInfo.requested_eids[i]);
1267 }
1268
1269 if (pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.present) {
1270 if (!pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.num_req_element_id_ext) {
1271 pe_err("RX: [802.11 BCN_RPT]: Requested num of Extn EID is 0");
1272 return eRRM_FAILURE;
1273 }
1274 if (pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id !=
1275 WLAN_ELEMID_EXTN_ELEM) {
1276 pe_err("RX: [802.11 BCN_RPT]: Extn Element ID is not 0xFF");
1277 return eRRM_FAILURE;
1278 }
1279
1280 pCurrentReq->request.Beacon.reqIes.ext_info.eid =
1281 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id;
1282 pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext =
1283 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.num_req_element_id_ext;
1284 qdf_mem_copy(pCurrentReq->request.Beacon.reqIes.ext_info.eid_ext,
1285 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id_ext,
1286 pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext);
1287 pe_debug("RX: [802.11 BCN_RPT]: EID is %d",
1288 pCurrentReq->request.Beacon.reqIes.ext_info.eid);
1289 pe_debug("RX: [802.11 BCN_RPT]:Num of Extn EID is %d",
1290 pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext);
1291 for (i = 0; i < pCurrentReq->request.Beacon.reqIes.ext_info.num_eid_ext; i++)
1292 pe_debug("RX: [802.11 BCN_RPT]:Requested Extn EID is %d",
1293 pBeaconReq->measurement_request.Beacon.ExtRequestedInfo.req_element_id_ext[i]);
1294 }
1295
1296 /* Prepare the request to send to SME. */
1297 psbrr = qdf_mem_malloc(sizeof(tSirBeaconReportReqInd));
1298 if (!psbrr)
1299 return eRRM_FAILURE;
1300
1301 /* Alloc memory for pSmeBcnReportReq, will be freed by other modules */
1302 qdf_mem_copy(psbrr->bssId, pe_session->bssId,
1303 sizeof(tSirMacAddr));
1304 psbrr->messageType = eWNI_SME_BEACON_REPORT_REQ_IND;
1305 psbrr->length = sizeof(tSirBeaconReportReqInd);
1306 psbrr->uDialogToken = pBeaconReq->measurement_token;
1307 psbrr->msgSource = eRRM_MSG_SOURCE_11K;
1308 psbrr->randomizationInterval =
1309 SYS_TU_TO_MS(pBeaconReq->measurement_request.Beacon.randomization);
1310 psbrr->measurement_idx = pCurrentReq->measurement_idx;
1311
1312 if (!wlan_reg_is_6ghz_supported(mac->psoc) &&
1313 (wlan_reg_is_6ghz_op_class(mac->pdev,
1314 pBeaconReq->measurement_request.Beacon.regClass))) {
1315 pe_nofl_err("RX: [802.11 BCN_RPT] Ch belongs to 6 ghz spectrum, abort");
1316 qdf_mem_free(psbrr);
1317 return eRRM_FAILURE;
1318 }
1319
1320 rrm_get_country_code_from_connected_profile(mac, pe_session->vdev_id,
1321 country);
1322 psbrr->channel_info.chan_num =
1323 pBeaconReq->measurement_request.Beacon.channel;
1324 psbrr->channel_info.reg_class =
1325 pBeaconReq->measurement_request.Beacon.regClass;
1326 if (psbrr->channel_info.chan_num &&
1327 psbrr->channel_info.chan_num != 255) {
1328 psbrr->channel_info.chan_freq =
1329 wlan_reg_country_chan_opclass_to_freq(
1330 mac->pdev,
1331 country,
1332 psbrr->channel_info.chan_num,
1333 psbrr->channel_info.reg_class,
1334 false);
1335 if (!psbrr->channel_info.chan_freq) {
1336 pe_debug("invalid ch freq, chan_num %d",
1337 psbrr->channel_info.chan_num);
1338 qdf_mem_free(psbrr);
1339 return eRRM_FAILURE;
1340 }
1341 } else {
1342 psbrr->channel_info.chan_freq = 0;
1343 }
1344 sme_debug("opclass %d, ch %d freq %d AP's country code %c%c 0x%x index:%d",
1345 psbrr->channel_info.reg_class,
1346 psbrr->channel_info.chan_num,
1347 psbrr->channel_info.chan_freq,
1348 country[0], country[1], country[2],
1349 psbrr->measurement_idx);
1350
1351 psbrr->measurementDuration[0] = measDuration;
1352 psbrr->fMeasurementtype[0] =
1353 pBeaconReq->measurement_request.Beacon.meas_mode;
1354 qdf_mem_copy(psbrr->macaddrBssid,
1355 pBeaconReq->measurement_request.Beacon.BSSID,
1356 sizeof(tSirMacAddr));
1357
1358 if (pBeaconReq->measurement_request.Beacon.SSID.present) {
1359 psbrr->ssId.length =
1360 pBeaconReq->measurement_request.Beacon.SSID.num_ssid;
1361 qdf_mem_copy(psbrr->ssId.ssId,
1362 pBeaconReq->measurement_request.Beacon.SSID.ssid,
1363 psbrr->ssId.length);
1364 }
1365
1366 pCurrentReq->token = pBeaconReq->measurement_token;
1367
1368 num_rpt = pBeaconReq->measurement_request.Beacon.num_APChannelReport;
1369 for (idx_rpt = 0; idx_rpt < num_rpt; idx_rpt++) {
1370 ie_ap_chan_rpt =
1371 &pBeaconReq->measurement_request.Beacon.APChannelReport[idx_rpt];
1372 for (tmp_idx = 0;
1373 tmp_idx < ie_ap_chan_rpt->num_channelList;
1374 tmp_idx++) {
1375 if (!wlan_reg_is_6ghz_supported(mac->psoc) &&
1376 (wlan_reg_is_6ghz_op_class(mac->pdev,
1377 ie_ap_chan_rpt->regulatoryClass))) {
1378 pe_nofl_err("RX: [802.11 BCN_RPT] Ch belongs to 6 ghz spectrum, abort");
1379 qdf_mem_free(psbrr);
1380 return eRRM_FAILURE;
1381 }
1382
1383 psbrr->channel_list.chan_freq_lst[ch_ctr++] =
1384 wlan_reg_country_chan_opclass_to_freq(
1385 mac->pdev, country,
1386 ie_ap_chan_rpt->channelList[tmp_idx],
1387 ie_ap_chan_rpt->regulatoryClass, true);
1388
1389 if (ch_ctr >= QDF_ARRAY_SIZE(psbrr->channel_list.chan_freq_lst))
1390 break;
1391 }
1392 if (ch_ctr >= QDF_ARRAY_SIZE(psbrr->channel_list.chan_freq_lst))
1393 break;
1394 }
1395
1396 psbrr->channel_list.num_channels = ch_ctr;
1397 buf_left = sizeof(ch_buf);
1398 tmp_buf = ch_buf;
1399 for (idx_rpt = 0; idx_rpt < ch_ctr; idx_rpt++) {
1400 buf_cons = qdf_snprint(tmp_buf, buf_left, "%d ",
1401 psbrr->channel_list.chan_freq_lst[idx_rpt]);
1402 buf_left -= buf_cons;
1403 tmp_buf += buf_cons;
1404 }
1405
1406 if (ch_ctr)
1407 pe_nofl_info("RX: [802.11 BCN_RPT] Ch-list:%s", ch_buf);
1408
1409 /* Send request to SME. */
1410 mmh_msg.type = eWNI_SME_BEACON_REPORT_REQ_IND;
1411 mmh_msg.bodyptr = psbrr;
1412 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
1413 pe_session->peSessionId, mmh_msg.type));
1414 lim_sys_process_mmh_msg_api(mac, &mmh_msg);
1415 return eRRM_SUCCESS;
1416 }
1417
1418 #ifdef WLAN_FEATURE_11BE_MLO
1419 static uint8_t *
rrm_check_ml_ie(uint8_t * ies,uint16_t len,uint8_t * mlie_copy_len)1420 rrm_check_ml_ie(uint8_t *ies, uint16_t len, uint8_t *mlie_copy_len)
1421 {
1422 uint8_t *ml_ie = NULL;
1423 qdf_size_t ml_ie_total_len = 0;
1424 uint8_t *mlie_copy = NULL;
1425 uint8_t ml_common_info_length = 0;
1426 uint8_t ml_bv_ie_len = 0;
1427
1428 util_find_mlie(ies, len, &ml_ie, &ml_ie_total_len);
1429 if (!ml_ie) {
1430 mlo_debug("[802.11 BCN_RPT]: Not ML AP total_len:%d", len);
1431 return NULL;
1432 }
1433
1434 mlo_debug("[802.11 BCN_RPT]: ML IE is present ml_ie_total_len:%zu",
1435 ml_ie_total_len);
1436
1437 util_get_mlie_common_info_len(ml_ie, ml_ie_total_len,
1438 &ml_common_info_length);
1439
1440 ml_bv_ie_len = sizeof(struct wlan_ie_multilink) + ml_common_info_length;
1441 if (ml_bv_ie_len) {
1442 mlie_copy = qdf_mem_malloc(ml_bv_ie_len);
1443 if (!mlie_copy) {
1444 mlo_err("malloc failed");
1445 goto end;
1446 }
1447 qdf_mem_copy(mlie_copy, ml_ie, ml_bv_ie_len);
1448 mlie_copy[TAG_LEN_POS] = ml_bv_ie_len - sizeof(struct ie_header);
1449 *mlie_copy_len = ml_bv_ie_len;
1450 }
1451
1452 end:
1453 return mlie_copy;
1454 }
1455
1456 static bool
rrm_copy_ml_ie(uint8_t eid,uint8_t extn_eid,uint8_t * ml_ie,uint16_t ml_len,uint8_t * pIes)1457 rrm_copy_ml_ie(uint8_t eid, uint8_t extn_eid,
1458 uint8_t *ml_ie, uint16_t ml_len, uint8_t *pIes)
1459 {
1460 if ((eid == WLAN_ELEMID_EXTN_ELEM || !eid) &&
1461 extn_eid == WLAN_EXTN_ELEMID_MULTI_LINK) {
1462 if (ml_ie && ml_len && pIes) {
1463 qdf_mem_copy(pIes, ml_ie, ml_len);
1464 return true;
1465 }
1466 }
1467
1468 return false;
1469 }
1470
1471 #else
1472 static inline uint8_t *
rrm_check_ml_ie(uint8_t * ies,uint16_t len,uint8_t * mlie_copy_len)1473 rrm_check_ml_ie(uint8_t *ies, uint16_t len, uint8_t *mlie_copy_len) {
1474 return NULL;
1475 }
1476
1477 static inline bool
rrm_copy_ml_ie(uint8_t eid,uint8_t extn_eid,uint8_t * ml_ie,uint16_t ml_len,uint8_t * pIes)1478 rrm_copy_ml_ie(uint8_t eid, uint8_t extn_eid, uint8_t *ml_ie,
1479 uint16_t ml_len, uint8_t *pIes) {
1480 return false;
1481 }
1482 #endif
1483 /**
1484 * rrm_fill_beacon_ies() - Fills fixed fields and Ies in bss description to an
1485 * array of uint8_t.
1486 * @mac: pointer to mac context
1487 * @pIes: pointer to the buffer that should be populated with ies.
1488 * @pNumIes: returns the num of ies filled in this param.
1489 * @pIesMaxSize: Max size of the buffer pIes.
1490 * @eids: pointer to array of eids. If NULL, all ies will be populated.
1491 * @numEids: number of elements in array eids.
1492 * @eid: EID
1493 * @extn_eids: pointer to array of ext eids
1494 * @extn_eids_count: count of elements in array extn_eids
1495 * @start_offset: Offset from where the IEs in the bss_desc should be parsed
1496 * @bss_desc: pointer to Bss Description.
1497 *
1498 * Return: Remaining length of IEs in current bss_desc which are not included
1499 * in pIes.
1500 */
1501 static uint16_t
rrm_fill_beacon_ies(struct mac_context * mac,uint8_t * pIes,uint8_t * pNumIes,uint8_t pIesMaxSize,uint8_t * eids,uint8_t numEids,uint8_t eid,uint8_t * extn_eids,uint8_t extn_eids_count,uint16_t start_offset,struct bss_description * bss_desc)1502 rrm_fill_beacon_ies(struct mac_context *mac, uint8_t *pIes,
1503 uint8_t *pNumIes, uint8_t pIesMaxSize, uint8_t *eids,
1504 uint8_t numEids, uint8_t eid, uint8_t *extn_eids,
1505 uint8_t extn_eids_count, uint16_t start_offset,
1506 struct bss_description *bss_desc)
1507 {
1508 uint8_t *pBcnIes, i;
1509 uint16_t BcnNumIes, total_ies_len, len;
1510 uint16_t rem_len = 0;
1511 uint8_t num_eids = 0;
1512 uint8_t ml_len = 0;
1513 uint8_t *ml_copy = NULL;
1514
1515 if ((!pIes) || (!pNumIes) || (!bss_desc)) {
1516 pe_err("Invalid parameters");
1517 return 0;
1518 }
1519 /* Make sure that if eid is null, numEids is set to zero. */
1520 num_eids = (!eids) ? 0 : numEids;
1521 num_eids += (!extn_eids) ? 0 : extn_eids_count;
1522 pe_err("extn_eids_count %d", extn_eids_count);
1523
1524 total_ies_len = GET_IE_LEN_IN_BSS(bss_desc->length);
1525 BcnNumIes = total_ies_len;
1526 if (start_offset > BcnNumIes) {
1527 pe_err("Invalid start offset %d Bcn IE len %d",
1528 start_offset, total_ies_len);
1529 return 0;
1530 }
1531
1532 pBcnIes = (uint8_t *)&bss_desc->ieFields[0];
1533 ml_copy = rrm_check_ml_ie(pBcnIes, total_ies_len, &ml_len);
1534 pBcnIes += start_offset;
1535 BcnNumIes = BcnNumIes - start_offset;
1536
1537 *pNumIes = 0;
1538
1539 /*
1540 * If start_offset is 0, this is the first fragment of the current
1541 * beacon. Include the Beacon Fixed Fields of length 12 bytes
1542 * (BEACON_FRAME_IES_OFFSET) in the first fragment.
1543 */
1544 if (start_offset == 0) {
1545 *((uint32_t *)pIes) = bss_desc->timeStamp[0];
1546 *pNumIes += sizeof(uint32_t);
1547 pIes += sizeof(uint32_t);
1548 *((uint32_t *)pIes) = bss_desc->timeStamp[1];
1549 *pNumIes += sizeof(uint32_t);
1550 pIes += sizeof(uint32_t);
1551 *((uint16_t *)pIes) = bss_desc->beaconInterval;
1552 *pNumIes += sizeof(uint16_t);
1553 pIes += sizeof(uint16_t);
1554 *((uint16_t *)pIes) = bss_desc->capabilityInfo;
1555 *pNumIes += sizeof(uint16_t);
1556 pIes += sizeof(uint16_t);
1557 }
1558
1559 while (BcnNumIes >= 2) {
1560 len = *(pBcnIes + 1);
1561 len += 2; /* element id + length. */
1562 pe_debug("EID = %d, len = %d total = %d",
1563 *pBcnIes, *(pBcnIes + 1), len);
1564 if (*pBcnIes == WLAN_ELEMID_EXTN_ELEM && *(pBcnIes + 2) > 0)
1565 pe_debug("Extended EID = %d", *(pBcnIes + 2));
1566
1567 if (BcnNumIes < len || len <= 2) {
1568 pe_err("RRM: Invalid IE len:%d exp_len:%d",
1569 len, BcnNumIes);
1570 break;
1571 }
1572
1573 i = 0;
1574 do {
1575 if (((!eids) || (*pBcnIes == eids[i])) ||
1576 ((*pBcnIes == eid) &&
1577 (extn_eids && *(pBcnIes + 2) == extn_eids[i]))) {
1578 if (((*pNumIes) + len) < pIesMaxSize) {
1579 qdf_mem_copy(pIes, pBcnIes, len);
1580 pIes += len;
1581 *pNumIes += len;
1582 } else {
1583 if (rrm_copy_ml_ie(*pBcnIes, *(pBcnIes + 2), ml_copy, ml_len, pIes)) {
1584 pIes += ml_len;
1585 *pNumIes += ml_len;
1586 start_offset = start_offset + len - ml_len;
1587 } else {
1588 /*
1589 * If max size of fragment is reached,
1590 * calculate the remaining length and
1591 * break. For first fragment, account
1592 * for the fixed fields also.
1593 */
1594 rem_len = total_ies_len - *pNumIes -
1595 start_offset;
1596 if (start_offset == 0)
1597 rem_len = rem_len +
1598 BEACON_FRAME_IES_OFFSET;
1599 pe_debug("rem_len %d ies added %d",
1600 rem_len, *pNumIes);
1601 }
1602 }
1603 break;
1604 }
1605 i++;
1606 } while (i < num_eids);
1607
1608 if (rem_len)
1609 break;
1610
1611 pBcnIes += len;
1612 BcnNumIes -= len;
1613 }
1614
1615 if (ml_copy)
1616 qdf_mem_free(ml_copy);
1617
1618 pe_debug("Total length of Ies added = %d rem_len %d",
1619 *pNumIes, rem_len);
1620
1621 return rem_len;
1622 }
1623
1624 /**
1625 * rrm_process_beacon_report_xmit() - create a rrm action frame
1626 * @mac_ctx: Global pointer to MAC context
1627 * @beacon_xmit_ind: Data for beacon report IE from SME.
1628 *
1629 * Create a Radio measurement report action frame and send it to peer.
1630 *
1631 * Return: QDF_STATUS
1632 */
1633 QDF_STATUS
rrm_process_beacon_report_xmit(struct mac_context * mac_ctx,tpSirBeaconReportXmitInd beacon_xmit_ind)1634 rrm_process_beacon_report_xmit(struct mac_context *mac_ctx,
1635 tpSirBeaconReportXmitInd beacon_xmit_ind)
1636 {
1637 QDF_STATUS status = QDF_STATUS_SUCCESS;
1638 tSirMacRadioMeasureReport *report = NULL;
1639 tSirMacBeaconReport *beacon_report;
1640 struct bss_description *bss_desc;
1641 tpRRMReq curr_req;
1642 struct pe_session *session_entry;
1643 uint8_t session_id, counter;
1644 uint8_t i, j;
1645 uint8_t bss_desc_count = 0;
1646 uint8_t report_index = 0;
1647 uint16_t rem_len = 0;
1648 uint16_t offset = 0;
1649 uint8_t frag_id = 0;
1650 uint8_t num_frames, num_reports_in_frame, final_measurement_index;
1651 uint32_t populated_beacon_report_size = 0;
1652 uint32_t max_reports_in_frame = 0;
1653 uint32_t radio_meas_rpt_size = 0, dot11_meas_rpt_size = 0;
1654 bool is_last_measurement_frame;
1655
1656
1657 if (!beacon_xmit_ind) {
1658 pe_err("Received beacon_xmit_ind is NULL in PE");
1659 return QDF_STATUS_E_FAILURE;
1660 }
1661
1662 if (beacon_xmit_ind->measurement_idx >=
1663 QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)) {
1664 pe_err("Received measurement_idx is out of range: %u - %zu",
1665 beacon_xmit_ind->measurement_idx,
1666 QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq));
1667 return QDF_STATUS_E_FAILURE;
1668 }
1669
1670 curr_req = mac_ctx->rrm.rrmPEContext.
1671 pCurrentReq[beacon_xmit_ind->measurement_idx];
1672 if (!curr_req) {
1673 pe_err("Received report xmit while there is no request pending in PE");
1674 status = QDF_STATUS_E_FAILURE;
1675 goto end;
1676 }
1677
1678 pe_debug("Received beacon report xmit indication on idx:%d",
1679 beacon_xmit_ind->measurement_idx);
1680
1681 /*
1682 * Send empty report only if all channels on a measurement index has
1683 * no scan results or if the AP requests for last beacon report
1684 * indication and last channel of the last index has empty report
1685 */
1686 if (beacon_xmit_ind->numBssDesc || curr_req->sendEmptyBcnRpt ||
1687 (beacon_xmit_ind->fMeasureDone &&
1688 curr_req->request.Beacon.last_beacon_report_indication &&
1689 (mac_ctx->rrm.rrmPEContext.num_active_request - 1) == 0)) {
1690 beacon_xmit_ind->numBssDesc = (beacon_xmit_ind->numBssDesc ==
1691 RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT :
1692 beacon_xmit_ind->numBssDesc;
1693
1694 session_entry = pe_find_session_by_bssid(mac_ctx,
1695 beacon_xmit_ind->bssId, &session_id);
1696 if (!session_entry) {
1697 pe_err("TX: [802.11 BCN_RPT] Session does not exist for bssId:"QDF_MAC_ADDR_FMT"",
1698 QDF_MAC_ADDR_REF(beacon_xmit_ind->bssId));
1699 status = QDF_STATUS_E_FAILURE;
1700 goto end;
1701 }
1702
1703 report = qdf_mem_malloc(MAX_BEACON_REPORTS * sizeof(*report));
1704 if (!report) {
1705 status = QDF_STATUS_E_NOMEM;
1706 goto end;
1707 }
1708
1709 for (i = 0; i < MAX_BEACON_REPORTS &&
1710 bss_desc_count < beacon_xmit_ind->numBssDesc; i++) {
1711 beacon_report = &report[i].report.beaconReport;
1712 /*
1713 * If the scan result is NULL then send report request
1714 * with option subelement as NULL.
1715 */
1716 pe_debug("TX: [802.11 BCN_RPT] report %d bss %d", i,
1717 bss_desc_count);
1718 bss_desc = beacon_xmit_ind->
1719 pBssDescription[bss_desc_count];
1720
1721 /* Prepare the beacon report and send it to the peer.*/
1722 report[i].token = beacon_xmit_ind->uDialogToken;
1723 report[i].refused = 0;
1724 report[i].incapable = 0;
1725 report[i].type = SIR_MAC_RRM_BEACON_TYPE;
1726
1727 /*
1728 * Valid response is included if the size of
1729 * becon xmit is == size of beacon xmit ind + ies
1730 */
1731 if (beacon_xmit_ind->length < sizeof(*beacon_xmit_ind))
1732 continue;
1733 beacon_report->regClass = beacon_xmit_ind->regClass;
1734 if (bss_desc) {
1735 beacon_report->channel =
1736 wlan_reg_freq_to_chan(
1737 mac_ctx->pdev,
1738 bss_desc->chan_freq);
1739 qdf_mem_copy(beacon_report->measStartTime,
1740 bss_desc->startTSF,
1741 sizeof(bss_desc->startTSF));
1742 beacon_report->measDuration =
1743 beacon_xmit_ind->duration;
1744 beacon_report->phyType = bss_desc->nwType;
1745 beacon_report->bcnProbeRsp = 1;
1746 beacon_report->rsni = bss_desc->sinr;
1747
1748 rrm_calculate_and_fill_rcpi(&beacon_report->rcpi,
1749 bss_desc->rssi);
1750 beacon_report->antennaId = 0;
1751 beacon_report->parentTSF = bss_desc->parentTSF;
1752 qdf_mem_copy(beacon_report->bssid,
1753 bss_desc->bssId, sizeof(tSirMacAddr));
1754 }
1755
1756 pe_debug("TX: [802.11 BCN_RPT] reporting detail requested %d",
1757 curr_req->request.Beacon.reportingDetail);
1758 switch (curr_req->request.Beacon.reportingDetail) {
1759 case BEACON_REPORTING_DETAIL_NO_FF_IE:
1760 /* 0: No need to include any elements. */
1761 break;
1762 case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE:
1763 /* 1: Include all FFs and Requested Ies. */
1764 if (!bss_desc)
1765 break;
1766
1767 rem_len = rrm_fill_beacon_ies(mac_ctx,
1768 (uint8_t *)&beacon_report->Ies[0],
1769 (uint8_t *)&beacon_report->numIes,
1770 BEACON_REPORT_MAX_IES,
1771 curr_req->request.Beacon.reqIes.
1772 pElementIds,
1773 curr_req->request.Beacon.reqIes.num,
1774 curr_req->request.Beacon.reqIes.ext_info.eid,
1775 &curr_req->request.Beacon.reqIes.ext_info.eid_ext[0],
1776 curr_req->request.Beacon.reqIes.ext_info.num_eid_ext,
1777 offset, bss_desc);
1778 break;
1779 case BEACON_REPORTING_DETAIL_ALL_FF_IE:
1780 /* 2: default - Include all FFs and all Ies. */
1781 default:
1782 if (!bss_desc)
1783 break;
1784
1785 rem_len = rrm_fill_beacon_ies(mac_ctx,
1786 (uint8_t *) &beacon_report->Ies[0],
1787 (uint8_t *) &beacon_report->numIes,
1788 BEACON_REPORT_MAX_IES,
1789 NULL,
1790 0,
1791 0,
1792 NULL,
1793 0,
1794 offset, bss_desc);
1795 break;
1796 }
1797 beacon_report->frame_body_frag_id.id = bss_desc_count;
1798 beacon_report->frame_body_frag_id.frag_id = frag_id;
1799 /*
1800 * If remaining length is non-zero, the beacon needs to
1801 * be fragmented only if the current request supports
1802 * last beacon report indication.
1803 * If last beacon report indication is not supported,
1804 * truncate and move on to the next beacon.
1805 */
1806 if (rem_len &&
1807 curr_req->request.Beacon.
1808 last_beacon_report_indication) {
1809 offset = GET_IE_LEN_IN_BSS(
1810 bss_desc->length) - rem_len;
1811 pe_debug("TX: [802.11 BCN_RPT] offset %d ie_len %lu rem_len %d frag_id %d",
1812 offset,
1813 GET_IE_LEN_IN_BSS(bss_desc->length),
1814 rem_len, frag_id);
1815 frag_id++;
1816 beacon_report->frame_body_frag_id.more_frags =
1817 true;
1818 } else {
1819 offset = 0;
1820 beacon_report->frame_body_frag_id.more_frags =
1821 false;
1822 frag_id = 0;
1823 bss_desc_count++;
1824 pe_debug("TX: [802.11 BCN_RPT] No remaining IEs");
1825 }
1826
1827 if (curr_req->request.Beacon.last_beacon_report_indication)
1828 beacon_report->last_bcn_report_ind_support = 1;
1829
1830 }
1831
1832 pe_debug("TX: [802.11 BCN_RPT] Total reports filled %d, last bcn_rpt ind:%d",
1833 i , curr_req->request.Beacon.last_beacon_report_indication);
1834
1835 /* Calculate size of populated beacon reports */
1836 radio_meas_rpt_size = sizeof(tSirMacRadioMeasureReport);
1837 populated_beacon_report_size = (i * radio_meas_rpt_size);
1838
1839 /* Calculate num of mgmt frames to send */
1840 num_frames = populated_beacon_report_size / MAX_MGMT_MPDU_LEN;
1841 if (populated_beacon_report_size % MAX_MGMT_MPDU_LEN)
1842 num_frames++;
1843
1844 /* Calculate num of maximum mgmt reports per frame */
1845 dot11_meas_rpt_size = sizeof(tDot11fRadioMeasurementReport);
1846 max_reports_in_frame = MAX_MGMT_MPDU_LEN / dot11_meas_rpt_size;
1847
1848 for (j = 0; j < num_frames; j++) {
1849 num_reports_in_frame = QDF_MIN((i - report_index),
1850 max_reports_in_frame);
1851
1852 final_measurement_index =
1853 mac_ctx->rrm.rrmPEContext.num_active_request;
1854 is_last_measurement_frame =
1855 ((j == num_frames - 1) &&
1856 beacon_xmit_ind->fMeasureDone &&
1857 !(final_measurement_index - 1));
1858
1859 lim_send_radio_measure_report_action_frame(mac_ctx,
1860 curr_req->dialog_token, num_reports_in_frame,
1861 is_last_measurement_frame,
1862 &report[report_index],
1863 beacon_xmit_ind->bssId, session_entry);
1864 report_index += num_reports_in_frame;
1865 }
1866 curr_req->sendEmptyBcnRpt = false;
1867 }
1868
1869 end:
1870 for (counter = 0; counter < beacon_xmit_ind->numBssDesc; counter++)
1871 qdf_mem_free(beacon_xmit_ind->pBssDescription[counter]);
1872
1873 if (beacon_xmit_ind->fMeasureDone) {
1874 pe_debug("Measurement done idx:%d",
1875 beacon_xmit_ind->measurement_idx);
1876 rrm_cleanup(mac_ctx, beacon_xmit_ind->measurement_idx);
1877 }
1878
1879 if (report)
1880 qdf_mem_free(report);
1881
1882 return status;
1883 }
1884
1885 static void
rrm_process_beacon_request_failure(struct mac_context * mac,struct pe_session * pe_session,tSirMacAddr peer,tRrmRetStatus status,uint8_t index)1886 rrm_process_beacon_request_failure(struct mac_context *mac,
1887 struct pe_session *pe_session,
1888 tSirMacAddr peer,
1889 tRrmRetStatus status, uint8_t index)
1890 {
1891 tpSirMacRadioMeasureReport pReport = NULL;
1892 tpRRMReq pCurrentReq = mac->rrm.rrmPEContext.pCurrentReq[index];
1893
1894 if (!pCurrentReq) {
1895 pe_err("Current request is NULL");
1896 return;
1897 }
1898
1899 pReport = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
1900 if (!pReport)
1901 return;
1902 pReport->token = pCurrentReq->token;
1903 pReport->type = SIR_MAC_RRM_BEACON_TYPE;
1904
1905 pe_debug("Measurement index:%d status %d token %d", index, status,
1906 pReport->token);
1907
1908 switch (status) {
1909 case eRRM_REFUSED:
1910 pReport->refused = 1;
1911 break;
1912 case eRRM_INCAPABLE:
1913 pReport->incapable = 1;
1914 break;
1915 default:
1916 pe_err("RX [802.11 BCN_RPT] Beacon request processing failed no report sent");
1917 qdf_mem_free(pReport);
1918 return;
1919 }
1920
1921 if (pCurrentReq->request.Beacon.last_beacon_report_indication)
1922 pReport->report.beaconReport.last_bcn_report_ind_support = 1;
1923
1924 lim_send_radio_measure_report_action_frame(mac,
1925 pCurrentReq->dialog_token,
1926 1, true,
1927 pReport, peer,
1928 pe_session);
1929
1930 qdf_mem_free(pReport);
1931 return;
1932 }
1933
1934 /**
1935 * rrm_process_beacon_req() - Update curr_req and report
1936 * @mac_ctx: Global pointer to MAC context
1937 * @peer: Macaddress of the peer requesting the radio measurement
1938 * @session_entry: session entry
1939 * @radiomes_report: Pointer to radio measurement report
1940 * @rrm_req: Array of Measurement request IEs
1941 * @num_report: No.of reports
1942 * @index: Index for Measurement request
1943 *
1944 * Update structure sRRMReq and sSirMacRadioMeasureReport and pass it to
1945 * rrm_process_beacon_report_req().
1946 *
1947 * Return: QDF_STATUS
1948 */
1949 static
rrm_process_beacon_req(struct mac_context * mac_ctx,tSirMacAddr peer,struct pe_session * session_entry,tpSirMacRadioMeasureReport * radiomes_report,tDot11fRadioMeasurementRequest * rrm_req,uint8_t * num_report,int index)1950 QDF_STATUS rrm_process_beacon_req(struct mac_context *mac_ctx, tSirMacAddr peer,
1951 struct pe_session *session_entry,
1952 tpSirMacRadioMeasureReport *radiomes_report,
1953 tDot11fRadioMeasurementRequest *rrm_req,
1954 uint8_t *num_report, int index)
1955 {
1956 tRrmRetStatus rrm_status = eRRM_SUCCESS;
1957 tpSirMacRadioMeasureReport report = NULL;
1958 tpRRMReq curr_req;
1959 QDF_STATUS status = QDF_STATUS_SUCCESS;
1960
1961 if (index >= MAX_MEASUREMENT_REQUEST) {
1962 status = rrm_reject_req(&report, rrm_req, num_report, index,
1963 rrm_req->MeasurementRequest[0].
1964 measurement_type);
1965 return status;
1966 }
1967
1968 curr_req = qdf_mem_malloc(sizeof(*curr_req));
1969 if (!curr_req) {
1970 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL;
1971 return QDF_STATUS_E_NOMEM;
1972 }
1973 pe_debug("Processing Beacon Report request %d", index);
1974 curr_req->dialog_token = rrm_req->DialogToken.token;
1975 curr_req->token =
1976 rrm_req->MeasurementRequest[index].measurement_token;
1977 curr_req->sendEmptyBcnRpt = true;
1978 curr_req->measurement_idx = index;
1979 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req;
1980 mac_ctx->rrm.rrmPEContext.num_active_request++;
1981 pe_debug("Processing Bcn Report req %d num_active_req:%d",
1982 index, mac_ctx->rrm.rrmPEContext.num_active_request);
1983 rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req,
1984 &rrm_req->MeasurementRequest[index], session_entry);
1985 if (eRRM_SUCCESS != rrm_status) {
1986 rrm_process_beacon_request_failure(mac_ctx,
1987 session_entry, peer, rrm_status, index);
1988 rrm_cleanup(mac_ctx, index);
1989 }
1990
1991 return QDF_STATUS_SUCCESS;
1992 }
1993
1994
1995 /**
1996 * rrm_process_channel_load_req() - process channel load request from AP
1997 * @mac: global mac context
1998 * @pe_session: per-vdev PE context
1999 * @curr_req: current measurement req in progress
2000 * @peer: Macaddress of the peer requesting the radio measurement
2001 * @chan_load_req: channel load request received from AP
2002 *
2003 * return tRrmRetStatus
2004 */
2005 static tRrmRetStatus
rrm_process_channel_load_req(struct mac_context * mac,struct pe_session * pe_session,tpRRMReq curr_req,tSirMacAddr peer,tDot11fIEMeasurementRequest * chan_load_req)2006 rrm_process_channel_load_req(struct mac_context *mac,
2007 struct pe_session *pe_session,
2008 tpRRMReq curr_req, tSirMacAddr peer,
2009 tDot11fIEMeasurementRequest *chan_load_req)
2010 {
2011 struct scheduler_msg msg = {0};
2012 struct ch_load_ind *load_ind;
2013 struct bw_ind_element bw_ind = {0};
2014 struct wide_bw_chan_switch wide_bw = {0};
2015 struct rrm_reporting rrm_report;
2016 uint8_t op_class, channel;
2017 uint16_t randomization_intv, meas_duration, max_meas_duration;
2018 bool is_rrm_reporting, is_wide_bw_chan_switch;
2019 uint8_t country[WNI_CFG_COUNTRY_CODE_LEN];
2020 qdf_freq_t chan_freq;
2021 bool is_freq_enabled, is_bw_ind;
2022
2023 if (wlan_policy_mgr_get_ll_lt_sap_vdev_id(mac->psoc) != WLAN_INVALID_VDEV_ID) {
2024 pe_debug("RX:[802.11 CH_LOAD] reject req as ll_lt_sap is present");
2025 return eRRM_REFUSED;
2026 }
2027
2028 is_rrm_reporting = chan_load_req->measurement_request.channel_load.rrm_reporting.present;
2029 is_wide_bw_chan_switch = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.present;
2030 is_bw_ind = chan_load_req->measurement_request.channel_load.bw_indication.present;
2031
2032 pe_debug("RX:[802.11 CH_LOAD] vdev: %d, is_rrm_reporting: %d, is_wide_bw_chan_switch: %d, is_bw_ind: %d",
2033 pe_session->vdev_id, is_rrm_reporting, is_wide_bw_chan_switch,
2034 is_bw_ind);
2035
2036 if (is_rrm_reporting) {
2037 rrm_report.threshold = chan_load_req->measurement_request.channel_load.rrm_reporting.threshold;
2038 rrm_report.reporting_condition = chan_load_req->measurement_request.channel_load.rrm_reporting.reporting_condition;
2039 pe_debug("RX:[802.11 CH_LOAD] threshold:%d reporting_c:%d",
2040 rrm_report.threshold, rrm_report.reporting_condition);
2041 if (rrm_report.reporting_condition != 0) {
2042 pe_debug("RX:[802.11 CH_LOAD]: Dropping req");
2043 return eRRM_INCAPABLE;
2044 }
2045 }
2046
2047 if (is_bw_ind) {
2048 bw_ind.is_bw_ind_element = true;
2049 bw_ind.channel_width = chan_load_req->measurement_request.channel_load.bw_indication.channel_width;
2050 bw_ind.ccfi0 = chan_load_req->measurement_request.channel_load.bw_indication.ccfs0;
2051 bw_ind.ccfi1 = chan_load_req->measurement_request.channel_load.bw_indication.ccfs1;
2052 bw_ind.center_freq = wlan_reg_compute_6g_center_freq_from_cfi(bw_ind.ccfi0);
2053 pe_debug("RX:[802.11 CH_LOAD] chan_width:%d ccfs0:%d, ccfs1:%d, center_freq:%d",
2054 bw_ind.channel_width, bw_ind.ccfi0,
2055 bw_ind.ccfi1, bw_ind.center_freq);
2056
2057 if (bw_ind.channel_width == 0 || !bw_ind.ccfi0 ||
2058 bw_ind.channel_width < CH_WIDTH_320MHZ || !bw_ind.center_freq) {
2059 pe_debug("Dropping req: invalid is_bw_ind_element IE");
2060 return eRRM_REFUSED;
2061 }
2062 }
2063
2064 if (is_wide_bw_chan_switch) {
2065 wide_bw.is_wide_bw_chan_switch = true;
2066 wide_bw.channel_width = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_chan_width;
2067 wide_bw.center_chan_freq0 = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_center_chan_freq0;
2068 wide_bw.center_chan_freq1 = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_center_chan_freq1;
2069 pe_debug("RX:[802.11 CH_LOAD] cw:%d ccf0:%d, ccf1:%d",
2070 wide_bw.channel_width, wide_bw.center_chan_freq0,
2071 wide_bw.center_chan_freq1);
2072 if (wide_bw.channel_width < CH_WIDTH_20MHZ ||
2073 wide_bw.channel_width >= CH_WIDTH_320MHZ) {
2074 pe_debug("Dropping req: invalid wide_bw IE");
2075 return eRRM_REFUSED;
2076 }
2077 }
2078
2079 op_class = chan_load_req->measurement_request.channel_load.op_class;
2080 channel = chan_load_req->measurement_request.channel_load.channel;
2081 meas_duration =
2082 chan_load_req->measurement_request.channel_load.meas_duration;
2083 randomization_intv =
2084 chan_load_req->measurement_request.channel_load.randomization_intv;
2085 max_meas_duration = rrm_get_max_meas_duration(mac, pe_session);
2086
2087 if (max_meas_duration < meas_duration) {
2088 if (chan_load_req->durationMandatory) {
2089 pe_nofl_err("RX:[802.11 CH_LOAD] Dropping the req: duration mandatory & max duration > meas duration");
2090 return eRRM_REFUSED;
2091 }
2092 meas_duration = max_meas_duration;
2093 }
2094
2095 pe_debug("RX:[802.11 CH_LOAD] vdev :%d, seq:%d Token:%d op_c:%d ch:%d meas_dur:%d, rand intv: %d, max_dur:%d",
2096 pe_session->vdev_id,
2097 mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
2098 chan_load_req->measurement_token, op_class,
2099 channel, meas_duration, randomization_intv,
2100 max_meas_duration);
2101
2102 if (!meas_duration || meas_duration > RRM_SCAN_MAX_DWELL_TIME)
2103 return eRRM_REFUSED;
2104
2105 if (!wlan_reg_is_6ghz_supported(mac->psoc) &&
2106 (wlan_reg_is_6ghz_op_class(mac->pdev, op_class))) {
2107 pe_debug("RX: [802.11 CH_LOAD] Ch belongs to 6 ghz spectrum, abort");
2108 return eRRM_INCAPABLE;
2109 }
2110
2111 rrm_get_country_code_from_connected_profile(mac, pe_session->vdev_id,
2112 country);
2113 chan_freq = wlan_reg_country_chan_opclass_to_freq(mac->pdev,
2114 country, channel,
2115 op_class, false);
2116 if (!chan_freq) {
2117 pe_debug("Invalid ch freq for country code %c%c 0x%x",
2118 country[0], country[1], country[2]);
2119 return eRRM_INCAPABLE;
2120 }
2121
2122 pe_debug("freq:%d, country code %c%c 0x%x", chan_freq, country[0],
2123 country[1], country[2]);
2124
2125 is_freq_enabled = wlan_reg_is_freq_enabled(mac->pdev, chan_freq,
2126 REG_CURRENT_PWR_MODE);
2127 if (!is_freq_enabled) {
2128 pe_debug("No channels populated with requested operation class and current country, Hence abort the rrm operation");
2129 return eRRM_INCAPABLE;
2130 }
2131
2132 /* Prepare the request to send to SME. */
2133 load_ind = qdf_mem_malloc(sizeof(struct ch_load_ind));
2134 if (!load_ind)
2135 return eRRM_FAILURE;
2136
2137 qdf_mem_copy(load_ind->peer_addr.bytes, peer,
2138 sizeof(struct qdf_mac_addr));
2139 load_ind->message_type = eWNI_SME_CHAN_LOAD_REQ_IND;
2140 load_ind->length = sizeof(struct ch_load_ind);
2141 load_ind->dialog_token = chan_load_req->measurement_token;
2142 load_ind->msg_source = eRRM_MSG_SOURCE_11K;
2143 load_ind->randomization_intv = SYS_TU_TO_MS(randomization_intv);
2144 load_ind->measurement_idx = curr_req->measurement_idx;
2145 load_ind->channel = channel;
2146 load_ind->req_freq = chan_freq;
2147 load_ind->op_class = op_class;
2148 load_ind->meas_duration = meas_duration;
2149 curr_req->token = chan_load_req->measurement_token;
2150
2151 if (is_wide_bw_chan_switch)
2152 load_ind->wide_bw = wide_bw;
2153
2154 if (is_bw_ind)
2155 load_ind->bw_ind = bw_ind;
2156
2157 /* Send request to SME. */
2158 msg.type = eWNI_SME_CHAN_LOAD_REQ_IND;
2159 msg.bodyptr = load_ind;
2160 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG,
2161 pe_session->vdev_id, msg.type));
2162 lim_sys_process_mmh_msg_api(mac, &msg);
2163 return eRRM_SUCCESS;
2164 }
2165
2166 /**
2167 * rrm_process_chan_load_request_failure() - process channel load request
2168 * in case of failure
2169 * @mac: global mac context
2170 * @pe_session: per-vdev PE context
2171 * @peer: peer mac address
2172 * @status:failure status of channel load request
2173 * @index: request index
2174 *
2175 * return none
2176 */
2177 static void
rrm_process_chan_load_request_failure(struct mac_context * mac,struct pe_session * pe_session,tSirMacAddr peer,tRrmRetStatus status,uint8_t index)2178 rrm_process_chan_load_request_failure(struct mac_context *mac,
2179 struct pe_session *pe_session,
2180 tSirMacAddr peer,
2181 tRrmRetStatus status, uint8_t index)
2182 {
2183 tpSirMacRadioMeasureReport report = NULL;
2184 tpRRMReq curr_req = mac->rrm.rrmPEContext.pCurrentReq[index];
2185
2186 if (!curr_req) {
2187 pe_debug("Current request is NULL");
2188 goto cleanup;
2189 }
2190 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
2191 if (!report)
2192 goto cleanup;
2193 report->token = curr_req->token;
2194 report->type = SIR_MAC_RRM_CHANNEL_LOAD_TYPE;
2195 pe_debug("vdev:%d measurement index:%d status %d token %d",
2196 pe_session->vdev_id, index, status, report->token);
2197 switch (status) {
2198 case eRRM_REFUSED:
2199 case eRRM_FAILURE:
2200 report->refused = 1;
2201 break;
2202 case eRRM_INCAPABLE:
2203 report->incapable = 1;
2204 break;
2205 default:
2206 goto free;
2207 }
2208
2209 lim_send_radio_measure_report_action_frame(mac, curr_req->dialog_token,
2210 1, true, report, peer,
2211 pe_session);
2212 free:
2213 qdf_mem_free(report);
2214 cleanup:
2215 rrm_cleanup(mac, index);
2216 }
2217
2218 void
rrm_process_chan_load_report_xmit(struct mac_context * mac_ctx,struct chan_load_xmit_ind * chan_load_ind)2219 rrm_process_chan_load_report_xmit(struct mac_context *mac_ctx,
2220 struct chan_load_xmit_ind *chan_load_ind)
2221 {
2222 tSirMacRadioMeasureReport *report = NULL;
2223 struct chan_load_report *channel_load_report;
2224 tpRRMReq curr_req;
2225 struct pe_session *session_entry;
2226 uint8_t session_id, idx;
2227 struct qdf_mac_addr sessionBssId;
2228
2229 if (!chan_load_ind) {
2230 pe_err("Received chan_load_xmit_ind is NULL in PE");
2231 return;
2232 }
2233
2234 idx = chan_load_ind->measurement_idx;
2235
2236 if (idx >= QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq)) {
2237 pe_err("Received measurement_idx is out of range: %u - %zu",
2238 idx,
2239 QDF_ARRAY_SIZE(mac_ctx->rrm.rrmPEContext.pCurrentReq));
2240 return;
2241 }
2242
2243 curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[idx];
2244 if (!curr_req) {
2245 pe_err("no request pending in PE");
2246 goto end;
2247 }
2248
2249 pe_debug("Received chan load report xmit indication on idx:%d", idx);
2250
2251 sessionBssId = mac_ctx->rrm.rrmSmeContext[idx].sessionBssId;
2252
2253 session_entry = pe_find_session_by_bssid(mac_ctx, sessionBssId.bytes,
2254 &session_id);
2255 if (!session_entry) {
2256 pe_err("NULL session for bssId "QDF_MAC_ADDR_FMT"",
2257 QDF_MAC_ADDR_REF(sessionBssId.bytes));
2258 goto end;
2259 }
2260
2261 if (!chan_load_ind->is_report_success) {
2262 rrm_process_chan_load_request_failure(mac_ctx, session_entry,
2263 sessionBssId.bytes,
2264 eRRM_REFUSED, idx);
2265 return;
2266 }
2267
2268 report = qdf_mem_malloc(sizeof(*report));
2269 if (!report)
2270 goto end;
2271
2272 /* Prepare the channel load report and send it to the peer.*/
2273 report->token = chan_load_ind->dialog_token;
2274 report->refused = 0;
2275 report->incapable = 0;
2276 report->type = SIR_MAC_RRM_CHANNEL_LOAD_TYPE;
2277
2278 channel_load_report = &report[0].report.channel_load_report;
2279 channel_load_report->op_class = chan_load_ind->op_class;
2280 channel_load_report->channel = chan_load_ind->channel;
2281 channel_load_report->rrm_scan_tsf = chan_load_ind->rrm_scan_tsf;
2282 channel_load_report->meas_duration = chan_load_ind->duration;
2283 channel_load_report->chan_load = chan_load_ind->chan_load;
2284 qdf_mem_copy(&channel_load_report->bw_ind, &chan_load_ind->bw_ind,
2285 sizeof(channel_load_report->bw_ind));
2286 qdf_mem_copy(&channel_load_report->wide_bw, &chan_load_ind->wide_bw,
2287 sizeof(channel_load_report->wide_bw));
2288 pe_err("send chan load report for bssId:" QDF_MAC_ADDR_FMT " reg_class:%d, channel:%d, measStartTime:%lu, measDuration:%d, chan_load:%d",
2289 QDF_MAC_ADDR_REF(sessionBssId.bytes),
2290 channel_load_report->op_class,
2291 channel_load_report->channel,
2292 channel_load_report->rrm_scan_tsf,
2293 channel_load_report->meas_duration,
2294 channel_load_report->chan_load);
2295
2296 lim_send_radio_measure_report_action_frame(mac_ctx,
2297 curr_req->dialog_token, 1,
2298 true, &report[0],
2299 sessionBssId.bytes,
2300 session_entry);
2301
2302 end:
2303 pe_debug("Measurement done idx:%d", idx);
2304 rrm_cleanup(mac_ctx, idx);
2305 qdf_mem_free(report);
2306
2307 return;
2308 }
2309
2310 /**
2311 * rrm_process_chan_load_req() - process channel load request
2312 * @mac_ctx: Global pointer to MAC context
2313 * @session_entry: session entry
2314 * @report: Pointer to radio measurement report
2315 * @rrm_req: Array of Measurement request IEs
2316 * @peer: mac address of the peer requesting the radio measurement
2317 * @num_report: No.of reports
2318 * @index: Index for Measurement request
2319 *
2320 * Update structure sRRMReq and struct chan_load_req_ind and pass it to
2321 * rrm_process_channel_load_req().
2322 *
2323 * Return: QDF_STATUS
2324 */
2325 static QDF_STATUS
rrm_process_chan_load_req(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirMacRadioMeasureReport * report,tDot11fRadioMeasurementRequest * rrm_req,tSirMacAddr peer,uint8_t * num_report,int index)2326 rrm_process_chan_load_req(struct mac_context *mac_ctx,
2327 struct pe_session *session_entry,
2328 tpSirMacRadioMeasureReport *report,
2329 tDot11fRadioMeasurementRequest *rrm_req,
2330 tSirMacAddr peer, uint8_t *num_report, int index)
2331 {
2332 tRrmRetStatus rrm_status = eRRM_SUCCESS;
2333 tpRRMReq curr_req;
2334 QDF_STATUS status = QDF_STATUS_SUCCESS;
2335
2336 if (index >= MAX_MEASUREMENT_REQUEST) {
2337 status = rrm_reject_req(report, rrm_req, num_report, index,
2338 rrm_req->MeasurementRequest[0].measurement_type);
2339 return status;
2340 }
2341
2342 curr_req = qdf_mem_malloc(sizeof(*curr_req));
2343 if (!curr_req) {
2344 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL;
2345 return QDF_STATUS_E_NOMEM;
2346 }
2347
2348 curr_req->dialog_token = rrm_req->DialogToken.token;
2349 curr_req->token =
2350 rrm_req->MeasurementRequest[index].measurement_token;
2351 curr_req->measurement_idx = index;
2352 mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req;
2353 mac_ctx->rrm.rrmPEContext.num_active_request++;
2354 pe_debug("Processing channel load req index: %d num_active_req:%d",
2355 index, mac_ctx->rrm.rrmPEContext.num_active_request);
2356 rrm_status = rrm_process_channel_load_req(mac_ctx, session_entry,
2357 curr_req, peer,
2358 &rrm_req->MeasurementRequest[index]);
2359 if (eRRM_SUCCESS != rrm_status)
2360 rrm_process_chan_load_request_failure(mac_ctx, session_entry,
2361 peer, rrm_status, index);
2362
2363 return QDF_STATUS_SUCCESS;
2364 }
2365
2366 /**
2367 * update_rrm_report() - Set incapable bit
2368 * @mac_ctx: Global pointer to MAC context
2369 * @report: Pointer to radio measurement report
2370 * @rrm_req: Array of Measurement request IEs
2371 * @num_report: No.of reports
2372 * @index: Index for Measurement request
2373 *
2374 * Send a report with incapabale bit set
2375 *
2376 * Return: QDF_STATUS
2377 */
2378 static
update_rrm_report(struct mac_context * mac_ctx,tpSirMacRadioMeasureReport * report,tDot11fRadioMeasurementRequest * rrm_req,uint8_t * num_report,int index)2379 QDF_STATUS update_rrm_report(struct mac_context *mac_ctx,
2380 tpSirMacRadioMeasureReport *report,
2381 tDot11fRadioMeasurementRequest *rrm_req,
2382 uint8_t *num_report, int index)
2383 {
2384 tpSirMacRadioMeasureReport rrm_report;
2385
2386 if (!*report) {
2387 /*
2388 * Allocate memory to send reports for
2389 * any subsequent requests.
2390 */
2391 *report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport) *
2392 (rrm_req->num_MeasurementRequest - index));
2393 if (!*report)
2394 return QDF_STATUS_E_NOMEM;
2395 pe_debug("rrm beacon type incapable of %d report", *num_report);
2396 }
2397 rrm_report = *report;
2398 rrm_report[*num_report].incapable = 1;
2399 rrm_report[*num_report].type =
2400 rrm_req->MeasurementRequest[index].measurement_type;
2401 rrm_report[*num_report].token =
2402 rrm_req->MeasurementRequest[index].measurement_token;
2403 (*num_report)++;
2404 return QDF_STATUS_SUCCESS;
2405 }
2406
rrm_reject_req(tpSirMacRadioMeasureReport * radiomes_report,tDot11fRadioMeasurementRequest * rrm_req,uint8_t * num_report,uint8_t index,uint8_t measurement_type)2407 QDF_STATUS rrm_reject_req(tpSirMacRadioMeasureReport *radiomes_report,
2408 tDot11fRadioMeasurementRequest *rrm_req,
2409 uint8_t *num_report, uint8_t index,
2410 uint8_t measurement_type)
2411 {
2412 tpSirMacRadioMeasureReport report;
2413
2414 if (!*radiomes_report) {
2415 /*
2416 * Allocate memory to send reports for
2417 * any subsequent requests.
2418 */
2419 *radiomes_report = qdf_mem_malloc(sizeof(*report) *
2420 (rrm_req->num_MeasurementRequest - index));
2421 if (!*radiomes_report)
2422 return QDF_STATUS_E_NOMEM;
2423
2424 pe_debug("rrm beacon refused of %d report, index: %d in beacon table",
2425 *num_report, index);
2426 }
2427 report = *radiomes_report;
2428 report[*num_report].refused = 1;
2429 report[*num_report].type = measurement_type;
2430 report[*num_report].token =
2431 rrm_req->MeasurementRequest[index].measurement_token;
2432 (*num_report)++;
2433
2434 return QDF_STATUS_SUCCESS;
2435
2436 }
2437
2438 /* -------------------------------------------------------------------- */
2439 /**
2440 * rrm_process_radio_measurement_request - Process rrm request
2441 * @mac_ctx: Global pointer to MAC context
2442 * @peer: Macaddress of the peer requesting the radio measurement.
2443 * @rrm_req: Array of Measurement request IEs
2444 * @session_entry: session entry.
2445 *
2446 * Processes the Radio Resource Measurement request.
2447 *
2448 * Return: QDF_STATUS
2449 */
2450 QDF_STATUS
rrm_process_radio_measurement_request(struct mac_context * mac_ctx,tSirMacAddr peer,tDot11fRadioMeasurementRequest * rrm_req,struct pe_session * session_entry)2451 rrm_process_radio_measurement_request(struct mac_context *mac_ctx,
2452 tSirMacAddr peer,
2453 tDot11fRadioMeasurementRequest *rrm_req,
2454 struct pe_session *session_entry)
2455 {
2456 uint8_t i, index;
2457 QDF_STATUS status = QDF_STATUS_SUCCESS;
2458 tpSirMacRadioMeasureReport report = NULL;
2459 uint8_t num_report = 0;
2460 bool reject = false;
2461
2462 if (!rrm_req->num_MeasurementRequest) {
2463 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
2464 if (!report)
2465 return QDF_STATUS_E_NOMEM;
2466 pe_err("RX: [802.11 RRM] No requestIes in the measurement request, sending incapable report");
2467 report->incapable = 1;
2468 num_report = 1;
2469 lim_send_radio_measure_report_action_frame(mac_ctx,
2470 rrm_req->DialogToken.token, num_report, true,
2471 report, peer, session_entry);
2472 qdf_mem_free(report);
2473 return QDF_STATUS_E_FAILURE;
2474 }
2475 /* PF Fix */
2476 if (rrm_req->NumOfRepetitions.repetitions > 0) {
2477 pe_info("RX: [802.11 RRM] number of repetitions %d, sending incapable report",
2478 rrm_req->NumOfRepetitions.repetitions);
2479 /*
2480 * Send a report with incapable bit set.
2481 * Not supporting repetitions.
2482 */
2483 report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
2484 if (!report)
2485 return QDF_STATUS_E_NOMEM;
2486 report->incapable = 1;
2487 report->type = rrm_req->MeasurementRequest[0].measurement_type;
2488 num_report = 1;
2489 goto end;
2490 }
2491
2492 for (index = 0; index < MAX_MEASUREMENT_REQUEST; index++) {
2493 if (mac_ctx->rrm.rrmPEContext.pCurrentReq[index]) {
2494 reject = true;
2495 pe_debug("RRM req for index: %d is already in progress",
2496 index);
2497 break;
2498 }
2499 }
2500
2501 if (reject) {
2502 for (i = 0; i < rrm_req->num_MeasurementRequest; i++) {
2503 status =
2504 rrm_reject_req(&report, rrm_req, &num_report, i,
2505 rrm_req->MeasurementRequest[i].
2506 measurement_type);
2507 if (QDF_IS_STATUS_ERROR(status)) {
2508 pe_debug("Fail to Reject rrm req for index: %d",
2509 i);
2510 return status;
2511 }
2512 }
2513
2514 goto end;
2515 }
2516
2517 /*
2518 * Clear global beacon_rpt_chan_list before processing every new
2519 * beacon report request.
2520 */
2521 qdf_mem_zero(mac_ctx->rrm.rrmPEContext.beacon_rpt_chan_list,
2522 sizeof(uint8_t) * MAX_NUM_CHANNELS);
2523 mac_ctx->rrm.rrmPEContext.beacon_rpt_chan_num = 0;
2524
2525 for (i = 0; i < rrm_req->num_MeasurementRequest; i++) {
2526 switch (rrm_req->MeasurementRequest[i].measurement_type) {
2527 case SIR_MAC_RRM_CHANNEL_LOAD_TYPE:
2528 /* Process channel load request */
2529 status = rrm_process_chan_load_req(mac_ctx,
2530 session_entry,
2531 &report,
2532 rrm_req, peer,
2533 &num_report, i);
2534 if (QDF_IS_STATUS_ERROR(status))
2535 return status;
2536 break;
2537 case SIR_MAC_RRM_BEACON_TYPE:
2538 /* Process beacon request. */
2539 status = rrm_process_beacon_req(mac_ctx, peer,
2540 session_entry, &report,
2541 rrm_req, &num_report,
2542 i);
2543 if (QDF_IS_STATUS_ERROR(status))
2544 return status;
2545 break;
2546 case SIR_MAC_RRM_STA_STATISTICS_TYPE:
2547 status = rrm_process_sta_stats_req(mac_ctx, peer,
2548 session_entry, &report,
2549 rrm_req, &num_report,
2550 i);
2551 break;
2552 case SIR_MAC_RRM_LCI_TYPE:
2553 case SIR_MAC_RRM_LOCATION_CIVIC_TYPE:
2554 case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE:
2555 pe_debug("RRM with type: %d sent to userspace",
2556 rrm_req->MeasurementRequest[i].measurement_type);
2557 break;
2558 default:
2559 /* Send a report with incapabale bit set. */
2560 status = update_rrm_report(mac_ctx, &report, rrm_req,
2561 &num_report, i);
2562 if (QDF_STATUS_SUCCESS != status)
2563 return status;
2564 break;
2565 }
2566 }
2567
2568 end:
2569 if (report) {
2570 lim_send_radio_measure_report_action_frame(mac_ctx,
2571 rrm_req->DialogToken.token, num_report, true,
2572 report, peer, session_entry);
2573 qdf_mem_free(report);
2574 }
2575 return status;
2576 }
2577
2578 /**
2579 * rrm_get_start_tsf() - Get the Start TSF.
2580 * @mac: pointer to mac context
2581 * @pStartTSF: store star TSF in this buffer.
2582 *
2583 * Return: None
2584 */
rrm_get_start_tsf(struct mac_context * mac,uint32_t * pStartTSF)2585 void rrm_get_start_tsf(struct mac_context *mac, uint32_t *pStartTSF)
2586 {
2587 pStartTSF[0] = mac->rrm.rrmPEContext.startTSF[0];
2588 pStartTSF[1] = mac->rrm.rrmPEContext.startTSF[1];
2589
2590 }
2591
2592 /* -------------------------------------------------------------------- */
2593 /**
2594 * rrm_get_capabilities() - Returns a pointer to tpRRMCaps with all the
2595 * caps enabled in RRM
2596 * @mac: pointer to mac context
2597 * @pe_session: pointer to pe session
2598 *
2599 * Return: pointer to tRRMCaps
2600 */
rrm_get_capabilities(struct mac_context * mac,struct pe_session * pe_session)2601 tpRRMCaps rrm_get_capabilities(struct mac_context *mac, struct pe_session *pe_session)
2602 {
2603 return &mac->rrm.rrmPEContext.rrmEnabledCaps;
2604 }
2605
2606 /**
2607 * rrm_initialize() - Initialize PE RRM parameters
2608 * @mac: Pointer to mac context
2609 *
2610 * Return: QDF_STATUS
2611 */
rrm_initialize(struct mac_context * mac)2612 QDF_STATUS rrm_initialize(struct mac_context *mac)
2613 {
2614 tpRRMCaps pRRMCaps = &mac->rrm.rrmPEContext.rrmEnabledCaps;
2615 uint8_t i;
2616
2617 for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++)
2618 mac->rrm.rrmPEContext.pCurrentReq[i] = NULL;
2619
2620 mac->rrm.rrmPEContext.txMgmtPower = 0;
2621 mac->rrm.rrmPEContext.DialogToken = 0;
2622
2623 mac->rrm.rrmPEContext.rrmEnable = 0;
2624 mac->rrm.rrmPEContext.prev_rrm_report_seq_num = 0xFFFF;
2625 mac->rrm.rrmPEContext.num_active_request = 0;
2626
2627 qdf_mem_zero(pRRMCaps, sizeof(tRRMCaps));
2628 pRRMCaps->LinkMeasurement = 1;
2629 pRRMCaps->NeighborRpt = 1;
2630 pRRMCaps->BeaconPassive = 1;
2631 pRRMCaps->BeaconActive = 1;
2632 pRRMCaps->BeaconTable = 1;
2633 pRRMCaps->APChanReport = 1;
2634 pRRMCaps->fine_time_meas_rpt = 1;
2635 pRRMCaps->lci_capability = 1;
2636 pRRMCaps->ChannelLoad = 1;
2637 pRRMCaps->statistics = 1;
2638
2639 pRRMCaps->operatingChanMax = 3;
2640 pRRMCaps->nonOperatingChanMax = 3;
2641
2642 return QDF_STATUS_SUCCESS;
2643 }
2644
rrm_cleanup(struct mac_context * mac,uint8_t idx)2645 void rrm_cleanup(struct mac_context *mac, uint8_t idx)
2646 {
2647 tpRRMReq cur_rrm_req = NULL;
2648
2649 if (mac->rrm.rrmPEContext.num_active_request)
2650 mac->rrm.rrmPEContext.num_active_request--;
2651
2652 cur_rrm_req = mac->rrm.rrmPEContext.pCurrentReq[idx];
2653 if (!cur_rrm_req)
2654 return;
2655 if (cur_rrm_req->request.Beacon.reqIes.num) {
2656 qdf_mem_free(cur_rrm_req->request.Beacon.reqIes.pElementIds);
2657 cur_rrm_req->request.Beacon.reqIes.pElementIds = NULL;
2658 cur_rrm_req->request.Beacon.reqIes.num = 0;
2659 }
2660
2661 if (cur_rrm_req->type == SIR_MAC_RRM_STA_STATISTICS_TYPE) {
2662 pe_debug("deactivate rrm sta stats timer");
2663 lim_deactivate_and_change_timer(mac,
2664 eLIM_RRM_STA_STATS_RSP_TIMER);
2665 qdf_mem_zero(&mac->rrm.rrmPEContext.rrm_sta_stats,
2666 sizeof(mac->rrm.rrmPEContext.rrm_sta_stats));
2667 }
2668 qdf_mem_free(cur_rrm_req);
2669 mac->rrm.rrmPEContext.pCurrentReq[idx] = NULL;
2670
2671 pe_debug("cleanup rrm req idx:%d, num_active_request:%d",
2672 idx, mac->rrm.rrmPEContext.num_active_request);
2673 }
2674
2675 /**
2676 * lim_update_rrm_capability() - Update PE context's rrm capability
2677 * @mac_ctx: Global pointer to MAC context
2678 *
2679 * Update PE context's rrm capability
2680 *
2681 * Return: None
2682 */
lim_update_rrm_capability(struct mac_context * mac_ctx)2683 void lim_update_rrm_capability(struct mac_context *mac_ctx)
2684 {
2685 mac_ctx->rrm.rrmPEContext.rrmEnable =
2686 mac_ctx->rrm.rrmConfig.rrm_enabled;
2687 qdf_mem_copy(&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps,
2688 &mac_ctx->rrm.rrmConfig.rm_capability,
2689 RMENABLEDCAP_MAX_LEN);
2690 }
2691