xref: /wlan-dirver/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c (revision 0bec9a925953c0d92cb530c808dd67de56a0923e)
1 /*
2  * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 /**=========================================================================
29 
30    \file  rrm_api.c
31 
32    \brief implementation for PE RRM APIs
33 
34    ========================================================================*/
35 
36 /* $Header$ */
37 
38 
39 /*--------------------------------------------------------------------------
40    Include Files
41    ------------------------------------------------------------------------*/
42 #include "cds_api.h"
43 #include "wni_api.h"
44 #include "sir_api.h"
45 #include "ani_global.h"
46 #include "wni_cfg.h"
47 #include "lim_types.h"
48 #include "lim_utils.h"
49 #include "lim_send_sme_rsp_messages.h"
50 #include "parser_api.h"
51 #include "lim_send_messages.h"
52 #include "rrm_global.h"
53 #include "rrm_api.h"
54 
55 #define MAX_RRM_TX_PWR_CAP 22
56 
57 uint8_t
58 rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac,
59 			    int8_t regMax, int8_t apTxPower)
60 {
61 	uint8_t maxTxPower = 0;
62 	uint8_t txPower = QDF_MIN(regMax, (apTxPower));
63 	if ((txPower >= RRM_MIN_TX_PWR_CAP) && (txPower <= RRM_MAX_TX_PWR_CAP))
64 		maxTxPower = txPower;
65 	else if (txPower < RRM_MIN_TX_PWR_CAP)
66 		maxTxPower = RRM_MIN_TX_PWR_CAP;
67 	else
68 		maxTxPower = RRM_MAX_TX_PWR_CAP;
69 
70 	pe_debug("regulatoryMax: %d, apTxPwr: %d, maxTxpwr: %d",
71 		regMax, apTxPower, maxTxPower);
72 	return maxTxPower;
73 }
74 
75 /* -------------------------------------------------------------------- */
76 /**
77  * rrm_cache_mgmt_tx_power
78  **
79  * FUNCTION:  Store Tx power for management frames.
80  *
81  * LOGIC:
82  *
83  * ASSUMPTIONS:
84  *
85  * NOTE:
86  *
87  * @param pSessionEntry session entry.
88  * @return None
89  */
90 void
91 rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, int8_t txPower,
92 			tpPESession pSessionEntry)
93 {
94 	pe_debug("Cache Mgmt Tx Power: %d", txPower);
95 
96 	if (pSessionEntry == NULL)
97 		pMac->rrm.rrmPEContext.txMgmtPower = txPower;
98 	else
99 		pSessionEntry->txMgmtPower = txPower;
100 }
101 
102 /* -------------------------------------------------------------------- */
103 /**
104  * rrm_get_mgmt_tx_power
105  *
106  * FUNCTION:  Get the Tx power for management frames.
107  *
108  * LOGIC:
109  *
110  * ASSUMPTIONS:
111  *
112  * NOTE:
113  *
114  * @param pSessionEntry session entry.
115  * @return txPower
116  */
117 int8_t rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry)
118 {
119 	if (pSessionEntry == NULL)
120 		return pMac->rrm.rrmPEContext.txMgmtPower;
121 
122 	pe_debug("tx mgmt pwr %d", pSessionEntry->txMgmtPower);
123 
124 	return pSessionEntry->txMgmtPower;
125 }
126 
127 /* -------------------------------------------------------------------- */
128 /**
129  * rrm_send_set_max_tx_power_req
130  *
131  * FUNCTION:  Send WMA_SET_MAX_TX_POWER_REQ message to change the max tx power.
132  *
133  * LOGIC:
134  *
135  * ASSUMPTIONS:
136  *
137  * NOTE:
138  *
139  * @param txPower txPower to be set.
140  * @param pSessionEntry session entry.
141  * @return None
142  */
143 tSirRetStatus
144 rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, int8_t txPower,
145 			      tpPESession pSessionEntry)
146 {
147 	tpMaxTxPowerParams pMaxTxParams;
148 	tSirRetStatus retCode = eSIR_SUCCESS;
149 	struct scheduler_msg msgQ = {0};
150 
151 	if (pSessionEntry == NULL) {
152 		pe_err("Invalid parameters");
153 		return eSIR_FAILURE;
154 	}
155 	pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams));
156 	if (NULL == pMaxTxParams) {
157 		pe_err("Unable to allocate memory for pMaxTxParams");
158 		return eSIR_MEM_ALLOC_FAILED;
159 
160 	}
161 	/* Allocated memory for pMaxTxParams...will be freed in other module */
162 	pMaxTxParams->power = txPower;
163 	qdf_mem_copy(pMaxTxParams->bssId.bytes, pSessionEntry->bssId,
164 		     QDF_MAC_ADDR_SIZE);
165 	qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes,
166 			pSessionEntry->selfMacAddr,
167 			QDF_MAC_ADDR_SIZE);
168 
169 	msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
170 	msgQ.reserved = 0;
171 	msgQ.bodyptr = pMaxTxParams;
172 	msgQ.bodyval = 0;
173 
174 	pe_debug("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL",
175 		txPower);
176 
177 	MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type));
178 	retCode = wma_post_ctrl_msg(pMac, &msgQ);
179 	if (eSIR_SUCCESS != retCode) {
180 		pe_err("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X",
181 			retCode);
182 		qdf_mem_free(pMaxTxParams);
183 		return retCode;
184 	}
185 	return retCode;
186 }
187 
188 /* -------------------------------------------------------------------- */
189 /**
190  * rrm_set_max_tx_power_rsp
191  *
192  * FUNCTION:  Process WMA_SET_MAX_TX_POWER_RSP message.
193  *
194  * LOGIC:
195  *
196  * ASSUMPTIONS:
197  *
198  * NOTE:
199  *
200  * @param txPower txPower to be set.
201  * @param pSessionEntry session entry.
202  * @return None
203  */
204 tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac,
205 				       struct scheduler_msg *limMsgQ)
206 {
207 	tSirRetStatus retCode = eSIR_SUCCESS;
208 	tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr;
209 	tpPESession pSessionEntry;
210 	uint8_t sessionId, i;
211 
212 	if (qdf_is_macaddr_broadcast(&pMaxTxParams->bssId)) {
213 		for (i = 0; i < pMac->lim.maxBssId; i++) {
214 			if (pMac->lim.gpSession[i].valid == true) {
215 				pSessionEntry = &pMac->lim.gpSession[i];
216 				rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power,
217 							pSessionEntry);
218 			}
219 		}
220 	} else {
221 		pSessionEntry = pe_find_session_by_bssid(pMac,
222 							 pMaxTxParams->bssId.bytes,
223 							 &sessionId);
224 		if (pSessionEntry == NULL) {
225 			retCode = eSIR_FAILURE;
226 		} else {
227 			rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power,
228 						pSessionEntry);
229 		}
230 	}
231 
232 	qdf_mem_free(limMsgQ->bodyptr);
233 	limMsgQ->bodyptr = NULL;
234 	return retCode;
235 }
236 
237 /* -------------------------------------------------------------------- */
238 /**
239  * rrm_process_link_measurement_request
240  *
241  * FUNCTION:  Processes the Link measurement request and send the report.
242  *
243  * LOGIC:
244  *
245  * ASSUMPTIONS:
246  *
247  * NOTE:
248  *
249  * @param pBd pointer to BD to extract RSSI and SNR
250  * @param pLinkReq pointer to the Link request frame structure.
251  * @param pSessionEntry session entry.
252  * @return None
253  */
254 tSirRetStatus
255 rrm_process_link_measurement_request(tpAniSirGlobal pMac,
256 				     uint8_t *pRxPacketInfo,
257 				     tDot11fLinkMeasurementRequest *pLinkReq,
258 				     tpPESession pSessionEntry)
259 {
260 	tSirMacLinkReport LinkReport;
261 	tpSirMacMgmtHdr pHdr;
262 	int8_t currentRSSI = 0;
263 
264 	pe_debug("Received Link measurement request");
265 
266 	if (pRxPacketInfo == NULL || pLinkReq == NULL || pSessionEntry == NULL) {
267 		pe_err("Invalid parameters - Ignoring the request");
268 		return eSIR_FAILURE;
269 	}
270 	pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
271 
272 	LinkReport.txPower = lim_get_max_tx_power(pSessionEntry->maxTxPower,
273 						pLinkReq->MaxTxPower.maxTxPower,
274 						  pMac->roam.configParam.
275 						  nTxPowerCap);
276 
277 	if ((LinkReport.txPower != (uint8_t) (pSessionEntry->maxTxPower)) &&
278 	    (eSIR_SUCCESS == rrm_send_set_max_tx_power_req(pMac,
279 							   LinkReport.txPower,
280 							   pSessionEntry))) {
281 		pe_warn("maxTx power in link report is not same as local..."
282 			" Local: %d Link Request TxPower: %d"
283 			" Link Report TxPower: %d",
284 			pSessionEntry->maxTxPower, LinkReport.txPower,
285 			pLinkReq->MaxTxPower.maxTxPower);
286 		pSessionEntry->maxTxPower =
287 			LinkReport.txPower;
288 	}
289 
290 	LinkReport.dialogToken = pLinkReq->DialogToken.token;
291 	LinkReport.rxAntenna = 0;
292 	LinkReport.txAntenna = 0;
293 	currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo);
294 
295 	pe_info("Received Link report frame with %d", currentRSSI);
296 
297 	/* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */
298 	if ((currentRSSI) <= RCPI_LOW_RSSI_VALUE)
299 		LinkReport.rcpi = 0;
300 	else if ((currentRSSI > RCPI_LOW_RSSI_VALUE) && (currentRSSI <= 0))
301 		LinkReport.rcpi = CALCULATE_RCPI(currentRSSI);
302 	else
303 		LinkReport.rcpi = RCPI_MAX_VALUE;
304 
305 	LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo);
306 
307 	pe_debug("Sending Link report frame");
308 
309 	return lim_send_link_report_action_frame(pMac, &LinkReport, pHdr->sa,
310 						 pSessionEntry);
311 }
312 
313 /* -------------------------------------------------------------------- */
314 /**
315  * rrm_process_neighbor_report_response
316  *
317  * FUNCTION:  Processes the Neighbor Report response from the peer AP.
318  *
319  * LOGIC:
320  *
321  * ASSUMPTIONS:
322  *
323  * NOTE:
324  *
325  * @param pNeighborRep pointer to the Neighbor report frame structure.
326  * @param pSessionEntry session entry.
327  * @return None
328  */
329 tSirRetStatus
330 rrm_process_neighbor_report_response(tpAniSirGlobal pMac,
331 				     tDot11fNeighborReportResponse *pNeighborRep,
332 				     tpPESession pSessionEntry)
333 {
334 	tSirRetStatus status = eSIR_FAILURE;
335 	tpSirNeighborReportInd pSmeNeighborRpt = NULL;
336 	uint16_t length;
337 	uint8_t i;
338 	struct scheduler_msg mmhMsg = {0};
339 
340 	if (pNeighborRep == NULL || pSessionEntry == NULL) {
341 		pe_err("Invalid parameters");
342 		return status;
343 	}
344 
345 	pe_debug("Neighbor report response received");
346 
347 	/* Dialog token */
348 	if (pMac->rrm.rrmPEContext.DialogToken !=
349 	    pNeighborRep->DialogToken.token) {
350 		pe_err("Dialog token mismatch in the received Neighbor report");
351 		return eSIR_FAILURE;
352 	}
353 	if (pNeighborRep->num_NeighborReport == 0) {
354 		pe_err("No neighbor report in the frame...Dropping it");
355 		return eSIR_FAILURE;
356 	}
357 	pe_debug("RRM:received num neighbor reports: %d",
358 			pNeighborRep->num_NeighborReport);
359 	if (pNeighborRep->num_NeighborReport > MAX_SUPPORTED_NEIGHBOR_RPT)
360 		pNeighborRep->num_NeighborReport = MAX_SUPPORTED_NEIGHBOR_RPT;
361 	length = (sizeof(tSirNeighborReportInd)) +
362 		 (sizeof(tSirNeighborBssDescription) *
363 		  (pNeighborRep->num_NeighborReport - 1));
364 
365 	/* Prepare the request to send to SME. */
366 	pSmeNeighborRpt = qdf_mem_malloc(length);
367 	if (NULL == pSmeNeighborRpt) {
368 		pe_err("Unable to allocate memory");
369 		return eSIR_MEM_ALLOC_FAILED;
370 	}
371 
372 	/* Allocated memory for pSmeNeighborRpt...will be freed by other module */
373 
374 	for (i = 0; i < pNeighborRep->num_NeighborReport; i++) {
375 		pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof(tSirNeighborBssDescription);        /*+ any optional ies */
376 		qdf_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId,
377 			     pNeighborRep->NeighborReport[i].bssid,
378 			     sizeof(tSirMacAddr));
379 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
380 		fApPreauthReachable =
381 			pNeighborRep->NeighborReport[i].APReachability;
382 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
383 		fSameSecurityMode =
384 			pNeighborRep->NeighborReport[i].Security;
385 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
386 		fSameAuthenticator =
387 			pNeighborRep->NeighborReport[i].KeyScope;
388 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
389 		fCapSpectrumMeasurement =
390 			pNeighborRep->NeighborReport[i].SpecMgmtCap;
391 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
392 		fCapQos = pNeighborRep->NeighborReport[i].QosCap;
393 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
394 		fCapApsd = pNeighborRep->NeighborReport[i].apsd;
395 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
396 		fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm;
397 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
398 		fCapDelayedBlockAck =
399 			pNeighborRep->NeighborReport[i].DelayedBA;
400 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
401 		fCapImmediateBlockAck =
402 			pNeighborRep->NeighborReport[i].ImmBA;
403 		pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
404 		fMobilityDomain =
405 			pNeighborRep->NeighborReport[i].MobilityDomain;
406 
407 		pSmeNeighborRpt->sNeighborBssDescription[i].regClass =
408 			pNeighborRep->NeighborReport[i].regulatoryClass;
409 		pSmeNeighborRpt->sNeighborBssDescription[i].channel =
410 			pNeighborRep->NeighborReport[i].channel;
411 		pSmeNeighborRpt->sNeighborBssDescription[i].phyType =
412 			pNeighborRep->NeighborReport[i].PhyType;
413 	}
414 
415 	pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND;
416 	pSmeNeighborRpt->length = length;
417 	pSmeNeighborRpt->sessionId = pSessionEntry->smeSessionId;
418 	pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport;
419 	qdf_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId,
420 		     sizeof(tSirMacAddr));
421 
422 	/* Send request to SME. */
423 	mmhMsg.type = pSmeNeighborRpt->messageType;
424 	mmhMsg.bodyptr = pSmeNeighborRpt;
425 	MTRACE(mac_trace(pMac, TRACE_CODE_TX_SME_MSG,
426 			 pSessionEntry->peSessionId, mmhMsg.type));
427 	status = lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
428 
429 	return status;
430 
431 }
432 
433 /* -------------------------------------------------------------------- */
434 /**
435  * rrm_process_neighbor_report_req
436  *
437  * FUNCTION:
438  *
439  * LOGIC: Create a Neighbor report request and send it to peer.
440  *
441  * ASSUMPTIONS:
442  *
443  * NOTE:
444  *
445  * @param pNeighborReq Neighbor report request params .
446  * @return None
447  */
448 tSirRetStatus
449 rrm_process_neighbor_report_req(tpAniSirGlobal pMac,
450 				tpSirNeighborReportReqInd pNeighborReq)
451 {
452 	tSirRetStatus status = eSIR_SUCCESS;
453 	tSirMacNeighborReportReq NeighborReportReq;
454 	tpPESession pSessionEntry;
455 	uint8_t sessionId;
456 
457 	if (pNeighborReq == NULL) {
458 		pe_err("NeighborReq is NULL");
459 		return eSIR_FAILURE;
460 	}
461 	pSessionEntry = pe_find_session_by_bssid(pMac, pNeighborReq->bssId,
462 						 &sessionId);
463 	if (pSessionEntry == NULL) {
464 		pe_err("session does not exist for given bssId");
465 		return eSIR_FAILURE;
466 	}
467 
468 	pe_debug("SSID present: %d", pNeighborReq->noSSID);
469 
470 	qdf_mem_set(&NeighborReportReq, sizeof(tSirMacNeighborReportReq), 0);
471 
472 	NeighborReportReq.dialogToken = ++pMac->rrm.rrmPEContext.DialogToken;
473 	NeighborReportReq.ssid_present = !pNeighborReq->noSSID;
474 	if (NeighborReportReq.ssid_present) {
475 		qdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID,
476 			     sizeof(tSirMacSSid));
477 		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
478 				   QDF_TRACE_LEVEL_DEBUG,
479 				   (uint8_t *) NeighborReportReq.ssid.ssId,
480 				   NeighborReportReq.ssid.length);
481 	}
482 
483 	status =
484 		lim_send_neighbor_report_request_frame(pMac, &NeighborReportReq,
485 						       pNeighborReq->bssId,
486 						       pSessionEntry);
487 
488 	return status;
489 }
490 
491 #define ABS(x)      ((x < 0) ? -x : x)
492 /* -------------------------------------------------------------------- */
493 /**
494  * rrm_process_beacon_report_req
495  *
496  * FUNCTION:  Processes the Beacon report request from the peer AP.
497  *
498  * LOGIC:
499  *
500  * ASSUMPTIONS:
501  *
502  * NOTE:
503  *
504  * @param pCurrentReq pointer to the current Req comtext.
505  * @param pBeaconReq pointer to the beacon report request IE from the peer.
506  * @param pSessionEntry session entry.
507  * @return None
508  */
509 static tRrmRetStatus
510 rrm_process_beacon_report_req(tpAniSirGlobal pMac,
511 			      tpRRMReq pCurrentReq,
512 			      tDot11fIEMeasurementRequest *pBeaconReq,
513 			      tpPESession pSessionEntry)
514 {
515 	struct scheduler_msg mmhMsg = {0};
516 	tpSirBeaconReportReqInd pSmeBcnReportReq;
517 	uint8_t num_channels = 0, num_APChanReport;
518 	uint16_t measDuration, maxMeasduration;
519 	int8_t maxDuration;
520 	uint8_t sign;
521 
522 	if (pBeaconReq->measurement_request.Beacon.BeaconReporting.present &&
523 	    (pBeaconReq->measurement_request.Beacon.BeaconReporting.
524 	     reportingCondition != 0)) {
525 		/* Repeated measurement is not supported. This means number of repetitions should be zero.(Already checked) */
526 		/* All test case in VoWifi(as of version 0.36)  use zero for number of repetitions. */
527 		/* Beacon reporting should not be included in request if number of repetitons is zero. */
528 		/* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */
529 
530 		pe_err("Dropping the request: Reporting condition included in beacon report request and it is not zero");
531 		return eRRM_INCAPABLE;
532 	}
533 
534 	/* The logic here is to check the measurement duration passed in the beacon request. Following are the cases handled.
535 	   Case 1: If measurement duration received in the beacon request is greater than the max measurement duration advertised
536 	   in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 1, REFUSE the beacon request
537 	   Case 2: If measurement duration received in the beacon request is greater than the max measurement duration advertised
538 	   in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 0, perform measurement for
539 	   the duration advertised in the RRM capabilities
540 
541 	   maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
542 	 */
543 	maxDuration =
544 		pMac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
545 	sign = (maxDuration < 0) ? 1 : 0;
546 	maxDuration = (1L << ABS(maxDuration));
547 	if (!sign)
548 		maxMeasduration =
549 			maxDuration * pSessionEntry->beaconParams.beaconInterval;
550 	else
551 		maxMeasduration =
552 			pSessionEntry->beaconParams.beaconInterval / maxDuration;
553 
554 	measDuration = pBeaconReq->measurement_request.Beacon.meas_duration;
555 
556 	pe_info("maxDuration = %d sign = %d maxMeasduration = %d measDuration = %d",
557 		maxDuration, sign, maxMeasduration, measDuration);
558 
559 	if (maxMeasduration < measDuration) {
560 		if (pBeaconReq->durationMandatory) {
561 			pe_err("Dropping the request: duration mandatory and maxduration > measduration");
562 			return eRRM_REFUSED;
563 		} else
564 			measDuration = maxMeasduration;
565 	}
566 	/* Cache the data required for sending report. */
567 	pCurrentReq->request.Beacon.reportingDetail =
568 		pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
569 		present ? pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
570 		reportingDetail : BEACON_REPORTING_DETAIL_ALL_FF_IE;
571 
572 	if (pBeaconReq->measurement_request.Beacon.RequestedInfo.present) {
573 		pCurrentReq->request.Beacon.reqIes.pElementIds =
574 			qdf_mem_malloc(sizeof(uint8_t) *
575 				       pBeaconReq->measurement_request.Beacon.
576 				       RequestedInfo.num_requested_eids);
577 		if (NULL == pCurrentReq->request.Beacon.reqIes.pElementIds) {
578 			pe_err("Unable to allocate memory for request IEs buffer");
579 			return eRRM_FAILURE;
580 		}
581 		pCurrentReq->request.Beacon.reqIes.num =
582 			pBeaconReq->measurement_request.Beacon.RequestedInfo.
583 			num_requested_eids;
584 		qdf_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds,
585 			     pBeaconReq->measurement_request.Beacon.
586 			     RequestedInfo.requested_eids,
587 			     pCurrentReq->request.Beacon.reqIes.num);
588 	}
589 
590 	if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) {
591 		for (num_APChanReport = 0;
592 		     num_APChanReport <
593 		     pBeaconReq->measurement_request.Beacon.num_APChannelReport;
594 		     num_APChanReport++)
595 			num_channels +=
596 				pBeaconReq->measurement_request.Beacon.
597 				APChannelReport[num_APChanReport].num_channelList;
598 	}
599 	/* Prepare the request to send to SME. */
600 	pSmeBcnReportReq = qdf_mem_malloc(sizeof(tSirBeaconReportReqInd));
601 	if (NULL == pSmeBcnReportReq) {
602 		pe_err("Unable to allocate memory during Beacon Report Req Ind to SME");
603 		return eRRM_FAILURE;
604 
605 	}
606 
607 	/* Allocated memory for pSmeBcnReportReq....will be freed by other modulea */
608 	qdf_mem_copy(pSmeBcnReportReq->bssId, pSessionEntry->bssId,
609 		     sizeof(tSirMacAddr));
610 	pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND;
611 	pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd);
612 	pSmeBcnReportReq->uDialogToken = pBeaconReq->measurement_token;
613 	pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_11K;
614 	pSmeBcnReportReq->randomizationInterval =
615 		SYS_TU_TO_MS(pBeaconReq->measurement_request.Beacon.randomization);
616 	pSmeBcnReportReq->channelInfo.regulatoryClass =
617 		pBeaconReq->measurement_request.Beacon.regClass;
618 	pSmeBcnReportReq->channelInfo.channelNum =
619 		pBeaconReq->measurement_request.Beacon.channel;
620 	pSmeBcnReportReq->measurementDuration[0] = SYS_TU_TO_MS(measDuration);
621 	pSmeBcnReportReq->fMeasurementtype[0] =
622 		pBeaconReq->measurement_request.Beacon.meas_mode;
623 	qdf_mem_copy(pSmeBcnReportReq->macaddrBssid,
624 		     pBeaconReq->measurement_request.Beacon.BSSID,
625 		     sizeof(tSirMacAddr));
626 
627 	if (pBeaconReq->measurement_request.Beacon.SSID.present) {
628 		pSmeBcnReportReq->ssId.length =
629 			pBeaconReq->measurement_request.Beacon.SSID.num_ssid;
630 		qdf_mem_copy(pSmeBcnReportReq->ssId.ssId,
631 			     pBeaconReq->measurement_request.Beacon.SSID.ssid,
632 			     pSmeBcnReportReq->ssId.length);
633 	}
634 
635 	pCurrentReq->token = pBeaconReq->measurement_token;
636 
637 	pSmeBcnReportReq->channelList.numChannels = num_channels;
638 	if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) {
639 		uint8_t *ch_lst = pSmeBcnReportReq->channelList.channelNumber;
640 		uint8_t len;
641 		uint16_t ch_ctr = 0;
642 		for (num_APChanReport = 0;
643 		     num_APChanReport <
644 		     pBeaconReq->measurement_request.Beacon.num_APChannelReport;
645 		     num_APChanReport++) {
646 			len = pBeaconReq->measurement_request.Beacon.
647 			    APChannelReport[num_APChanReport].num_channelList;
648 			if (ch_ctr + len >
649 			   sizeof(pSmeBcnReportReq->channelList.channelNumber))
650 				break;
651 
652 			qdf_mem_copy(&ch_lst[ch_ctr],
653 				     pBeaconReq->measurement_request.Beacon.
654 				     APChannelReport[num_APChanReport].
655 				     channelList, len);
656 
657 			ch_ctr += len;
658 		}
659 	}
660 	/* Send request to SME. */
661 	mmhMsg.type = eWNI_SME_BEACON_REPORT_REQ_IND;
662 	mmhMsg.bodyptr = pSmeBcnReportReq;
663 	MTRACE(mac_trace(pMac, TRACE_CODE_TX_SME_MSG,
664 			 pSessionEntry->peSessionId, mmhMsg.type));
665 	if (eSIR_SUCCESS != lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT))
666 		return eRRM_FAILURE;
667 	return eRRM_SUCCESS;
668 }
669 
670 /* -------------------------------------------------------------------- */
671 /**
672  * rrm_fill_beacon_ies
673  *
674  * FUNCTION:
675  *
676  * LOGIC: Fills Fixed fields and Ies in bss description to an array of uint8_t.
677  *
678  * ASSUMPTIONS:
679  *
680  * NOTE:
681  *
682  * @param pIes - pointer to the buffer that should be populated with ies.
683  * @param pNumIes - returns the num of ies filled in this param.
684  * @param pIesMaxSize - Max size of the buffer pIes.
685  * @param eids - pointer to array of eids. If NULL, all ies will be populated.
686  * @param numEids - number of elements in array eids.
687  * @param pBssDesc - pointer to Bss Description.
688  * @return None
689  */
690 static void
691 rrm_fill_beacon_ies(tpAniSirGlobal pMac,
692 		    uint8_t *pIes, uint8_t *pNumIes, uint8_t pIesMaxSize,
693 		    uint8_t *eids, uint8_t numEids, tpSirBssDescription pBssDesc)
694 {
695 	uint8_t len, *pBcnIes, count = 0, i;
696 	uint8_t BcnNumIes;
697 
698 	if ((pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL)) {
699 		pe_err("Invalid parameters");
700 		return;
701 	}
702 	/* Make sure that if eid is null, numEids is set to zero. */
703 	numEids = (eids == NULL) ? 0 : numEids;
704 
705 	pBcnIes = (uint8_t *) &pBssDesc->ieFields[0];
706 	BcnNumIes = (uint8_t) GET_IE_LEN_IN_BSS(pBssDesc->length);
707 
708 	*pNumIes = 0;
709 
710 	*((uint32_t *) pIes) = pBssDesc->timeStamp[0];
711 	*pNumIes += sizeof(uint32_t);
712 	pIes += sizeof(uint32_t);
713 	*((uint32_t *) pIes) = pBssDesc->timeStamp[1];
714 	*pNumIes += sizeof(uint32_t);
715 	pIes += sizeof(uint32_t);
716 	*((uint16_t *) pIes) = pBssDesc->beaconInterval;
717 	*pNumIes += sizeof(uint16_t);
718 	pIes += sizeof(uint16_t);
719 	*((uint16_t *) pIes) = pBssDesc->capabilityInfo;
720 	*pNumIes += sizeof(uint16_t);
721 	pIes += sizeof(uint16_t);
722 
723 	while (BcnNumIes > 0) {
724 		len = *(pBcnIes + 1) + 2;       /* element id + length. */
725 		pe_debug("EID = %d, len = %d total = %d",
726 			*pBcnIes, *(pBcnIes + 1), len);
727 
728 		i = 0;
729 		do {
730 			if (((eids == NULL) || (*pBcnIes == eids[i])) &&
731 			    ((*pNumIes) + len) < pIesMaxSize) {
732 				pe_debug("Adding Eid %d, len=%d",
733 					*pBcnIes, len);
734 
735 				qdf_mem_copy(pIes, pBcnIes, len);
736 				pIes += len;
737 				*pNumIes += len;
738 				count++;
739 				break;
740 			}
741 			i++;
742 		} while (i < numEids);
743 
744 		pBcnIes += len;
745 		BcnNumIes -= len;
746 	}
747 	pe_debug("Total length of Ies added = %d", *pNumIes);
748 }
749 
750 /**
751  * rrm_process_beacon_report_xmit() - create a rrm action frame
752  * @mac_ctx: Global pointer to MAC context
753  * @beacon_xmit_ind: Data for beacon report IE from SME.
754  *
755  * Create a Radio measurement report action frame and send it to peer.
756  *
757  * Return: tSirRetStatus
758  */
759 tSirRetStatus
760 rrm_process_beacon_report_xmit(tpAniSirGlobal mac_ctx,
761 			       tpSirBeaconReportXmitInd beacon_xmit_ind)
762 {
763 	tSirRetStatus status = eSIR_SUCCESS;
764 	tSirMacRadioMeasureReport *report = NULL;
765 	tSirMacBeaconReport *beacon_report;
766 	tpSirBssDescription bss_desc;
767 	tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq;
768 	tpPESession session_entry;
769 	uint8_t session_id, counter;
770 	uint8_t bss_desc_count = 0;
771 
772 	pe_debug("Received beacon report xmit indication");
773 
774 	if (NULL == beacon_xmit_ind) {
775 		pe_err("Received beacon_xmit_ind is NULL in PE");
776 		return eSIR_FAILURE;
777 	}
778 
779 	if (NULL == curr_req) {
780 		pe_err("Received report xmit while there is no request pending in PE");
781 		status = eSIR_FAILURE;
782 		goto end;
783 	}
784 
785 	if ((beacon_xmit_ind->numBssDesc) || curr_req->sendEmptyBcnRpt) {
786 		beacon_xmit_ind->numBssDesc = (beacon_xmit_ind->numBssDesc ==
787 			RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT :
788 			beacon_xmit_ind->numBssDesc;
789 
790 		session_entry = pe_find_session_by_bssid(mac_ctx,
791 				beacon_xmit_ind->bssId, &session_id);
792 		if (NULL == session_entry) {
793 			pe_err("session does not exist for given bssId");
794 			status = eSIR_FAILURE;
795 			goto end;
796 		}
797 
798 		report = qdf_mem_malloc(beacon_xmit_ind->numBssDesc *
799 			 sizeof(*report));
800 
801 		if (NULL == report) {
802 			pe_err("RRM Report is NULL, allocation failed");
803 			status = eSIR_MEM_ALLOC_FAILED;
804 			goto end;
805 		}
806 
807 		for (bss_desc_count = 0; bss_desc_count <
808 		     beacon_xmit_ind->numBssDesc; bss_desc_count++) {
809 			beacon_report =
810 				&report[bss_desc_count].report.beaconReport;
811 			/*
812 			 * If the scan result is NULL then send report request
813 			 * with option subelement as NULL.
814 			 */
815 			bss_desc = beacon_xmit_ind->
816 				   pBssDescription[bss_desc_count];
817 			/* Prepare the beacon report and send it to the peer.*/
818 			report[bss_desc_count].token =
819 				beacon_xmit_ind->uDialogToken;
820 			report[bss_desc_count].refused = 0;
821 			report[bss_desc_count].incapable = 0;
822 			report[bss_desc_count].type = SIR_MAC_RRM_BEACON_TYPE;
823 
824 			/*
825 			 * Valid response is included if the size of
826 			 * becon xmit is == size of beacon xmit ind + ies
827 			 */
828 			if (beacon_xmit_ind->length < sizeof(*beacon_xmit_ind))
829 				continue;
830 			beacon_report->regClass = beacon_xmit_ind->regClass;
831 			if (bss_desc) {
832 				beacon_report->channel = bss_desc->channelId;
833 				qdf_mem_copy(beacon_report->measStartTime,
834 					bss_desc->startTSF,
835 					sizeof(bss_desc->startTSF));
836 				beacon_report->measDuration =
837 					SYS_MS_TO_TU(beacon_xmit_ind->duration);
838 				beacon_report->phyType = bss_desc->nwType;
839 				beacon_report->bcnProbeRsp = 1;
840 				beacon_report->rsni = bss_desc->sinr;
841 				beacon_report->rcpi = bss_desc->rssi;
842 				beacon_report->antennaId = 0;
843 				beacon_report->parentTSF = bss_desc->parentTSF;
844 				qdf_mem_copy(beacon_report->bssid,
845 					bss_desc->bssId, sizeof(tSirMacAddr));
846 			}
847 
848 			switch (curr_req->request.Beacon.reportingDetail) {
849 			case BEACON_REPORTING_DETAIL_NO_FF_IE:
850 				/* 0: No need to include any elements. */
851 				pe_debug("No reporting detail requested");
852 				break;
853 			case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE:
854 				/* 1: Include all FFs and Requested Ies. */
855 				pe_debug("Only requested IEs in reporting detail requested");
856 
857 				if (bss_desc) {
858 					rrm_fill_beacon_ies(mac_ctx,
859 					    (uint8_t *) &beacon_report->Ies[0],
860 					    (uint8_t *) &beacon_report->numIes,
861 					    BEACON_REPORT_MAX_IES,
862 					    curr_req->request.Beacon.reqIes.
863 					    pElementIds,
864 					    curr_req->request.Beacon.reqIes.num,
865 					    bss_desc);
866 				}
867 				break;
868 			case BEACON_REPORTING_DETAIL_ALL_FF_IE:
869 				/* 2: default - Include all FFs and all Ies. */
870 			default:
871 				pe_debug("Default all IEs and FFs");
872 				if (bss_desc) {
873 					rrm_fill_beacon_ies(mac_ctx,
874 					    (uint8_t *) &beacon_report->Ies[0],
875 					    (uint8_t *) &beacon_report->numIes,
876 					    BEACON_REPORT_MAX_IES,
877 					    NULL,
878 					    0,
879 					    bss_desc);
880 				}
881 				break;
882 			}
883 		}
884 		pe_info("Sending Action frame with %d bss info",
885 			bss_desc_count);
886 		lim_send_radio_measure_report_action_frame(mac_ctx,
887 			curr_req->dialog_token, bss_desc_count, report,
888 			beacon_xmit_ind->bssId, session_entry);
889 
890 		curr_req->sendEmptyBcnRpt = false;
891 	}
892 
893 end:
894 	for (counter = 0; counter < beacon_xmit_ind->numBssDesc; counter++)
895 		qdf_mem_free(beacon_xmit_ind->pBssDescription[counter]);
896 
897 	if (beacon_xmit_ind->fMeasureDone) {
898 		pe_debug("Measurement done....cleanup the context");
899 		rrm_cleanup(mac_ctx);
900 	}
901 
902 	if (NULL != report)
903 		qdf_mem_free(report);
904 
905 	return status;
906 }
907 
908 static void rrm_process_beacon_request_failure(tpAniSirGlobal pMac,
909 					       tpPESession pSessionEntry,
910 					       tSirMacAddr peer,
911 					       tRrmRetStatus status)
912 {
913 	tpSirMacRadioMeasureReport pReport = NULL;
914 	tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
915 
916 	pReport = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
917 	if (NULL == pReport) {
918 		pe_err("Unable to allocate memory during RRM Req processing");
919 		return;
920 	}
921 	pReport->token = pCurrentReq->token;
922 	pReport->type = SIR_MAC_RRM_BEACON_TYPE;
923 
924 	pe_debug("status %d token %d", status, pReport->token);
925 
926 	switch (status) {
927 	case eRRM_REFUSED:
928 		pReport->refused = 1;
929 		break;
930 	case eRRM_INCAPABLE:
931 		pReport->incapable = 1;
932 		break;
933 	default:
934 		pe_err("Beacon request processing failed no report sent with status %d",
935 			       status);
936 		qdf_mem_free(pReport);
937 		return;
938 	}
939 
940 	lim_send_radio_measure_report_action_frame(pMac, pCurrentReq->dialog_token, 1,
941 						   pReport, peer, pSessionEntry);
942 
943 	qdf_mem_free(pReport);
944 	return;
945 }
946 
947 /**
948  * rrm_process_beacon_req() - Update curr_req and report
949  * @mac_ctx: Global pointer to MAC context
950  * @peer: Macaddress of the peer requesting the radio measurement
951  * @session_entry: session entry
952  * @curr_req: Pointer to RRM request
953  * @report: Pointer to radio measurement report
954  * @rrm_req: Array of Measurement request IEs
955  * @num_report: No.of reports
956  * @index: Index for Measurement request
957  *
958  * Update structure sRRMReq and sSirMacRadioMeasureReport and pass it to
959  * rrm_process_beacon_report_req().
960  *
961  * Return: tSirRetStatus
962  */
963 static
964 tSirRetStatus rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer,
965 			     tpPESession session_entry, tpRRMReq curr_req,
966 			     tpSirMacRadioMeasureReport report,
967 			     tDot11fRadioMeasurementRequest *rrm_req,
968 			     uint8_t *num_report, int index)
969 {
970 	tRrmRetStatus rrm_status = eRRM_SUCCESS;
971 
972 	if (curr_req) {
973 		if (report == NULL) {
974 			/*
975 			 * Allocate memory to send reports for
976 			 * any subsequent requests.
977 			 */
978 			report = qdf_mem_malloc(sizeof(*report) *
979 				(rrm_req->num_MeasurementRequest - index));
980 			if (NULL == report) {
981 				pe_err("Unable to allocate memory during RRM Req processing");
982 				return eSIR_MEM_ALLOC_FAILED;
983 			}
984 			pe_debug("rrm beacon type refused of %d report in beacon table",
985 				*num_report);
986 		}
987 		report[*num_report].refused = 1;
988 		report[*num_report].type = SIR_MAC_RRM_BEACON_TYPE;
989 		report[*num_report].token =
990 			rrm_req->MeasurementRequest[index].measurement_token;
991 		(*num_report)++;
992 		return eSIR_SUCCESS;
993 	} else {
994 		curr_req = qdf_mem_malloc(sizeof(*curr_req));
995 		if (NULL == curr_req) {
996 			pe_err("Unable to allocate memory during RRM Req processing");
997 				qdf_mem_free(report);
998 			return eSIR_MEM_ALLOC_FAILED;
999 		}
1000 		pe_debug("Processing Beacon Report request");
1001 		curr_req->dialog_token = rrm_req->DialogToken.token;
1002 		curr_req->token = rrm_req->
1003 				  MeasurementRequest[index].measurement_token;
1004 		curr_req->sendEmptyBcnRpt = true;
1005 		mac_ctx->rrm.rrmPEContext.pCurrentReq = curr_req;
1006 		rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req,
1007 			&rrm_req->MeasurementRequest[index], session_entry);
1008 		if (eRRM_SUCCESS != rrm_status) {
1009 			rrm_process_beacon_request_failure(mac_ctx,
1010 				session_entry, peer, rrm_status);
1011 			rrm_cleanup(mac_ctx);
1012 		}
1013 	}
1014 	return eSIR_SUCCESS;
1015 }
1016 
1017 /**
1018  * update_rrm_report() - Set incapable bit
1019  * @mac_ctx: Global pointer to MAC context
1020  * @report: Pointer to radio measurement report
1021  * @rrm_req: Array of Measurement request IEs
1022  * @num_report: No.of reports
1023  * @index: Index for Measurement request
1024  *
1025  * Send a report with incapabale bit set
1026  *
1027  * Return: tSirRetStatus
1028  */
1029 static
1030 tSirRetStatus update_rrm_report(tpAniSirGlobal mac_ctx,
1031 				tpSirMacRadioMeasureReport report,
1032 				tDot11fRadioMeasurementRequest *rrm_req,
1033 				uint8_t *num_report, int index)
1034 {
1035 	if (report == NULL) {
1036 		/*
1037 		 * Allocate memory to send reports for
1038 		 * any subsequent requests.
1039 		 */
1040 		report = qdf_mem_malloc(sizeof(*report) *
1041 			 (rrm_req->num_MeasurementRequest - index));
1042 		if (NULL == report) {
1043 			pe_err("Unable to allocate memory during RRM Req processing");
1044 			return eSIR_MEM_ALLOC_FAILED;
1045 		}
1046 		pe_debug("rrm beacon type incapable of %d report",
1047 			*num_report);
1048 	}
1049 	report[*num_report].incapable = 1;
1050 	report[*num_report].type =
1051 		rrm_req->MeasurementRequest[index].measurement_type;
1052 	report[*num_report].token =
1053 		 rrm_req->MeasurementRequest[index].measurement_token;
1054 	(*num_report)++;
1055 	return eSIR_SUCCESS;
1056 }
1057 
1058 /* -------------------------------------------------------------------- */
1059 /**
1060  * rrm_process_radio_measurement_request - Process rrm request
1061  * @mac_ctx: Global pointer to MAC context
1062  * @peer: Macaddress of the peer requesting the radio measurement.
1063  * @rrm_req: Array of Measurement request IEs
1064  * @session_entry: session entry.
1065  *
1066  * Processes the Radio Resource Measurement request.
1067  *
1068  * Return: tSirRetStatus
1069  */
1070 tSirRetStatus
1071 rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx,
1072 				      tSirMacAddr peer,
1073 				      tDot11fRadioMeasurementRequest *rrm_req,
1074 				      tpPESession session_entry)
1075 {
1076 	uint8_t i;
1077 	tSirRetStatus status = eSIR_SUCCESS;
1078 	tpSirMacRadioMeasureReport report = NULL;
1079 	uint8_t num_report = 0;
1080 	tpRRMReq curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq;
1081 
1082 	if (!rrm_req->num_MeasurementRequest) {
1083 		report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
1084 		if (NULL == report) {
1085 			pe_err("Unable to allocate memory during RRM Req processing");
1086 			return eSIR_MEM_ALLOC_FAILED;
1087 		}
1088 		pe_err("No requestIes in the measurement request, sending incapable report");
1089 		report->incapable = 1;
1090 		num_report = 1;
1091 		lim_send_radio_measure_report_action_frame(mac_ctx,
1092 			rrm_req->DialogToken.token, num_report, report, peer,
1093 			session_entry);
1094 		qdf_mem_free(report);
1095 		return eSIR_FAILURE;
1096 	}
1097 	/* PF Fix */
1098 	if (rrm_req->NumOfRepetitions.repetitions > 0) {
1099 		pe_info("number of repetitions %d",
1100 			rrm_req->NumOfRepetitions.repetitions);
1101 		/*
1102 		 * Send a report with incapable bit set.
1103 		 * Not supporting repetitions.
1104 		 */
1105 		report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
1106 		if (NULL == report) {
1107 			pe_err("Unable to allocate memory during RRM Req processing");
1108 			return eSIR_MEM_ALLOC_FAILED;
1109 		}
1110 		report->incapable = 1;
1111 		report->type = rrm_req->MeasurementRequest[0].measurement_type;
1112 		num_report = 1;
1113 		goto end;
1114 	}
1115 
1116 	for (i = 0; i < rrm_req->num_MeasurementRequest; i++) {
1117 		switch (rrm_req->MeasurementRequest[i].measurement_type) {
1118 		case SIR_MAC_RRM_BEACON_TYPE:
1119 			/* Process beacon request. */
1120 			status = rrm_process_beacon_req(mac_ctx, peer,
1121 				 session_entry, curr_req, report, rrm_req,
1122 				 &num_report, i);
1123 			if (eSIR_SUCCESS != status)
1124 				return status;
1125 			break;
1126 		case SIR_MAC_RRM_LCI_TYPE:
1127 		case SIR_MAC_RRM_LOCATION_CIVIC_TYPE:
1128 		case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE:
1129 			pe_debug("RRM with type: %d sent to userspace",
1130 			    rrm_req->MeasurementRequest[i].measurement_type);
1131 			break;
1132 		default:
1133 			/* Send a report with incapabale bit set. */
1134 			status = update_rrm_report(mac_ctx, report, rrm_req,
1135 						   &num_report, i);
1136 			if (eSIR_SUCCESS != status)
1137 				return status;
1138 			break;
1139 		}
1140 	}
1141 
1142 end:
1143 	if (report) {
1144 		lim_send_radio_measure_report_action_frame(mac_ctx,
1145 			rrm_req->DialogToken.token, num_report, report,
1146 			peer, session_entry);
1147 		qdf_mem_free(report);
1148 	}
1149 	return status;
1150 }
1151 
1152 /* -------------------------------------------------------------------- */
1153 /**
1154  * rrm_update_start_tsf
1155  **
1156  * FUNCTION:  Store start TSF of measurement.
1157  *
1158  * LOGIC:
1159  *
1160  * ASSUMPTIONS:
1161  *
1162  * NOTE:
1163  *
1164  * @param startTSF - TSF value at the start of measurement.
1165  * @return None
1166  */
1167 void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2])
1168 {
1169 	pMac->rrm.rrmPEContext.startTSF[0] = startTSF[0];
1170 	pMac->rrm.rrmPEContext.startTSF[1] = startTSF[1];
1171 }
1172 
1173 /* -------------------------------------------------------------------- */
1174 /**
1175  * rrm_get_start_tsf
1176  *
1177  * FUNCTION:  Get the Start TSF.
1178  *
1179  * LOGIC:
1180  *
1181  * ASSUMPTIONS:
1182  *
1183  * NOTE:
1184  *
1185  * @param startTSF - store star TSF in this buffer.
1186  * @return txPower
1187  */
1188 void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF)
1189 {
1190 	pStartTSF[0] = pMac->rrm.rrmPEContext.startTSF[0];
1191 	pStartTSF[1] = pMac->rrm.rrmPEContext.startTSF[1];
1192 
1193 }
1194 
1195 /* -------------------------------------------------------------------- */
1196 /**
1197  * rrm_get_capabilities
1198  *
1199  * FUNCTION:
1200  * Returns a pointer to tpRRMCaps with all the caps enabled in RRM
1201  *
1202  * LOGIC:
1203  *
1204  * ASSUMPTIONS:
1205  *
1206  * NOTE:
1207  *
1208  * @param pSessionEntry
1209  * @return pointer to tRRMCaps
1210  */
1211 tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry)
1212 {
1213 	return &pMac->rrm.rrmPEContext.rrmEnabledCaps;
1214 }
1215 
1216 /* -------------------------------------------------------------------- */
1217 /**
1218  * rrm_initialize
1219  *
1220  * FUNCTION:
1221  * Initialize RRM module
1222  *
1223  * LOGIC:
1224  *
1225  * ASSUMPTIONS:
1226  *
1227  * NOTE:
1228  *
1229  * @return None
1230  */
1231 
1232 tSirRetStatus rrm_initialize(tpAniSirGlobal pMac)
1233 {
1234 	tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps;
1235 
1236 	pMac->rrm.rrmPEContext.pCurrentReq = NULL;
1237 	pMac->rrm.rrmPEContext.txMgmtPower = 0;
1238 	pMac->rrm.rrmPEContext.DialogToken = 0;
1239 
1240 	pMac->rrm.rrmPEContext.rrmEnable = 0;
1241 
1242 	qdf_mem_set(pRRMCaps, sizeof(tRRMCaps), 0);
1243 	pRRMCaps->LinkMeasurement = 1;
1244 	pRRMCaps->NeighborRpt = 1;
1245 	pRRMCaps->BeaconPassive = 1;
1246 	pRRMCaps->BeaconActive = 1;
1247 	pRRMCaps->BeaconTable = 1;
1248 	pRRMCaps->APChanReport = 1;
1249 	pRRMCaps->fine_time_meas_rpt = 1;
1250 	pRRMCaps->lci_capability = 1;
1251 
1252 	pRRMCaps->operatingChanMax = 3;
1253 	pRRMCaps->nonOperatingChanMax = 3;
1254 
1255 	return eSIR_SUCCESS;
1256 }
1257 
1258 /* -------------------------------------------------------------------- */
1259 /**
1260  * rrm_cleanup
1261  *
1262  * FUNCTION:
1263  * cleanup RRM module
1264  *
1265  * LOGIC:
1266  *
1267  * ASSUMPTIONS:
1268  *
1269  * NOTE:
1270  *
1271  * @param mode
1272  * @param rate
1273  * @return None
1274  */
1275 
1276 tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac)
1277 {
1278 	if (pMac->rrm.rrmPEContext.pCurrentReq) {
1279 		if (pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes.
1280 		    pElementIds) {
1281 			qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq->
1282 				     request.Beacon.reqIes.pElementIds);
1283 		}
1284 
1285 		qdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq);
1286 	}
1287 
1288 	pMac->rrm.rrmPEContext.pCurrentReq = NULL;
1289 	return eSIR_SUCCESS;
1290 }
1291 
1292 /**
1293  * lim_update_rrm_capability() - Update PE context's rrm capability
1294  * @mac_ctx: Global pointer to MAC context
1295  * @join_req: Pointer to SME join request.
1296  *
1297  * Update PE context's rrm capability based on SME join request.
1298  *
1299  * Return: None
1300  */
1301 void lim_update_rrm_capability(tpAniSirGlobal mac_ctx,
1302 			       tpSirSmeJoinReq join_req)
1303 {
1304 	mac_ctx->rrm.rrmPEContext.rrmEnable = join_req->rrm_config.rrm_enabled;
1305 	qdf_mem_copy(&mac_ctx->rrm.rrmPEContext.rrmEnabledCaps,
1306 		     &join_req->rrm_config.rm_capability,
1307 		     RMENABLEDCAP_MAX_LEN);
1308 
1309 	return;
1310 }
1311