xref: /wlan-dirver/qcacld-3.0/core/sme/src/rrm/sme_rrm.c (revision eff16d956b6c25bc860fac91ea57d737c47dd7a7)
1 /*
2  * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * DOC: sme_rrm.c
21  *
22  * Implementation for SME RRM APIs
23  */
24 
25 #include "ani_global.h"
26 #include "sme_inside.h"
27 #include "sme_api.h"
28 #include "cfg_api.h"
29 
30 #ifdef FEATURE_WLAN_DIAG_SUPPORT
31 #include "host_diag_core_event.h"
32 #include "host_diag_core_log.h"
33 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
34 
35 #include "csr_inside_api.h"
36 
37 #include "rrm_global.h"
38 #include <wlan_scan_ucfg_api.h>
39 #include <wlan_scan_utils_api.h>
40 #include <wlan_utility.h>
41 
42 /* Roam score for a neighbor AP will be calculated based on the below
43  * definitions. The calculated roam score will be used to select the
44  * roamable candidate from neighbor AP list
45  */
46 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY             0
47 /* When we support 11r over the DS, this should have a non-zero value */
48 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY                 10
49 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE                20
50 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0
51 /* Not used */
52 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS           5
53 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD          3
54 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM           8
55 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA    0
56 /* We dont support delayed BA */
57 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA  3
58 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN          30
59 
60 #ifdef FEATURE_WLAN_ESE
61 #define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST                       30
62 #endif
63 
64 uint64_t rrm_scan_timer;
65 
66 /**
67  * rrm_ll_purge_neighbor_cache() -Purges all the entries in the neighbor cache
68  *
69  * @pMac: Pointer to the Hal Handle.
70  * @pList: Pointer the List that should be purged.
71  *
72  * This function purges all the entries in the neighbor cache and frees up all
73  * the internal nodes
74  *
75  * Return: void
76  */
77 static void rrm_ll_purge_neighbor_cache(tpAniSirGlobal pMac,
78 	tDblLinkList *pList)
79 {
80 	tListElem *pEntry;
81 	tRrmNeighborReportDesc *pNeighborReportDesc;
82 
83 	csr_ll_lock(pList);
84 	while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) {
85 		pNeighborReportDesc =
86 			GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List);
87 		qdf_mem_free(pNeighborReportDesc->pNeighborBssDescription);
88 		qdf_mem_free(pNeighborReportDesc);
89 	}
90 	csr_ll_unlock(pList);
91 }
92 
93 /**
94  * rrm_indicate_neighbor_report_result() -calls the callback registered for
95  *                                                      neighbor report
96  * @pMac: Pointer to the Hal Handle.
97  * @qdf_status - QDF_STATUS_SUCCESS/QDF_STATUS_FAILURE based on whether a valid
98  *                       report is received or neighbor timer expired
99  *
100  * This function calls the callback register by the caller while requesting for
101  * neighbor report. This function gets invoked if a neighbor report is received
102  * from an AP or neighbor response wait timer expires.
103  *
104  * Return: void
105  */
106 static void rrm_indicate_neighbor_report_result(tpAniSirGlobal pMac,
107 						QDF_STATUS qdf_status)
108 {
109 	NeighborReportRspCallback callback;
110 	void *callbackContext;
111 
112 	/* Reset the neighbor response pending status */
113 	pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending =
114 		false;
115 
116 	/* Stop the timer if it is already running.
117 	 *  The timer should be running only in the SUCCESS case.
118 	 */
119 	if (QDF_TIMER_STATE_RUNNING ==
120 	    qdf_mc_timer_get_current_state(&pMac->rrm.rrmSmeContext.
121 					   neighborReqControlInfo.
122 					   neighborRspWaitTimer)) {
123 		sme_debug("No entry in neighbor report cache");
124 		qdf_mc_timer_stop(&pMac->rrm.rrmSmeContext.
125 				  neighborReqControlInfo.neighborRspWaitTimer);
126 	}
127 	callback =
128 		pMac->rrm.rrmSmeContext.neighborReqControlInfo.
129 		neighborRspCallbackInfo.neighborRspCallback;
130 	callbackContext =
131 		pMac->rrm.rrmSmeContext.neighborReqControlInfo.
132 		neighborRspCallbackInfo.neighborRspCallbackContext;
133 
134 	/* Reset the callback and the callback context before calling the
135 	 * callback. It is very likely that there may be a registration in
136 	 * callback itself.
137 	 */
138 	pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.
139 	neighborRspCallback = NULL;
140 	pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.
141 	neighborRspCallbackContext = NULL;
142 
143 	/* Call the callback with the status received from caller */
144 	if (callback)
145 		callback(callbackContext, qdf_status);
146 
147 
148 }
149 
150 /**
151  * sme_RrmBeaconReportXmitInd () - Send beacon report
152  * @mac_ctx  Pointer to mac context
153  * @result_arr scan results
154  * @msrmnt_status flag to indicate that the measurement is done.
155  * @bss_count  bss count
156  *
157  * Create and send the beacon report Xmit ind message to PE.
158  *
159  * Return: status
160  */
161 
162 static QDF_STATUS
163 sme_rrm_send_beacon_report_xmit_ind(tpAniSirGlobal mac_ctx,
164 	tCsrScanResultInfo **result_arr, uint8_t msrmnt_status,
165 	uint8_t bss_count)
166 {
167 	tpSirBssDescription bss_desc = NULL;
168 	tpSirBeaconReportXmitInd beacon_rep;
169 	uint16_t length;
170 	uint32_t size;
171 	uint8_t  i = 0, j = 0, counter = 0;
172 	tCsrScanResultInfo *cur_result = NULL;
173 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
174 	tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext;
175 	tpSirBssDescription bss_desc_to_free[SIR_BCN_REPORT_MAX_BSS_DESC] = {0};
176 
177 	if (NULL == result_arr && !msrmnt_status) {
178 		sme_err("Beacon report xmit Ind to PE Failed");
179 		return QDF_STATUS_E_FAILURE;
180 	}
181 
182 	if (result_arr)
183 		cur_result = result_arr[j];
184 
185 	do {
186 		length = sizeof(tSirBeaconReportXmitInd);
187 		beacon_rep = qdf_mem_malloc(length);
188 		if (NULL == beacon_rep) {
189 			sme_err("Unable to allocate memory for beacon report");
190 			return QDF_STATUS_E_NOMEM;
191 		}
192 		beacon_rep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND;
193 		beacon_rep->length = length;
194 		beacon_rep->uDialogToken = rrm_ctx->token;
195 		beacon_rep->duration = rrm_ctx->duration[0];
196 		beacon_rep->regClass = rrm_ctx->regClass;
197 		qdf_mem_copy(beacon_rep->bssId, rrm_ctx->sessionBssId.bytes,
198 			QDF_MAC_ADDR_SIZE);
199 
200 		i = 0;
201 		while (cur_result) {
202 			bss_desc = &cur_result->BssDescriptor;
203 			if (bss_desc == NULL)
204 				break;
205 			size =  bss_desc->length + sizeof(bss_desc->length);
206 			beacon_rep->pBssDescription[i] = qdf_mem_malloc(size);
207 			if (NULL ==
208 				beacon_rep->pBssDescription[i])
209 				break;
210 			qdf_mem_copy(beacon_rep->pBssDescription[i],
211 				bss_desc, size);
212 			bss_desc_to_free[i] =
213 				beacon_rep->pBssDescription[i];
214 			sme_debug("RRM Result Bssid = " MAC_ADDRESS_STR
215 				" chan= %d, rssi = -%d",
216 				MAC_ADDR_ARRAY(
217 				beacon_rep->pBssDescription[i]->bssId),
218 				beacon_rep->pBssDescription[i]->channelId,
219 				beacon_rep->pBssDescription[i]->rssi * (-1));
220 			beacon_rep->numBssDesc++;
221 			if (++i >= SIR_BCN_REPORT_MAX_BSS_DESC)
222 				break;
223 			cur_result =
224 				result_arr[j + i];
225 		}
226 
227 		j += i;
228 		if (!result_arr || (cur_result == NULL)
229 			|| (j >= bss_count)) {
230 			cur_result = NULL;
231 			sme_debug("Reached to  max/last BSS in cur_result list");
232 		} else {
233 			cur_result = result_arr[j];
234 			sme_debug("Move to the next BSS set in cur_result list");
235 		}
236 		beacon_rep->fMeasureDone =
237 			(cur_result) ? false : msrmnt_status;
238 		sme_debug("SME Sending BcnRepXmit to PE numBss %d i %d j %d",
239 			beacon_rep->numBssDesc, i, j);
240 		status = umac_send_mb_message_to_mac(beacon_rep);
241 		if (status != QDF_STATUS_SUCCESS)
242 			for (counter = 0; counter < i; ++counter)
243 				qdf_mem_free(bss_desc_to_free[counter]);
244 	} while (cur_result);
245 
246 	return status;
247 }
248 
249 #ifdef FEATURE_WLAN_ESE
250 /**
251  * sme_ese_send_beacon_req_scan_results () - Send beacon report
252  * @mac_ctx  Pointer to mac context
253  * @session_id - session id
254  * @result_arr scan results
255  * @msrmnt_status flag to indicate that the measurement is done.
256  * @bss_count  number of bss found
257  *
258  * This function sends up the scan results received as a part of
259  * beacon request scanning.
260  * This function is called after receiving the scan results per channel
261  * Due to the limitation on the size of the IWEVCUSTOM buffer, we send
262  * 3 BSSIDs of beacon report information in one custom event;
263  *
264  * Return: status
265  */
266 static QDF_STATUS sme_ese_send_beacon_req_scan_results(
267 	tpAniSirGlobal mac_ctx, uint32_t session_id,
268 	uint8_t channel, tCsrScanResultInfo **result_arr,
269 	uint8_t msrmnt_status, uint8_t bss_count)
270 {
271 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
272 	QDF_STATUS fill_ie_status;
273 	tpSirBssDescription bss_desc = NULL;
274 	uint32_t ie_len = 0;
275 	uint32_t out_ie_len = 0;
276 	uint8_t bss_counter = 0;
277 	tCsrScanResultInfo *cur_result = NULL;
278 	tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext;
279 	struct csr_roam_info roam_info;
280 	tSirEseBcnReportRsp bcn_rpt_rsp;
281 	tpSirEseBcnReportRsp bcn_report = &bcn_rpt_rsp;
282 	tpCsrEseBeaconReqParams cur_meas_req = NULL;
283 	uint8_t i = 0, j = 0;
284 	tBcnReportFields *bcn_rpt_fields;
285 
286 	if (NULL == rrm_ctx) {
287 		sme_err("rrm_ctx is NULL");
288 		return QDF_STATUS_E_FAILURE;
289 	}
290 
291 	if (NULL == result_arr && !msrmnt_status) {
292 		sme_err("Beacon report xmit Ind to HDD Failed");
293 		return QDF_STATUS_E_FAILURE;
294 	}
295 
296 	if (result_arr)
297 		cur_result = result_arr[bss_counter];
298 
299 	qdf_mem_zero(&bcn_rpt_rsp, sizeof(tSirEseBcnReportRsp));
300 	do {
301 		cur_meas_req = NULL;
302 		for (i = 0; i < rrm_ctx->eseBcnReqInfo.numBcnReqIe; i++) {
303 			if (rrm_ctx->eseBcnReqInfo.bcnReq[i].channel ==
304 				channel) {
305 				cur_meas_req =
306 					&rrm_ctx->eseBcnReqInfo.bcnReq[i];
307 				break;
308 			}
309 		}
310 		if (NULL != cur_meas_req)
311 			bcn_report->measurementToken =
312 				cur_meas_req->measurementToken;
313 		sme_debug("Channel: %d MeasToken: %d", channel,
314 			bcn_report->measurementToken);
315 
316 		j = 0;
317 		while (cur_result) {
318 			bss_desc = &cur_result->BssDescriptor;
319 			if (NULL == bss_desc) {
320 				cur_result = NULL;
321 				break;
322 			}
323 			ie_len = GET_IE_LEN_IN_BSS(bss_desc->length);
324 			bcn_rpt_fields =
325 				&bcn_report->bcnRepBssInfo[j].bcnReportFields;
326 			bcn_rpt_fields->ChanNum =
327 				bss_desc->channelId;
328 			bcn_report->bcnRepBssInfo[j].bcnReportFields.Spare = 0;
329 			if (NULL != cur_meas_req)
330 				bcn_rpt_fields->MeasDuration =
331 					cur_meas_req->measurementDuration;
332 			bcn_rpt_fields->PhyType = bss_desc->nwType;
333 			bcn_rpt_fields->RecvSigPower = bss_desc->rssi;
334 			bcn_rpt_fields->ParentTsf = bss_desc->parentTSF;
335 			bcn_rpt_fields->TargetTsf[0] = bss_desc->timeStamp[0];
336 			bcn_rpt_fields->TargetTsf[1] = bss_desc->timeStamp[1];
337 			bcn_rpt_fields->BcnInterval = bss_desc->beaconInterval;
338 			bcn_rpt_fields->CapabilityInfo =
339 				bss_desc->capabilityInfo;
340 
341 			qdf_mem_copy(bcn_rpt_fields->Bssid,
342 				bss_desc->bssId, sizeof(tSirMacAddr));
343 				fill_ie_status =
344 					sir_beacon_ie_ese_bcn_report(mac_ctx,
345 						(uint8_t *) bss_desc->ieFields,
346 						ie_len,
347 						&(bcn_report->bcnRepBssInfo[j].
348 						pBuf),
349 						&out_ie_len);
350 			if (QDF_STATUS_E_FAILURE == fill_ie_status)
351 				continue;
352 			bcn_report->bcnRepBssInfo[j].ieLen = out_ie_len;
353 
354 			sme_debug("Bssid"MAC_ADDRESS_STR" Channel: %d Rssi: %d",
355 				MAC_ADDR_ARRAY(bss_desc->bssId),
356 				bss_desc->channelId, (-1) * bss_desc->rssi);
357 			bcn_report->numBss++;
358 			if (++j >= SIR_BCN_REPORT_MAX_BSS_DESC)
359 				break;
360 			cur_result = result_arr[j];
361 		}
362 
363 		bss_counter += j;
364 		if (!result_arr || !cur_result
365 		|| (bss_counter >= SIR_BCN_REPORT_MAX_BSS_DESC)) {
366 			cur_result = NULL;
367 			sme_err("Reached to the max/last BSS in cur_result list");
368 		} else {
369 			cur_result = result_arr[bss_counter];
370 			sme_err("Move to the next BSS set in cur_result list");
371 		}
372 
373 		bcn_report->flag =
374 			(msrmnt_status << 1) | ((cur_result) ? true : false);
375 
376 		sme_debug("SME Sending BcnRep to HDD numBss: %d j: %d bss_counter: %d flag: %d",
377 			bcn_report->numBss, j, bss_counter,
378 			bcn_report->flag);
379 
380 		roam_info.pEseBcnReportRsp = bcn_report;
381 		status = csr_roam_call_callback(mac_ctx, session_id, &roam_info,
382 			0, eCSR_ROAM_ESE_BCN_REPORT_IND, 0);
383 
384 		/* Free the memory allocated to IE */
385 		for (i = 0; i < j; i++)
386 			if (bcn_report->bcnRepBssInfo[i].pBuf)
387 				qdf_mem_free(bcn_report->bcnRepBssInfo[i].pBuf);
388 	} while (cur_result);
389 	return status;
390 }
391 
392 #endif /* FEATURE_WLAN_ESE */
393 
394 /**
395  * sme_rrm_send_scan_result() - to get scan result and send the beacon report
396  * @mac_ctx: pointer to mac context
397  * @num_chan: number of channels
398  * @chan_list: list of channels to fetch the result from
399  * @measurementdone: Flag to indicate measurement done or no
400  *
401  * This function is called to get the scan result from CSR and send the beacon
402  * report xmit ind message to PE
403  *
404  * Return: QDF_STATUS
405  */
406 static QDF_STATUS sme_rrm_send_scan_result(tpAniSirGlobal mac_ctx,
407 					   uint8_t num_chan,
408 					   uint8_t *chan_list,
409 					   uint8_t measurementdone)
410 {
411 	mac_handle_t mac_handle = MAC_HANDLE(mac_ctx);
412 	tCsrScanResultFilter filter;
413 	tScanResultHandle result_handle;
414 	tCsrScanResultInfo *scan_results, *next_result;
415 	tCsrScanResultInfo *scanresults_arr[SIR_BCN_REPORT_MAX_BSS_DESC];
416 	QDF_STATUS status;
417 	uint8_t counter = 0;
418 	tpRrmSMEContext rrm_ctx = &mac_ctx->rrm.rrmSmeContext;
419 	uint32_t session_id;
420 	struct csr_roam_info *roam_info;
421 	tSirScanType scan_type;
422 	struct csr_roam_session *session;
423 
424 	qdf_mem_zero(&filter, sizeof(filter));
425 	qdf_mem_zero(scanresults_arr,
426 			sizeof(next_result) * SIR_BCN_REPORT_MAX_BSS_DESC);
427 	filter.BSSIDs.numOfBSSIDs = 1;
428 	filter.BSSIDs.bssid = (struct qdf_mac_addr *)&rrm_ctx->bssId;
429 
430 	if (rrm_ctx->ssId.length) {
431 		filter.SSIDs.SSIDList =
432 			(tCsrSSIDInfo *) qdf_mem_malloc(sizeof(tCsrSSIDInfo));
433 		if (filter.SSIDs.SSIDList == NULL) {
434 			sme_err("qdf_mem_malloc failed");
435 			return QDF_STATUS_E_NOMEM;
436 		}
437 
438 		filter.SSIDs.SSIDList->SSID.length =
439 			rrm_ctx->ssId.length;
440 		qdf_mem_copy(filter.SSIDs.SSIDList->SSID.ssId,
441 				rrm_ctx->ssId.ssId, rrm_ctx->ssId.length);
442 		filter.SSIDs.numOfSSIDs = 1;
443 	} else {
444 		filter.SSIDs.numOfSSIDs = 0;
445 	}
446 
447 	filter.ChannelInfo.numOfChannels = num_chan;
448 	filter.ChannelInfo.ChannelList = chan_list;
449 	filter.fMeasurement = true;
450 
451 	/*
452 	 * In case this is beacon report request from last AP (before roaming)
453 	 * following call to csr_roam_get_session_id_from_bssid will fail,
454 	 * hence use current session ID instead of one stored in SME rrm context
455 	 */
456 	if (QDF_STATUS_E_FAILURE == csr_roam_get_session_id_from_bssid(mac_ctx,
457 			&rrm_ctx->sessionBssId, &session_id)) {
458 		sme_debug("BSSID mismatch, using current session_id");
459 		session_id = mac_ctx->roam.roamSession->sessionId;
460 	}
461 	status = sme_scan_get_result(mac_handle, (uint8_t)session_id,
462 				     &filter, &result_handle);
463 
464 	if (filter.SSIDs.SSIDList)
465 		qdf_mem_free(filter.SSIDs.SSIDList);
466 
467 	sme_debug("RRM Measurement Done %d", measurementdone);
468 	if (NULL == result_handle) {
469 		/*
470 		 * no scan results
471 		 * Spec. doesn't say anything about such condition
472 		 * Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report
473 		 * frame should contain one or more report IEs. It probably
474 		 * means dont send any respose if no matching BSS found.
475 		 * Moreover, there is no flag or field in measurement report
476 		 * IE(7.3.2.22) OR beacon report IE(7.3.2.22.6) that can be set
477 		 * to indicate no BSS found on a given channel. If we finished
478 		 * measurement on all the channels, we still need to send a
479 		 * xmit indication with moreToFollow set to MEASURMENT_DONE so
480 		 * that PE can clean any context allocated.
481 		 */
482 		if (!measurementdone)
483 			return status;
484 #ifdef FEATURE_WLAN_ESE
485 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource)
486 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
487 					session_id, chan_list[0],
488 					NULL, measurementdone, 0);
489 		else
490 #endif /* FEATURE_WLAN_ESE */
491 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
492 					NULL, measurementdone, 0);
493 		return status;
494 	}
495 	scan_results = sme_scan_result_get_first(mac_handle, result_handle);
496 	if (NULL == scan_results && measurementdone) {
497 #ifdef FEATURE_WLAN_ESE
498 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) {
499 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
500 					session_id,
501 					chan_list[0],
502 					NULL,
503 					measurementdone,
504 					0);
505 		} else
506 #endif /* FEATURE_WLAN_ESE */
507 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
508 						NULL, measurementdone, 0);
509 	}
510 	counter = 0;
511 
512 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
513 	if (NULL == roam_info) {
514 		sme_err("malloc failed");
515 		status = QDF_STATUS_E_NOMEM;
516 		goto rrm_send_scan_results_done;
517 	}
518 
519 	session = CSR_GET_SESSION(mac_ctx, session_id);
520 	if ((!session) ||  (!csr_is_conn_state_connected_infra(
521 	    mac_ctx, session_id)) ||
522 	    (NULL == session->pConnectBssDesc)) {
523 		sme_err("Invaild session");
524 		status = QDF_STATUS_E_FAILURE;
525 		goto rrm_send_scan_results_done;
526 	}
527 
528 	if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource ||
529 	    eRRM_MSG_SOURCE_LEGACY_ESE == rrm_ctx->msgSource)
530 		scan_type = rrm_ctx->measMode[rrm_ctx->currentIndex];
531 	else
532 		scan_type = rrm_ctx->measMode[0];
533 
534 	while (scan_results) {
535 		/*
536 		 * In passive scan, sta listens beacon. Connected AP beacon
537 		 * is offloaded to firmware. Firmware will discard
538 		 * connected AP beacon except that special IE exists.
539 		 * Connected AP beacon will not be sent to host. Hence, timer
540 		 * of connected AP in scan results is not updated and can
541 		 * not meet "pScanResult->timer >= RRM_scan_timer".
542 		 */
543 		uint8_t is_conn_bss_found = false;
544 
545 		if ((scan_type == eSIR_PASSIVE_SCAN) &&
546 		     (!qdf_mem_cmp(scan_results->BssDescriptor.bssId,
547 		      session->pConnectBssDesc->bssId,
548 		      sizeof(struct qdf_mac_addr)))) {
549 			is_conn_bss_found = true;
550 			sme_debug("Connected BSS in scan results");
551 		}
552 		next_result = sme_scan_result_get_next(mac_handle,
553 						       result_handle);
554 		sme_debug("Scan res timer:%lu, rrm scan timer:%llu",
555 				scan_results->timer, rrm_scan_timer);
556 		if ((scan_results->timer >= rrm_scan_timer) ||
557 		    (is_conn_bss_found == true)) {
558 			roam_info->pBssDesc = &scan_results->BssDescriptor;
559 			csr_roam_call_callback(mac_ctx, session_id, roam_info,
560 						0, eCSR_ROAM_UPDATE_SCAN_RESULT,
561 						eCSR_ROAM_RESULT_NONE);
562 			scanresults_arr[counter++] = scan_results;
563 		}
564 		scan_results = next_result;
565 		if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC)
566 			break;
567 	}
568 	qdf_mem_free(roam_info);
569 	/*
570 	 * The beacon report should be sent whether the counter is zero or
571 	 * non-zero. There might be a few scan results in the cache but not
572 	 * actually are a result of this scan. During that scenario, the
573 	 * counter will be zero. The report should be sent and LIM will further
574 	 * cleanup the RRM to accept the further incoming requests
575 	 * In case the counter is Zero, the pScanResultsArr will be NULL.
576 	 * The next level routine does a check for the measurementDone to
577 	 * determine whether to send a report or not.
578 	 */
579 	sme_debug("Number of BSS Desc with RRM Scan %d", counter);
580 	if (counter || measurementdone) {
581 #ifdef FEATURE_WLAN_ESE
582 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource)
583 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
584 					session_id, chan_list[0],
585 					scanresults_arr, measurementdone,
586 					counter);
587 		else
588 #endif /* FEATURE_WLAN_ESE */
589 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
590 					scanresults_arr, measurementdone,
591 					counter);
592 	}
593 
594 rrm_send_scan_results_done:
595 	sme_scan_result_purge(result_handle);
596 	return status;
597 }
598 
599 
600 /**
601  * sme_rrm_scan_request_callback() -Sends the beacon report xmit to PE
602  * @halHandle: Pointer to the Hal Handle.
603  * @sessionId: session id
604  * @scanId: Scan ID.
605  * @status: CSR Status.
606  *
607  * The sme module calls this callback function once it finish the scan request
608  * and this function send the beacon report xmit to PE and starts a timer of
609  * random interval to issue next request.
610  *
611  * Return : 0 for success, non zero for failure
612  */
613 static QDF_STATUS sme_rrm_scan_request_callback(tHalHandle halHandle,
614 						uint8_t sessionId,
615 						uint32_t scanId,
616 						eCsrScanStatus status)
617 {
618 	uint16_t interval;
619 	tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle;
620 	tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
621 	uint32_t time_tick;
622 
623 	/* if any more channels are pending, start a timer of a random value
624 	 * within randomization interval.
625 	 */
626 	if ((pSmeRrmContext->currentIndex + 1) <
627 	    pSmeRrmContext->channelList.numOfChannels) {
628 		sme_rrm_send_scan_result(pMac, 1,
629 					 &pSmeRrmContext->channelList.
630 					 ChannelList[pSmeRrmContext
631 					->currentIndex],
632 					 false);
633 		/* Advance the current index. */
634 		pSmeRrmContext->currentIndex++;
635 		/* start the timer to issue next request. */
636 		/* From timer tick get a random number within 10ms and max
637 		 * randmization interval.
638 		 */
639 		time_tick = qdf_mc_timer_get_system_ticks();
640 		interval =
641 			time_tick % (pSmeRrmContext->randnIntvl - 10 + 1) + 10;
642 
643 		sme_debug("Set timer for interval %d ", interval);
644 		qdf_mc_timer_start(&pSmeRrmContext->IterMeasTimer, interval);
645 
646 	} else {
647 		/* Done with the measurement. Clean up all context and send a
648 		 * message to PE with measurement done flag set.
649 		 */
650 		sme_rrm_send_scan_result(pMac, 1,
651 					 &pSmeRrmContext->channelList.
652 					 ChannelList[pSmeRrmContext
653 					->currentIndex],
654 					 true);
655 		qdf_mem_free(pSmeRrmContext->channelList.ChannelList);
656 #ifdef FEATURE_WLAN_ESE
657 		pSmeRrmContext->eseBcnReqInProgress = false;
658 #endif
659 	}
660 
661 	return QDF_STATUS_SUCCESS;
662 }
663 
664 static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev,
665 			struct scan_event *event, void *arg)
666 {
667 	uint32_t scan_id;
668 	uint8_t session_id;
669 	eCsrScanStatus scan_status = eCSR_SCAN_FAILURE;
670 	tHalHandle hal_handle;
671 	bool success = false;
672 	session_id = wlan_vdev_get_id(vdev);
673 	scan_id = event->scan_id;
674 	hal_handle = cds_get_context(QDF_MODULE_ID_SME);
675 	if (!hal_handle) {
676 		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_FATAL,
677 			  FL("invalid h_hal"));
678 		return;
679 	}
680 
681 	qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SME, event->type,
682 		   event->vdev_id, event->scan_id);
683 
684 	if (!util_is_scan_completed(event, &success))
685 		return;
686 
687 	if (success)
688 		scan_status = eCSR_SCAN_SUCCESS;
689 
690 	sme_rrm_scan_request_callback(hal_handle, session_id,
691 					scan_id, scan_status);
692 }
693 
694 
695 /**
696  * sme_rrm_issue_scan_req() - To issue rrm scan request
697  * @mac_ctx: pointer to mac context
698  *
699  * This routine is called to issue rrm scan request
700  *
701  * Return: QDF_STATUS
702  */
703 static QDF_STATUS sme_rrm_issue_scan_req(tpAniSirGlobal mac_ctx)
704 {
705 	QDF_STATUS status = QDF_STATUS_SUCCESS;
706 	tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext;
707 	uint32_t session_id;
708 	tSirScanType scan_type;
709 
710 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
711 			&sme_rrm_ctx->sessionBssId, &session_id);
712 	if (status != QDF_STATUS_SUCCESS) {
713 		sme_err("sme session ID not found for bssid= "MAC_ADDRESS_STR,
714 			MAC_ADDR_ARRAY(sme_rrm_ctx->sessionBssId.bytes));
715 		status = QDF_STATUS_E_FAILURE;
716 		goto free_ch_lst;
717 	}
718 
719 	if ((sme_rrm_ctx->currentIndex) >=
720 			sme_rrm_ctx->channelList.numOfChannels) {
721 		sme_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0);
722 		sme_debug("done with the complete ch lt. finish and fee now");
723 		goto free_ch_lst;
724 	}
725 
726 	if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource ||
727 		eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource)
728 		scan_type = sme_rrm_ctx->measMode[sme_rrm_ctx->currentIndex];
729 	else
730 		scan_type = sme_rrm_ctx->measMode[0];
731 
732 	if ((eSIR_ACTIVE_SCAN == scan_type) ||
733 			(eSIR_PASSIVE_SCAN == scan_type)) {
734 		uint32_t max_chan_time;
735 		uint64_t current_time;
736 		struct scan_start_request *req;
737 		struct wlan_objmgr_vdev *vdev;
738 		uint32_t chan_num;
739 
740 		req = qdf_mem_malloc(sizeof(*req));
741 		if (!req) {
742 			sme_debug("Failed to allocate memory");
743 			return QDF_STATUS_E_NOMEM;
744 		}
745 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
746 						mac_ctx->psoc,
747 						session_id,
748 						WLAN_LEGACY_SME_ID);
749 		if (!vdev) {
750 			sme_err("VDEV is null %d", session_id);
751 			return QDF_STATUS_E_INVAL;
752 		}
753 		ucfg_scan_init_default_params(vdev, req);
754 		req->scan_req.dwell_time_active = 0;
755 		req->scan_req.scan_id = ucfg_scan_get_scan_id(mac_ctx->psoc);
756 		req->scan_req.scan_f_passive =
757 				(scan_type == eSIR_ACTIVE_SCAN) ? false : true;
758 		req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
759 		req->scan_req.scan_req_id = sme_rrm_ctx->req_id;
760 		qdf_mem_copy(&req->scan_req.bssid_list[0], sme_rrm_ctx->bssId,
761 				QDF_MAC_ADDR_SIZE);
762 		req->scan_req.num_bssid = 1;
763 		if (sme_rrm_ctx->ssId.length) {
764 			req->scan_req.num_ssids = 1;
765 			qdf_mem_copy(&req->scan_req.ssid[0].ssid,
766 					sme_rrm_ctx->ssId.ssId,
767 					sme_rrm_ctx->ssId.length);
768 			req->scan_req.ssid[0].length = sme_rrm_ctx->ssId.length;
769 		}
770 
771 		/*
772 		 * set min and max channel time
773 		 * sme_rrm_ctx->duration; Dont use min timeout.
774 		 */
775 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource ||
776 			eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource)
777 			req->scan_req.dwell_time_active = sme_rrm_ctx->duration[
778 						sme_rrm_ctx->currentIndex];
779 		else
780 			req->scan_req.dwell_time_active =
781 						sme_rrm_ctx->duration[0];
782 
783 		sme_debug("Scan Type(%d) Max Dwell Time(%d)",
784 				scan_type,
785 				req->scan_req.dwell_time_active);
786 		/*
787 		 * Use gPassive/gActiveMaxChannelTime if maxChanTime is less
788 		 * than default.
789 		 */
790 		if (eSIR_ACTIVE_SCAN == scan_type)
791 			max_chan_time =
792 				mac_ctx->roam.configParam.nActiveMaxChnTime;
793 		else
794 			max_chan_time =
795 				mac_ctx->roam.configParam.nPassiveMaxChnTime;
796 
797 		if (req->scan_req.dwell_time_active < max_chan_time) {
798 			req->scan_req.dwell_time_active = max_chan_time;
799 			sme_debug("Setting default max %d ChanTime",
800 				max_chan_time);
801 		}
802 
803 		req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
804 		/*
805 		 * For RRM scans timing is very important especially when the
806 		 * request is for limited channels. There is no need for
807 		 * firmware to rest for about 100-200 ms on the home channel.
808 		 * Instead, it can start the scan right away which will make the
809 		 * host to respond with the beacon report as quickly as
810 		 * possible. Ensure that the scan requests are not back to back
811 		 * and hence there is a check to see if the requests are atleast
812 		 * 1 second apart.
813 		 */
814 		current_time = (uint64_t)qdf_mc_timer_get_system_time();
815 		sme_debug("prev scan triggered before %llu ms, totalchannels %d",
816 				current_time - rrm_scan_timer,
817 				sme_rrm_ctx->channelList.numOfChannels);
818 		if ((abs(current_time - rrm_scan_timer) > 1000) &&
819 				(sme_rrm_ctx->channelList.numOfChannels == 1)) {
820 			req->scan_req.max_rest_time = 1;
821 			req->scan_req.min_rest_time = 1;
822 			req->scan_req.idle_time = 1;
823 		}
824 
825 		rrm_scan_timer = (uint64_t)qdf_mc_timer_get_system_time();
826 
827 		/* set requestType to full scan */
828 		req->scan_req.chan_list.num_chan = 1;
829 		chan_num = sme_rrm_ctx->channelList.ChannelList[
830 			   sme_rrm_ctx->currentIndex];
831 		req->scan_req.chan_list.chan[0].freq =
832 			wlan_chan_to_freq(chan_num);
833 		sme_debug("Duration %d On channel %d freq %d",
834 				req->scan_req.dwell_time_active,
835 				chan_num,
836 				req->scan_req.chan_list.chan[0].freq);
837 		status = ucfg_scan_start(req);
838 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
839 
840 		return status;
841 	} else if (eSIR_BEACON_TABLE == scan_type) {
842 		/*
843 		 * In beacon table mode, scan results are taken directly from
844 		 * scan cache without issuing any scan request. So, it is not
845 		 * proper to update rrm_scan_timer with latest time and hence
846 		 * made it to zero to satisfy
847 		 * pScanResult->timer >= rrm_scan_timer
848 		 */
849 		rrm_scan_timer = 0;
850 		if ((sme_rrm_ctx->currentIndex + 1) <
851 			sme_rrm_ctx->channelList.numOfChannels) {
852 			sme_rrm_send_scan_result(mac_ctx, 1,
853 				&sme_rrm_ctx->channelList.ChannelList[
854 					sme_rrm_ctx->currentIndex], false);
855 			/* Advance the current index. */
856 			sme_rrm_ctx->currentIndex++;
857 			sme_rrm_issue_scan_req(mac_ctx);
858 #ifdef FEATURE_WLAN_ESE
859 			sme_rrm_ctx->eseBcnReqInProgress = false;
860 #endif
861 			return status;
862 		} else {
863 			/*
864 			 * Done with the measurement. Clean up all context and
865 			 * send a message to PE with measurement done flag set.
866 			 */
867 			sme_rrm_send_scan_result(mac_ctx, 1,
868 				&sme_rrm_ctx->channelList.ChannelList[
869 					sme_rrm_ctx->currentIndex], true);
870 			goto free_ch_lst;
871 		}
872 	} else {
873 		sme_err("Unknown beacon report req mode(%d)", scan_type);
874 		/*
875 		 * Indicate measurement completion to PE
876 		 * If this is not done, pCurrentReq pointer will not be freed
877 		 * and PE will not handle subsequent Beacon requests
878 		 */
879 		sme_rrm_send_beacon_report_xmit_ind(mac_ctx, NULL, true, 0);
880 		goto free_ch_lst;
881 	}
882 
883 free_ch_lst:
884 	qdf_mem_free(sme_rrm_ctx->channelList.ChannelList);
885 	sme_rrm_ctx->channelList.ChannelList = NULL;
886 	return status;
887 }
888 
889 /**
890  * sme_rrm_process_beacon_report_req_ind() -Process beacon report request
891  * @pMac:- Global Mac structure
892  * @pMsgBuf:- a pointer to a buffer that maps to various structures base
893  *                  on the message type.The beginning of the buffer can always
894  *                  map to tSirSmeRsp.
895  *
896  * This is called to process the Beacon
897  * report request from peer AP forwarded through PE .
898  *
899  * Return : QDF_STATUS_SUCCESS - Validation is successful.
900  */
901 QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac,
902 						void *pMsgBuf)
903 {
904 	tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf;
905 	tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
906 	uint32_t len = 0, i = 0;
907 
908 	sme_debug("Received Beacon report request ind Channel = %d",
909 		pBeaconReq->channelInfo.channelNum);
910 	/* section 11.10.8.1 (IEEE Std 802.11k-2008) */
911 	/* channel 0 and 255 has special meaning. */
912 	if ((pBeaconReq->channelInfo.channelNum == 0) ||
913 	    ((pBeaconReq->channelInfo.channelNum == 255)
914 	     && (pBeaconReq->channelList.numChannels == 0))) {
915 		/* Add all the channel in the regulatory domain. */
916 		wlan_cfg_get_str_len(pMac, WNI_CFG_VALID_CHANNEL_LIST, &len);
917 		pSmeRrmContext->channelList.ChannelList = qdf_mem_malloc(len);
918 		if (pSmeRrmContext->channelList.ChannelList == NULL) {
919 			sme_err("qdf_mem_malloc failed");
920 			return QDF_STATUS_E_NOMEM;
921 		}
922 		csr_get_cfg_valid_channels(pMac, pSmeRrmContext->channelList.
923 					ChannelList, &len);
924 		pSmeRrmContext->channelList.numOfChannels = (uint8_t) len;
925 	} else {
926 		len = 0;
927 		pSmeRrmContext->channelList.numOfChannels = 0;
928 
929 		/* If valid channel is present. We first Measure on the given
930 		 * channel and if there are additional channels present in
931 		 * APchannelreport, measure on these also.
932 		 */
933 		if (pBeaconReq->channelInfo.channelNum != 255)
934 			len = 1;
935 
936 		len += pBeaconReq->channelList.numChannels;
937 
938 		pSmeRrmContext->channelList.ChannelList = qdf_mem_malloc(len);
939 		if (pSmeRrmContext->channelList.ChannelList == NULL) {
940 			sme_err("qdf_mem_malloc failed");
941 			return QDF_STATUS_E_NOMEM;
942 		}
943 
944 		if (pBeaconReq->channelInfo.channelNum != 255) {
945 			if (csr_roam_is_channel_valid
946 				    (pMac, pBeaconReq->channelInfo.channelNum))
947 				pSmeRrmContext->channelList.
948 				ChannelList[pSmeRrmContext->channelList.
949 					    numOfChannels++] =
950 					pBeaconReq->channelInfo.channelNum;
951 			else
952 				sme_err("Invalid channel: %d",
953 					pBeaconReq->channelInfo.channelNum);
954 		}
955 
956 		for (i = 0; i < pBeaconReq->channelList.numChannels; i++) {
957 			if (csr_roam_is_channel_valid(pMac, pBeaconReq->
958 					channelList.channelNumber[i])) {
959 				pSmeRrmContext->channelList.
960 					ChannelList[pSmeRrmContext->channelList.
961 				numOfChannels] = pBeaconReq->channelList.
962 					channelNumber[i];
963 				pSmeRrmContext->channelList.numOfChannels++;
964 			}
965 		}
966 	}
967 
968 	/* Copy session bssid */
969 	qdf_mem_copy(pSmeRrmContext->sessionBssId.bytes, pBeaconReq->bssId,
970 		     sizeof(tSirMacAddr));
971 
972 	/* copy measurement bssid */
973 	qdf_mem_copy(pSmeRrmContext->bssId, pBeaconReq->macaddrBssid,
974 		     sizeof(tSirMacAddr));
975 
976 	/* Copy ssid */
977 	qdf_mem_copy(&pSmeRrmContext->ssId, &pBeaconReq->ssId,
978 		     sizeof(tAniSSID));
979 
980 	pSmeRrmContext->token = pBeaconReq->uDialogToken;
981 	pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass;
982 	pSmeRrmContext->randnIntvl =
983 		QDF_MAX(pBeaconReq->randomizationInterval,
984 			pSmeRrmContext->rrmConfig.max_randn_interval);
985 	pSmeRrmContext->currentIndex = 0;
986 	pSmeRrmContext->msgSource = pBeaconReq->msgSource;
987 	qdf_mem_copy((uint8_t *) &pSmeRrmContext->measMode,
988 		     (uint8_t *) &pBeaconReq->fMeasurementtype,
989 		     SIR_ESE_MAX_MEAS_IE_REQS);
990 	qdf_mem_copy((uint8_t *) &pSmeRrmContext->duration,
991 		     (uint8_t *) &pBeaconReq->measurementDuration,
992 		     SIR_ESE_MAX_MEAS_IE_REQS);
993 
994 	sme_debug("token: %d regClass: %d randnIntvl: %d msgSource: %d",
995 		pSmeRrmContext->token, pSmeRrmContext->regClass,
996 		pSmeRrmContext->randnIntvl, pSmeRrmContext->msgSource);
997 
998 	return sme_rrm_issue_scan_req(pMac);
999 }
1000 
1001 /**
1002  * sme_rrm_neighbor_report_request() - This is API can be used to trigger a
1003  *        Neighbor report from the peer.
1004  * @sessionId: session identifier on which the request should be made.
1005  * @pNeighborReq: a pointer to a neighbor report request.
1006  *
1007  * This is API can be used to trigger a  Neighbor report from the peer.
1008  *
1009  * Return: QDF_STATUS_SUCCESS - Validation is successful.
1010  */
1011 QDF_STATUS sme_rrm_neighbor_report_request(tpAniSirGlobal pMac, uint8_t
1012 					sessionId, tpRrmNeighborReq
1013 					pNeighborReq,
1014 					tpRrmNeighborRspCallbackInfo
1015 					callbackInfo)
1016 {
1017 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1018 	tpSirNeighborReportReqInd pMsg;
1019 	struct csr_roam_session *pSession;
1020 
1021 	sme_debug("Request to send Neighbor report request received ");
1022 	if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
1023 		sme_err("Invalid session %d", sessionId);
1024 		return QDF_STATUS_E_INVAL;
1025 	}
1026 	pSession = CSR_GET_SESSION(pMac, sessionId);
1027 
1028 	/* If already a report is pending, return failure */
1029 	if (true ==
1030 	    pMac->rrm.rrmSmeContext.neighborReqControlInfo.
1031 	    isNeighborRspPending) {
1032 		sme_err("Neighbor request already pending.. Not allowed");
1033 		return QDF_STATUS_E_AGAIN;
1034 	}
1035 
1036 	pMsg = qdf_mem_malloc(sizeof(tSirNeighborReportReqInd));
1037 	if (NULL == pMsg) {
1038 		sme_err("Unable to allocate memory for Neighbor request");
1039 		return QDF_STATUS_E_NOMEM;
1040 	}
1041 
1042 	rrm_ll_purge_neighbor_cache(pMac,
1043 			    &pMac->rrm.rrmSmeContext.neighborReportCache);
1044 
1045 	pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND;
1046 	pMsg->length = sizeof(tSirNeighborReportReqInd);
1047 	qdf_mem_copy(&pMsg->bssId, &pSession->connectedProfile.bssid,
1048 		     sizeof(tSirMacAddr));
1049 	pMsg->noSSID = pNeighborReq->no_ssid;
1050 	qdf_mem_copy(&pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid));
1051 
1052 	status = umac_send_mb_message_to_mac(pMsg);
1053 	if (status != QDF_STATUS_SUCCESS)
1054 		return QDF_STATUS_E_FAILURE;
1055 
1056 	/* Neighbor report request message sent successfully to PE.
1057 	 * Now register the callbacks
1058 	 */
1059 	pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.
1060 	neighborRspCallback = callbackInfo->neighborRspCallback;
1061 	pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.
1062 	neighborRspCallbackContext =
1063 		callbackInfo->neighborRspCallbackContext;
1064 	pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending =
1065 		true;
1066 
1067 	/* Start neighbor response wait timer now */
1068 	qdf_mc_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.
1069 			   neighborRspWaitTimer, callbackInfo->timeout);
1070 
1071 	return QDF_STATUS_SUCCESS;
1072 }
1073 
1074 /**
1075  * rrm_calculate_neighbor_ap_roam_score() - caclulates roam score
1076  * @mac_ctx:                mac global context
1077  * @pNeighborReportDesc:    Neighbor BSS Descriptor node for which roam score
1078  *                          should be calculated
1079  *
1080  * This API is called while handling individual neighbor reports from the APs
1081  * neighbor AP report to calculate the cumulative roam score before storing it
1082  * in neighbor cache.
1083  *
1084  * Return: void
1085  */
1086 static void
1087 rrm_calculate_neighbor_ap_roam_score(tpAniSirGlobal mac_ctx,
1088 				tpRrmNeighborReportDesc nbr_report_desc)
1089 {
1090 	tpSirNeighborBssDescripton nbr_bss_desc;
1091 	uint32_t roam_score = 0;
1092 #ifdef FEATURE_WLAN_ESE
1093 	uint8_t session_id;
1094 #endif
1095 	if (NULL == nbr_report_desc) {
1096 		QDF_ASSERT(0);
1097 		return;
1098 	}
1099 
1100 	if (NULL == nbr_report_desc->pNeighborBssDescription) {
1101 		QDF_ASSERT(0);
1102 		return;
1103 	}
1104 
1105 	nbr_bss_desc = nbr_report_desc->pNeighborBssDescription;
1106 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fMobilityDomain)
1107 		goto check_11r_assoc;
1108 
1109 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN;
1110 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameSecurityMode)
1111 		goto check_11r_assoc;
1112 
1113 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY;
1114 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameAuthenticator)
1115 		goto check_11r_assoc;
1116 
1117 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE;
1118 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fCapRadioMeasurement)
1119 		goto check_11r_assoc;
1120 
1121 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM;
1122 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapSpectrumMeasurement)
1123 		roam_score +=
1124 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT;
1125 
1126 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapQos)
1127 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS;
1128 
1129 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapApsd)
1130 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD;
1131 
1132 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapDelayedBlockAck)
1133 		roam_score +=
1134 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA;
1135 
1136 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapImmediateBlockAck)
1137 		roam_score +=
1138 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA;
1139 
1140 	if (nbr_bss_desc->bssidInfo.rrmInfo.fApPreauthReachable)
1141 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY;
1142 
1143 check_11r_assoc:
1144 #ifdef FEATURE_WLAN_ESE
1145 	session_id = nbr_report_desc->sessionId;
1146 	/* It has come in the report so its the best score */
1147 	if (csr_neighbor_roam_is11r_assoc(mac_ctx, session_id) == false) {
1148 		/* IAPP Route so lets make use of this info save all AP, as the
1149 		 * list does not come all the time. Save and reuse till the next
1150 		 * AP List comes to us. Even save our own MAC address. Will be
1151 		 * useful next time around.
1152 		 */
1153 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST;
1154 	}
1155 #endif
1156 	nbr_report_desc->roamScore = roam_score;
1157 }
1158 
1159 /**
1160  * rrm_store_neighbor_rpt_by_roam_score()-store Neighbor BSS descriptor
1161  * @pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache
1162  *
1163  * This API is called to store a given
1164  * Neighbor BSS descriptor to the neighbor cache. This function
1165  * stores the neighbor BSS descriptors in such a way that descriptors
1166  * are sorted by roamScore in descending order
1167  *
1168  * Return: void.
1169  */
1170 static void rrm_store_neighbor_rpt_by_roam_score(tpAniSirGlobal pMac,
1171 				tpRrmNeighborReportDesc pNeighborReportDesc)
1172 {
1173 	tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
1174 	tListElem *pEntry;
1175 	tRrmNeighborReportDesc *pTempNeighborReportDesc;
1176 
1177 	if (NULL == pNeighborReportDesc) {
1178 		QDF_ASSERT(0);
1179 		return;
1180 	}
1181 	if (NULL == pNeighborReportDesc->pNeighborBssDescription) {
1182 		QDF_ASSERT(0);
1183 		return;
1184 	}
1185 
1186 	if (csr_ll_is_list_empty
1187 		    (&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) {
1188 		sme_err("Neighbor report cache is empty.. Adding a entry now");
1189 		/* Neighbor list cache is empty. Insert this entry
1190 		 * in the tail
1191 		 */
1192 		csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache,
1193 				   &pNeighborReportDesc->List, LL_ACCESS_LOCK);
1194 		return;
1195 	}
1196 	/* Should store the neighbor BSS description in the order
1197 	 * sorted by roamScore in descending order. APs with highest
1198 	 * roamScore should be the 1st entry in the list
1199 	 */
1200 	pEntry = csr_ll_peek_head(&pSmeRrmContext->neighborReportCache,
1201 				LL_ACCESS_LOCK);
1202 	while (pEntry != NULL) {
1203 		pTempNeighborReportDesc = GET_BASE_ADDR(pEntry,
1204 					tRrmNeighborReportDesc, List);
1205 		if (pTempNeighborReportDesc->roamScore <
1206 				pNeighborReportDesc->roamScore)
1207 			break;
1208 		pEntry = csr_ll_next(&pSmeRrmContext->
1209 				neighborReportCache, pEntry, LL_ACCESS_LOCK);
1210 		}
1211 
1212 	if (pEntry)
1213 		/* This BSS roamscore is better than something in the
1214 		 * list. Insert this before that one
1215 		 */
1216 		csr_ll_insert_entry(&pSmeRrmContext->neighborReportCache,
1217 					pEntry, &pNeighborReportDesc->List,
1218 					LL_ACCESS_LOCK);
1219 	else
1220 		/* All the entries in the list has a better roam Score
1221 		 * than this one. Insert this at the last
1222 		 */
1223 		csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache,
1224 					&pNeighborReportDesc->List,
1225 					LL_ACCESS_LOCK);
1226 }
1227 
1228 /**
1229  * sme_rrm_process_neighbor_report() -Process the Neighbor report received
1230  *                                                     from PE
1231  * @pMac - Global MAC structure
1232  * @pMsgBuf - a pointer to a buffer that maps to various structures base
1233  *                  on the message type.
1234  *                  The beginning of the buffer can always map to tSirSmeRsp.
1235  * This is called to process the Neighbor report received from PE.
1236  *
1237  * Return: QDF_STATUS_SUCCESS - Validation is successful
1238  */
1239 static QDF_STATUS sme_rrm_process_neighbor_report(tpAniSirGlobal pMac,
1240 						  void *pMsgBuf)
1241 {
1242 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1243 	tpSirNeighborReportInd pNeighborRpt = (tpSirNeighborReportInd) pMsgBuf;
1244 	tpRrmNeighborReportDesc pNeighborReportDesc;
1245 	uint8_t i = 0;
1246 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1247 	uint32_t sessionId;
1248 
1249 	/* Get the session id */
1250 	status =
1251 		csr_roam_get_session_id_from_bssid(pMac,
1252 			   (struct qdf_mac_addr *) pNeighborRpt->bssId,
1253 			   &sessionId);
1254 	if (QDF_IS_STATUS_SUCCESS(status)) {
1255 #ifdef FEATURE_WLAN_ESE
1256 		/* Clear the cache for ESE. */
1257 		if (csr_roam_is_ese_assoc(pMac, sessionId)) {
1258 			rrm_ll_purge_neighbor_cache(pMac,
1259 						    &pMac->rrm.rrmSmeContext.
1260 						    neighborReportCache);
1261 		}
1262 #endif
1263 	}
1264 
1265 	for (i = 0; i < pNeighborRpt->numNeighborReports; i++) {
1266 		pNeighborReportDesc =
1267 			qdf_mem_malloc(sizeof(tRrmNeighborReportDesc));
1268 		if (NULL == pNeighborReportDesc) {
1269 			sme_err("Failed to alloc memory for RRM report desc");
1270 			status = QDF_STATUS_E_NOMEM;
1271 			goto end;
1272 
1273 		}
1274 
1275 		pNeighborReportDesc->pNeighborBssDescription =
1276 			qdf_mem_malloc(sizeof(tSirNeighborBssDescription));
1277 		if (NULL == pNeighborReportDesc->pNeighborBssDescription) {
1278 			sme_err("Failed to alloc mem for RRM BSS Description");
1279 			qdf_mem_free(pNeighborReportDesc);
1280 			status = QDF_STATUS_E_NOMEM;
1281 			goto end;
1282 		}
1283 		qdf_mem_copy(pNeighborReportDesc->pNeighborBssDescription,
1284 			     &pNeighborRpt->sNeighborBssDescription[i],
1285 			     sizeof(tSirNeighborBssDescription));
1286 
1287 		sme_debug("Received neighbor report with Neighbor BSSID: "
1288 			MAC_ADDRESS_STR,
1289 			MAC_ADDR_ARRAY(
1290 			       pNeighborRpt->sNeighborBssDescription[i].bssId));
1291 
1292 		rrm_calculate_neighbor_ap_roam_score(pMac, pNeighborReportDesc);
1293 
1294 		if (pNeighborReportDesc->roamScore > 0) {
1295 			rrm_store_neighbor_rpt_by_roam_score(pMac,
1296 				     pNeighborReportDesc);
1297 		} else {
1298 			sme_err("Roam score of BSSID  " MAC_ADDRESS_STR
1299 				" is 0, Ignoring..",
1300 				MAC_ADDR_ARRAY(pNeighborRpt->
1301 					       sNeighborBssDescription[i].
1302 					       bssId));
1303 
1304 			qdf_mem_free(
1305 				pNeighborReportDesc->pNeighborBssDescription);
1306 			qdf_mem_free(pNeighborReportDesc);
1307 		}
1308 	}
1309 end:
1310 
1311 	if (!csr_ll_count(&pMac->rrm.rrmSmeContext.neighborReportCache))
1312 		qdf_status = QDF_STATUS_E_FAILURE;
1313 
1314 	rrm_indicate_neighbor_report_result(pMac, qdf_status);
1315 	return status;
1316 }
1317 
1318 /**
1319  * sme_rrm_msg_processor()-Process RRM message
1320  * @pMac - Pointer to the global MAC parameter structure.
1321  * @msg_type - the type of msg passed by PE as defined in wni_api.h
1322  * @pMsgBuf - a pointer to a buffer that maps to various structures base
1323  *                  on the message type.
1324  *                  The beginning of the buffer can always map to tSirSmeRsp.
1325  * sme_process_msg() calls this function for the
1326  * messages that are handled by SME RRM module.
1327  *
1328  * Return: QDF_STATUS_SUCCESS - Validation is successful.
1329  */
1330 QDF_STATUS sme_rrm_msg_processor(tpAniSirGlobal pMac, uint16_t msg_type,
1331 				 void *pMsgBuf)
1332 {
1333 	sme_debug("Msg = %d for RRM measurement", msg_type);
1334 
1335 	/* switch on the msg type & make the state transition accordingly */
1336 	switch (msg_type) {
1337 	case eWNI_SME_NEIGHBOR_REPORT_IND:
1338 		sme_rrm_process_neighbor_report(pMac, pMsgBuf);
1339 		break;
1340 
1341 	case eWNI_SME_BEACON_REPORT_REQ_IND:
1342 		sme_rrm_process_beacon_report_req_ind(pMac, pMsgBuf);
1343 		break;
1344 
1345 	default:
1346 		sme_err("Unknown msg type: %d", msg_type);
1347 		break;
1348 	}
1349 
1350 	return QDF_STATUS_SUCCESS;
1351 }
1352 
1353 /**
1354  * rrm_iter_meas_timer_handle() - Timer handler to handlet the timeout
1355  * @ pMac - The handle returned by mac_open.
1356  *
1357  * Timer handler to handlet the timeout condition when a specific BT
1358  * stop event does not come back, in which case to restore back the
1359  * heartbeat timer.
1360  *
1361  * Return: NULL
1362  */
1363 static void rrm_iter_meas_timer_handle(void *userData)
1364 {
1365 	tpAniSirGlobal pMac = (tpAniSirGlobal) userData;
1366 
1367 	sme_warn("Randomization timer expired...send on next channel");
1368 	/* Issue a scan req for next channel. */
1369 	sme_rrm_issue_scan_req(pMac);
1370 }
1371 /**
1372  * rrm_neighbor_rsp_timeout_handler() - Timer handler to handlet the timeout
1373  * @pMac - The handle returned by mac_open.
1374  *
1375  * Timer handler to handle the timeout condition when a neighbor request is sent
1376  * and no neighbor response is received from the AP
1377  *
1378  * Return: NULL
1379  */
1380 static void rrm_neighbor_rsp_timeout_handler(void *userData)
1381 {
1382 	tpAniSirGlobal pMac = (tpAniSirGlobal) userData;
1383 
1384 	sme_warn("Neighbor Response timed out");
1385 	rrm_indicate_neighbor_report_result(pMac, QDF_STATUS_E_FAILURE);
1386 }
1387 
1388 /**
1389  * rrm_open() - Initialze all RRM module
1390  * @ pMac: The handle returned by mac_open.
1391  *
1392  * Initialze all RRM module.
1393  *
1394  * Return: QDF_STATUS
1395  */
1396 QDF_STATUS rrm_open(tpAniSirGlobal pMac)
1397 {
1398 
1399 	QDF_STATUS qdf_status;
1400 	tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
1401 	QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
1402 
1403 	pSmeRrmContext->rrmConfig.max_randn_interval = 50;        /* ms */
1404 
1405 	qdf_status = qdf_mc_timer_init(&pSmeRrmContext->IterMeasTimer,
1406 				       QDF_TIMER_TYPE_SW,
1407 				       rrm_iter_meas_timer_handle,
1408 					(void *)pMac);
1409 
1410 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1411 		sme_err("Fail to init measurement timer");
1412 		return QDF_STATUS_E_FAILURE;
1413 	}
1414 
1415 	qdf_status =
1416 		qdf_mc_timer_init(&pSmeRrmContext->neighborReqControlInfo.
1417 				  neighborRspWaitTimer, QDF_TIMER_TYPE_SW,
1418 				  rrm_neighbor_rsp_timeout_handler,
1419 					(void *)pMac);
1420 
1421 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1422 		sme_err("Fail to init neighbor rsp wait timer");
1423 		return QDF_STATUS_E_FAILURE;
1424 	}
1425 
1426 	pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = false;
1427 
1428 	qdf_ret_status = csr_ll_open(&pSmeRrmContext->neighborReportCache);
1429 	if (QDF_STATUS_SUCCESS != qdf_ret_status) {
1430 		sme_err("Fail to open neighbor cache result");
1431 		return QDF_STATUS_E_FAILURE;
1432 	}
1433 
1434 	return QDF_STATUS_SUCCESS;
1435 }
1436 
1437 /**
1438  * rrm_close() - Release all RRM modules and their resources.
1439  * @pMac - The handle returned by mac_open.
1440  *
1441  * Release all RRM modules and their resources.
1442  *
1443  * Return: QDF_STATUS
1444  *           QDF_STATUS_E_FAILURE  success
1445  *           QDF_STATUS_SUCCESS  failure
1446  */
1447 
1448 QDF_STATUS rrm_close(tpAniSirGlobal pMac)
1449 {
1450 
1451 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1452 	tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
1453 
1454 	if (QDF_TIMER_STATE_RUNNING ==
1455 	    qdf_mc_timer_get_current_state(&pSmeRrmContext->IterMeasTimer)) {
1456 		qdf_status = qdf_mc_timer_stop(&pSmeRrmContext->IterMeasTimer);
1457 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1458 			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
1459 				  FL("Timer stop fail"));
1460 		}
1461 	}
1462 
1463 	qdf_status = qdf_mc_timer_destroy(&pSmeRrmContext->IterMeasTimer);
1464 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1465 
1466 		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
1467 			  FL("Fail to destroy timer"));
1468 
1469 	}
1470 
1471 	if (QDF_TIMER_STATE_RUNNING ==
1472 	    qdf_mc_timer_get_current_state(&pSmeRrmContext->
1473 					   neighborReqControlInfo.
1474 					   neighborRspWaitTimer)) {
1475 		qdf_status = qdf_mc_timer_stop(&pSmeRrmContext->
1476 					neighborReqControlInfo.
1477 					  neighborRspWaitTimer);
1478 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1479 			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
1480 				  FL("Timer stop fail"));
1481 		}
1482 	}
1483 
1484 	qdf_status =
1485 		qdf_mc_timer_destroy(&pSmeRrmContext->neighborReqControlInfo.
1486 				     neighborRspWaitTimer);
1487 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1488 		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
1489 			  FL("Fail to destroy timer"));
1490 
1491 	}
1492 
1493 	rrm_ll_purge_neighbor_cache(pMac, &pSmeRrmContext->neighborReportCache);
1494 
1495 	csr_ll_close(&pSmeRrmContext->neighborReportCache);
1496 
1497 	return qdf_status;
1498 
1499 }
1500 
1501 /**
1502  * rrm_change_default_config_param() - Changing default config param to new
1503  * @pMac - The handle returned by mac_open.
1504  * param  pRrmConfig - pointer to new rrm configs.
1505  *
1506  * Return: QDF_STATUS
1507  *           QDF_STATUS_SUCCESS  success
1508  */
1509 QDF_STATUS rrm_change_default_config_param(tpAniSirGlobal pMac,
1510 					   struct rrm_config_param *rrm_config)
1511 {
1512 	qdf_mem_copy(&pMac->rrm.rrmSmeContext.rrmConfig, rrm_config,
1513 		     sizeof(struct rrm_config_param));
1514 
1515 	return QDF_STATUS_SUCCESS;
1516 }
1517 
1518 QDF_STATUS rrm_start(tpAniSirGlobal mac_ctx)
1519 {
1520 	tpRrmSMEContext smerrmctx = &mac_ctx->rrm.rrmSmeContext;
1521 
1522 	/* Register with scan component */
1523 	smerrmctx->req_id = ucfg_scan_register_requester(mac_ctx->psoc,
1524 					"RRM",
1525 					sme_rrm_scan_event_callback,
1526 					smerrmctx);
1527 
1528 	return QDF_STATUS_SUCCESS;
1529 }
1530 
1531 QDF_STATUS rrm_stop(tpAniSirGlobal mac_ctx)
1532 {
1533 	tpRrmSMEContext smerrmctx = &mac_ctx->rrm.rrmSmeContext;
1534 
1535 	ucfg_scan_unregister_requester(mac_ctx->psoc, smerrmctx->req_id);
1536 
1537 	return QDF_STATUS_SUCCESS;
1538 }
1539