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