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