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