xref: /wlan-driver/qcacld-3.0/core/sme/src/rrm/sme_rrm.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * DOC: sme_rrm.c
22  *
23  * Implementation for SME RRM APIs
24  */
25 
26 #include "ani_global.h"
27 #include "sme_inside.h"
28 #include "sme_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_api.h>
39 #include <wlan_scan_utils_api.h>
40 #include <wlan_reg_services_api.h>
41 #include <wlan_utility.h>
42 #include <../../core/src/wlan_cm_vdev_api.h>
43 #include "rrm_api.h"
44 #include "wlan_cp_stats_mc_ucfg_api.h"
45 
46 /* Roam score for a neighbor AP will be calculated based on the below
47  * definitions. The calculated roam score will be used to select the
48  * roamable candidate from neighbor AP list
49  */
50 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY             0
51 /* When we support 11r over the DS, this should have a non-zero value */
52 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY                 10
53 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE                20
54 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0
55 /* Not used */
56 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS           5
57 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD          3
58 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM           8
59 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA    0
60 /* We dont support delayed BA */
61 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA  3
62 #define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN          30
63 
64 #ifdef FEATURE_WLAN_ESE
65 #define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST                       30
66 #endif
67 /* RRM SCAN DWELL TIME */
68 #define RRM_SCAN_MIN_DWELL_TIME 20
69 
70 uint64_t rrm_scan_timer;
71 
72 /**
73  * rrm_ll_purge_neighbor_cache() -Purges all the entries in the neighbor cache
74  *
75  * @mac: Pointer to the Hal Handle.
76  * @pList: Pointer the List that should be purged.
77  *
78  * This function purges all the entries in the neighbor cache and frees up all
79  * the internal nodes
80  *
81  * Return: void
82  */
rrm_ll_purge_neighbor_cache(struct mac_context * mac,tDblLinkList * pList)83 static void rrm_ll_purge_neighbor_cache(struct mac_context *mac,
84 	tDblLinkList *pList)
85 {
86 	tListElem *pEntry;
87 	tRrmNeighborReportDesc *pNeighborReportDesc;
88 
89 	csr_ll_lock(pList);
90 	while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) {
91 		pNeighborReportDesc =
92 			GET_BASE_ADDR(pEntry, tRrmNeighborReportDesc, List);
93 		qdf_mem_free(pNeighborReportDesc->pNeighborBssDescription);
94 		qdf_mem_free(pNeighborReportDesc);
95 	}
96 	csr_ll_unlock(pList);
97 }
98 
99 /**
100  * rrm_indicate_neighbor_report_result() -calls the callback registered for
101  *                                                      neighbor report
102  * @mac: Pointer to the Hal Handle.
103  * @qdf_status - QDF_STATUS_SUCCESS/QDF_STATUS_FAILURE based on whether a valid
104  *                       report is received or neighbor timer expired
105  *
106  * This function calls the callback register by the caller while requesting for
107  * neighbor report. This function gets invoked if a neighbor report is received
108  * from an AP or neighbor response wait timer expires.
109  *
110  * Return: void
111  */
rrm_indicate_neighbor_report_result(struct mac_context * mac,QDF_STATUS qdf_status)112 static void rrm_indicate_neighbor_report_result(struct mac_context *mac,
113 						QDF_STATUS qdf_status)
114 {
115 	NeighborReportRspCallback callback;
116 	void *callbackContext;
117 
118 	/* Reset the neighbor response pending status */
119 	mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].
120 	neighborReqControlInfo.isNeighborRspPending = false;
121 
122 	/* Stop the timer if it is already running.
123 	 *  The timer should be running only in the SUCCESS case.
124 	 */
125 	if (QDF_TIMER_STATE_RUNNING ==
126 	    qdf_mc_timer_get_current_state(&mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].
127 					   neighborReqControlInfo.
128 					   neighborRspWaitTimer)) {
129 		sme_debug("No entry in neighbor report cache");
130 		qdf_mc_timer_stop(&mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].
131 				  neighborReqControlInfo.neighborRspWaitTimer);
132 	}
133 	callback =
134 		mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
135 		neighborRspCallbackInfo.neighborRspCallback;
136 	callbackContext =
137 		mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
138 		neighborRspCallbackInfo.neighborRspCallbackContext;
139 
140 	/* Reset the callback and the callback context before calling the
141 	 * callback. It is very likely that there may be a registration in
142 	 * callback itself.
143 	 */
144 	mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
145 		neighborRspCallbackInfo.neighborRspCallback = NULL;
146 	mac->rrm.rrmSmeContext[DEFAULT_RRM_IDX].neighborReqControlInfo.
147 		neighborRspCallbackInfo.neighborRspCallbackContext = NULL;
148 
149 	/* Call the callback with the status received from caller */
150 	if (callback)
151 		callback(callbackContext, qdf_status);
152 }
153 
154 /**
155  * sme_RrmBeaconReportXmitInd () - Send beacon report
156  * @mac_ctx  Pointer to mac context
157  * @measurement_index: Measurement index
158  * @result_arr scan results
159  * @msrmnt_status flag to indicate that the measurement is done.
160  * @bss_count  bss count
161  *
162  * Create and send the beacon report Xmit ind message to PE.
163  *
164  * Return: status
165  */
166 
167 static QDF_STATUS
sme_rrm_send_beacon_report_xmit_ind(struct mac_context * mac_ctx,uint8_t measurement_index,tCsrScanResultInfo ** result_arr,uint8_t msrmnt_status,uint8_t bss_count)168 sme_rrm_send_beacon_report_xmit_ind(struct mac_context *mac_ctx,
169 	uint8_t measurement_index, tCsrScanResultInfo **result_arr,
170 	uint8_t msrmnt_status, uint8_t bss_count)
171 {
172 	struct bss_description *bss_desc = NULL;
173 	tpSirBeaconReportXmitInd beacon_rep;
174 	uint16_t length;
175 	uint32_t size;
176 	uint8_t  i = 0, j = 0, counter = 0;
177 	tCsrScanResultInfo *cur_result = NULL;
178 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
179 	tpRrmSMEContext rrm_ctx =
180 			&mac_ctx->rrm.rrmSmeContext[measurement_index];
181 	struct bss_description *tmp_bss_desc[SIR_BCN_REPORT_MAX_BSS_DESC] = {0};
182 
183 	if (!result_arr && !msrmnt_status) {
184 		sme_err("Beacon report xmit Ind to PE Failed");
185 		return QDF_STATUS_E_FAILURE;
186 	}
187 
188 	if (result_arr)
189 		cur_result = result_arr[j];
190 
191 	do {
192 		length = sizeof(tSirBeaconReportXmitInd);
193 		beacon_rep = qdf_mem_malloc(length);
194 		if (!beacon_rep)
195 			return QDF_STATUS_E_NOMEM;
196 
197 		beacon_rep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND;
198 		beacon_rep->length = length;
199 		beacon_rep->measurement_idx = measurement_index;
200 		beacon_rep->uDialogToken = rrm_ctx->token;
201 		beacon_rep->duration = rrm_ctx->duration[0];
202 		beacon_rep->regClass = rrm_ctx->regClass;
203 		qdf_mem_copy(beacon_rep->bssId, rrm_ctx->sessionBssId.bytes,
204 			QDF_MAC_ADDR_SIZE);
205 
206 		i = 0;
207 		while (cur_result) {
208 			bss_desc = &cur_result->BssDescriptor;
209 			if (!bss_desc)
210 				break;
211 			size =  bss_desc->length + sizeof(bss_desc->length);
212 			beacon_rep->pBssDescription[i] = qdf_mem_malloc(size);
213 			if (NULL ==
214 				beacon_rep->pBssDescription[i])
215 				break;
216 			qdf_mem_copy(beacon_rep->pBssDescription[i],
217 				bss_desc, size);
218 			tmp_bss_desc[i] =
219 				beacon_rep->pBssDescription[i];
220 			sme_debug("RRM Result Bssid = " QDF_MAC_ADDR_FMT
221 				  " freq= %d, rssi = -%d",
222 				  QDF_MAC_ADDR_REF(
223 				  beacon_rep->pBssDescription[i]->bssId),
224 				  beacon_rep->pBssDescription[i]->chan_freq,
225 				  beacon_rep->pBssDescription[i]->rssi * (-1));
226 			beacon_rep->numBssDesc++;
227 			if (++i >= SIR_BCN_REPORT_MAX_BSS_DESC)
228 				break;
229 			if (i + j >= bss_count)
230 				break;
231 			cur_result =
232 				result_arr[j + i];
233 		}
234 
235 		j += i;
236 		if (!result_arr || (!cur_result)
237 			|| (j >= bss_count)) {
238 			cur_result = NULL;
239 			sme_debug("Reached to  max/last BSS in cur_result list");
240 		} else {
241 			cur_result = result_arr[j];
242 			sme_debug("Move to the next BSS set in cur_result list");
243 		}
244 		beacon_rep->fMeasureDone =
245 			(cur_result) ? false : msrmnt_status;
246 		sme_debug("SME Sending BcnRepXmit to PE numBss %d i %d j %d",
247 			beacon_rep->numBssDesc, i, j);
248 		status = umac_send_mb_message_to_mac(beacon_rep);
249 		if (status != QDF_STATUS_SUCCESS)
250 			for (counter = 0; counter < i; ++counter)
251 				qdf_mem_free(tmp_bss_desc[counter]);
252 	} while (cur_result);
253 
254 	return status;
255 }
256 
257 #ifdef FEATURE_WLAN_ESE
258 /**
259  * sme_ese_send_beacon_req_scan_results () - Send beacon report
260  * @mac_ctx: Pointer to mac context
261  * @measurement_index: Measurement request index
262  * @session_id: session id
263  * @freq: channel frequency
264  * @result_arr: scan results
265  * @msrmnt_status: flag to indicate that the measurement is done.
266  * @bss_count:  number of bss found
267  *
268  * This function sends up the scan results received as a part of
269  * beacon request scanning.
270  * This function is called after receiving the scan results per channel
271  * Due to the limitation on the size of the IWEVCUSTOM buffer, we send
272  * 3 BSSIDs of beacon report information in one custom event;
273  *
274  * Return: status
275  */
sme_ese_send_beacon_req_scan_results(struct mac_context * mac_ctx,uint8_t measurement_index,uint32_t session_id,uint32_t freq,tCsrScanResultInfo ** result_arr,uint8_t msrmnt_status,uint8_t bss_count)276 static QDF_STATUS sme_ese_send_beacon_req_scan_results(
277 	struct mac_context *mac_ctx, uint8_t measurement_index,
278 	uint32_t session_id, uint32_t freq,
279 	tCsrScanResultInfo **result_arr,
280 	uint8_t msrmnt_status, uint8_t bss_count)
281 {
282 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
283 	QDF_STATUS fill_ie_status;
284 	struct bss_description *bss_desc = NULL;
285 	uint32_t ie_len = 0;
286 	uint32_t out_ie_len = 0;
287 	uint8_t bss_counter = 0;
288 	tCsrScanResultInfo *cur_result = NULL;
289 	tpRrmSMEContext rrm_ctx =
290 		&mac_ctx->rrm.rrmSmeContext[measurement_index];
291 	struct csr_roam_info *roam_info;
292 	struct ese_bcn_report_rsp bcn_rpt_rsp;
293 	struct ese_bcn_report_rsp *bcn_report = &bcn_rpt_rsp;
294 	tpCsrEseBeaconReqParams cur_meas_req = NULL;
295 	uint8_t i = 0, j = 0;
296 	tBcnReportFields *bcn_rpt_fields;
297 
298 	if (!rrm_ctx) {
299 		sme_err("rrm_ctx is NULL");
300 		return QDF_STATUS_E_FAILURE;
301 	}
302 
303 	if (!result_arr && !msrmnt_status) {
304 		sme_err("Beacon report xmit Ind to HDD Failed");
305 		return QDF_STATUS_E_FAILURE;
306 	}
307 
308 	roam_info = qdf_mem_malloc(sizeof(*roam_info));
309 	if (!roam_info)
310 		return QDF_STATUS_E_NOMEM;
311 
312 	if (result_arr)
313 		cur_result = result_arr[bss_counter];
314 
315 	do {
316 		cur_meas_req = NULL;
317 		/* memset bcn_rpt_rsp for each iteration */
318 		qdf_mem_zero(&bcn_rpt_rsp, sizeof(bcn_rpt_rsp));
319 
320 		for (i = 0; i < rrm_ctx->eseBcnReqInfo.numBcnReqIe; i++) {
321 			if (rrm_ctx->eseBcnReqInfo.bcnReq[i].ch_freq == freq) {
322 				cur_meas_req =
323 					&rrm_ctx->eseBcnReqInfo.bcnReq[i];
324 				break;
325 			}
326 		}
327 		if (cur_meas_req)
328 			bcn_report->measurementToken =
329 				cur_meas_req->measurementToken;
330 		sme_debug("freq: %d MeasToken: %d", freq,
331 			  bcn_report->measurementToken);
332 
333 		j = 0;
334 		while (cur_result) {
335 			bss_desc = &cur_result->BssDescriptor;
336 			if (!bss_desc) {
337 				cur_result = NULL;
338 				break;
339 			}
340 			ie_len = GET_IE_LEN_IN_BSS(bss_desc->length);
341 			bcn_rpt_fields =
342 				&bcn_report->bcnRepBssInfo[j].bcnReportFields;
343 			bcn_rpt_fields->ChanNum = wlan_reg_freq_to_chan(
344 					mac_ctx->pdev,
345 					bss_desc->chan_freq);
346 			bcn_report->bcnRepBssInfo[j].bcnReportFields.Spare = 0;
347 			if (cur_meas_req)
348 				bcn_rpt_fields->MeasDuration =
349 					cur_meas_req->measurementDuration;
350 			bcn_rpt_fields->PhyType = bss_desc->nwType;
351 			bcn_rpt_fields->RecvSigPower = bss_desc->rssi;
352 			bcn_rpt_fields->ParentTsf = bss_desc->parentTSF;
353 			bcn_rpt_fields->TargetTsf[0] = bss_desc->timeStamp[0];
354 			bcn_rpt_fields->TargetTsf[1] = bss_desc->timeStamp[1];
355 			bcn_rpt_fields->BcnInterval = bss_desc->beaconInterval;
356 			bcn_rpt_fields->CapabilityInfo =
357 				bss_desc->capabilityInfo;
358 
359 			qdf_mem_copy(bcn_rpt_fields->Bssid,
360 				bss_desc->bssId, sizeof(tSirMacAddr));
361 				fill_ie_status =
362 					sir_beacon_ie_ese_bcn_report(mac_ctx,
363 						(uint8_t *) bss_desc->ieFields,
364 						ie_len,
365 						&(bcn_report->bcnRepBssInfo[j].
366 						pBuf),
367 						&out_ie_len);
368 			if (QDF_STATUS_E_FAILURE == fill_ie_status)
369 				continue;
370 			bcn_report->bcnRepBssInfo[j].ieLen = out_ie_len;
371 
372 			sme_debug("Bssid"QDF_MAC_ADDR_FMT" Freq:%d Rssi:%d",
373 				  QDF_MAC_ADDR_REF(bss_desc->bssId),
374 				  bss_desc->chan_freq, (-1) * bss_desc->rssi);
375 			bcn_report->numBss++;
376 			if (++j >= SIR_BCN_REPORT_MAX_BSS_DESC)
377 				break;
378 			if ((bss_counter + j) >= bss_count)
379 				break;
380 			cur_result = result_arr[bss_counter + j];
381 		}
382 
383 		bss_counter += j;
384 		if (!result_arr || !cur_result || (bss_counter >= bss_count)) {
385 			cur_result = NULL;
386 			sme_err("Reached to the max/last BSS in cur_result list");
387 		} else {
388 			cur_result = result_arr[bss_counter];
389 			sme_err("Move to the next BSS set in cur_result list");
390 		}
391 
392 		bcn_report->flag =
393 			(msrmnt_status << 1) | ((cur_result) ? true : false);
394 
395 		sme_debug("SME Sending BcnRep to HDD numBss: %d j: %d bss_counter: %d flag: %d",
396 			bcn_report->numBss, j, bss_counter,
397 			bcn_report->flag);
398 
399 		roam_info->pEseBcnReportRsp = bcn_report;
400 		status = csr_roam_call_callback(mac_ctx, session_id, roam_info,
401 						eCSR_ROAM_ESE_BCN_REPORT_IND, 0);
402 
403 		/* Free the memory allocated to IE */
404 		for (i = 0; i < j; i++)
405 			if (bcn_report->bcnRepBssInfo[i].pBuf)
406 				qdf_mem_free(bcn_report->bcnRepBssInfo[i].pBuf);
407 	} while (cur_result);
408 	qdf_mem_free(roam_info);
409 	return status;
410 }
411 
412 static inline
sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)413 void sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)
414 {
415 	if (sme_rrm_ctx)
416 		sme_rrm_ctx->eseBcnReqInProgress = false;
417 }
418 
419 #else
420 
421 static inline
sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)422 void sme_reset_ese_bcn_req_in_progress(tpRrmSMEContext sme_rrm_ctx)
423 {}
424 #endif /* FEATURE_WLAN_ESE */
425 
426 /**
427  * sme_rrm_send_scan_result() - to get scan result and send the beacon report
428  * @mac_ctx: pointer to mac context
429  * @measurement_index: Measurement request number
430  * @num_chan: number of channels
431  * @freq_list: list of channel frequencies to fetch the result from
432  * @measurementdone: Flag to indicate measurement done or no
433  *
434  * This function is called to get the scan result from CSR and send the beacon
435  * report xmit ind message to PE
436  *
437  * Return: QDF_STATUS
438  */
sme_rrm_send_scan_result(struct mac_context * mac_ctx,uint8_t measurement_index,uint8_t num_chan,uint32_t * freq_list,uint8_t measurementdone)439 static QDF_STATUS sme_rrm_send_scan_result(struct mac_context *mac_ctx,
440 					   uint8_t measurement_index,
441 					   uint8_t num_chan,
442 					   uint32_t *freq_list,
443 					   uint8_t measurementdone)
444 {
445 	struct scan_filter *filter;
446 	tScanResultHandle result_handle;
447 	tCsrScanResultInfo *scan_results, *next_result;
448 	tCsrScanResultInfo **scanresults_arr = NULL;
449 	struct scan_result_list *result_list;
450 	QDF_STATUS status;
451 	uint32_t num_scan_results, counter = 0;
452 	tpRrmSMEContext rrm_ctx =
453 		&mac_ctx->rrm.rrmSmeContext[measurement_index];
454 	uint32_t session_id;
455 	tSirScanType scan_type;
456 	struct qdf_mac_addr bss_peer_mac;
457 
458 	filter = qdf_mem_malloc(sizeof(*filter));
459 	if (!filter)
460 		return QDF_STATUS_E_NOMEM;
461 
462 	if (qdf_is_macaddr_zero(filter->bssid_list) ||
463 	    qdf_is_macaddr_group(filter->bssid_list)) {
464 		filter->num_of_bssid = 0;
465 	} else {
466 		/* update filter to get scan result with just target BSSID */
467 		filter->num_of_bssid = 1;
468 		qdf_mem_copy(filter->bssid_list[0].bytes,
469 			     rrm_ctx->bssId, sizeof(struct qdf_mac_addr));
470 	}
471 
472 	if (rrm_ctx->ssId.length) {
473 		filter->num_of_ssid = 1;
474 		filter->ssid_list[0].length = rrm_ctx->ssId.length;
475 		if (filter->ssid_list[0].length > WLAN_SSID_MAX_LEN)
476 			filter->ssid_list[0].length = WLAN_SSID_MAX_LEN;
477 		qdf_mem_copy(filter->ssid_list[0].ssid,
478 			     rrm_ctx->ssId.ssId, filter->ssid_list[0].length);
479 	}
480 
481 	filter->num_of_channels = num_chan;
482 	if (filter->num_of_channels > NUM_CHANNELS)
483 		filter->num_of_channels = NUM_CHANNELS;
484 	qdf_mem_copy(filter->chan_freq_list, freq_list,
485 		     filter->num_of_channels *
486 		     sizeof(filter->chan_freq_list[0]));
487 	filter->rrm_measurement_filter = true;
488 
489 	if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource ||
490 	    eRRM_MSG_SOURCE_LEGACY_ESE == rrm_ctx->msgSource)
491 		scan_type = rrm_ctx->measMode[rrm_ctx->currentIndex];
492 	else
493 		scan_type = rrm_ctx->measMode[0];
494 
495 	if (scan_type == eSIR_BEACON_TABLE)
496 		filter->age_threshold =
497 			wlan_scan_get_aging_time(mac_ctx->psoc);
498 
499 
500 	/*
501 	 * In case this is beacon report request from last AP (before roaming)
502 	 * following call to csr_roam_get_session_id_from_bssid will fail,
503 	 * hence use current session ID instead of one stored in SME rrm context
504 	 */
505 	if (QDF_STATUS_E_FAILURE == csr_roam_get_session_id_from_bssid(mac_ctx,
506 			&rrm_ctx->sessionBssId, &session_id)) {
507 		sme_debug("BSSID mismatch, using current session_id");
508 		session_id = mac_ctx->roam.roamSession->vdev_id;
509 	}
510 	status = csr_scan_get_result(mac_ctx, filter, &result_handle);
511 	qdf_mem_free(filter);
512 
513 	sme_debug("RRM Measurement Done %d for index:%d",
514 		  measurementdone, measurement_index);
515 	if (!result_handle) {
516 		/*
517 		 * no scan results
518 		 * Spec. doesn't say anything about such condition
519 		 * Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report
520 		 * frame should contain one or more report IEs. It probably
521 		 * means dont send any response if no matching BSS found.
522 		 * Moreover, there is no flag or field in measurement report
523 		 * IE(7.3.2.22) OR beacon report IE(7.3.2.22.6) that can be set
524 		 * to indicate no BSS found on a given channel. If we finished
525 		 * measurement on all the channels, we still need to send a
526 		 * xmit indication with moreToFollow set to MEASURMENT_DONE so
527 		 * that PE can clean any context allocated.
528 		 */
529 		if (!measurementdone)
530 			return status;
531 #ifdef FEATURE_WLAN_ESE
532 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource)
533 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
534 					measurement_index, session_id,
535 					freq_list[0], NULL,
536 					measurementdone, 0);
537 		else
538 #endif /* FEATURE_WLAN_ESE */
539 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
540 							measurement_index, NULL,
541 							measurementdone, 0);
542 		return status;
543 	}
544 	scan_results = csr_scan_result_get_first(mac_ctx, result_handle);
545 	if (!scan_results && measurementdone) {
546 #ifdef FEATURE_WLAN_ESE
547 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource) {
548 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
549 					measurement_index, session_id,
550 					freq_list[0], NULL,
551 					measurementdone, 0);
552 		} else
553 #endif /* FEATURE_WLAN_ESE */
554 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
555 						measurement_index,
556 						NULL, measurementdone, 0);
557 	}
558 
559 	result_list = (struct scan_result_list *)result_handle;
560 	num_scan_results = csr_ll_count(&result_list->List);
561 	if (!num_scan_results) {
562 		sme_err("num_scan_results is %d", num_scan_results);
563 		status = QDF_STATUS_E_FAILURE;
564 		goto rrm_send_scan_results_done;
565 	}
566 
567 	sme_debug("num_scan_results %d", num_scan_results);
568 	scanresults_arr = qdf_mem_malloc(num_scan_results *
569 					 sizeof(next_result));
570 	if (!scanresults_arr) {
571 		status = QDF_STATUS_E_NOMEM;
572 		goto send_scan_results;
573 	}
574 
575 	status = wlan_mlme_get_bssid_vdev_id(mac_ctx->pdev, session_id,
576 					     &bss_peer_mac);
577 	if (QDF_IS_STATUS_ERROR(status)) {
578 		sme_err("BSSID not found for vdev: %d", session_id);
579 		status = QDF_STATUS_E_FAILURE;
580 		goto send_scan_results;
581 	}
582 
583 	if (!cm_is_vdevid_connected(mac_ctx->pdev, session_id)) {
584 		sme_err("vdev:%d is not connected", session_id);
585 		status = QDF_STATUS_E_FAILURE;
586 		goto send_scan_results;
587 	}
588 
589 	while (scan_results) {
590 		/*
591 		 * Connected AP beacon is offloaded to firmware.
592 		 * Firmware will discard connected AP beacon except that
593 		 * special IE exists Connected AP beacon will not be sent
594 		 * to host. Hence, timer of connected AP in scan results is
595 		 * not updated and can not meet
596 		 * "pScanResult->timer >= RRM_scan_timer".
597 		 */
598 		uint8_t is_conn_bss_found = false;
599 		uint8_t is_nontx_of_conn_bss = false;
600 
601 		if (!qdf_mem_cmp(scan_results->BssDescriptor.bssId,
602 				 bss_peer_mac.bytes,
603 		    sizeof(struct qdf_mac_addr))) {
604 			is_conn_bss_found = true;
605 			sme_debug("Connected BSS in scan results");
606 		}
607 		if (scan_results->BssDescriptor.mbssid_info.profile_num) {
608 			if (!qdf_mem_cmp(scan_results->BssDescriptor.
609 					 mbssid_info.trans_bssid,
610 					 bss_peer_mac.bytes,
611 					 QDF_MAC_ADDR_SIZE)) {
612 				is_nontx_of_conn_bss = true;
613 				sme_debug("Non Tx BSS of Conn AP in results");
614 			}
615 		}
616 		next_result = csr_scan_result_get_next(mac_ctx,
617 						       result_handle);
618 		sme_debug("Scan res timer:%lu, rrm scan timer:%llu",
619 				scan_results->timer, rrm_scan_timer);
620 		if ((scan_results->timer >= rrm_scan_timer) ||
621 		    (is_conn_bss_found == true) || is_nontx_of_conn_bss)
622 			scanresults_arr[counter++] = scan_results;
623 		scan_results = next_result;
624 		if (counter >= num_scan_results)
625 			break;
626 	}
627 
628 send_scan_results:
629 	/*
630 	 * The beacon report should be sent whether the counter is zero or
631 	 * non-zero. There might be a few scan results in the cache but not
632 	 * actually are a result of this scan. During that scenario, the
633 	 * counter will be zero. The report should be sent and LIM will further
634 	 * cleanup the RRM to accept the further incoming requests
635 	 * In case the counter is Zero, the pScanResultsArr will be NULL.
636 	 * The next level routine does a check for the measurementDone to
637 	 * determine whether to send a report or not.
638 	 */
639 	sme_debug("Number of BSS Desc with RRM Scan %d", counter);
640 	if (counter || measurementdone) {
641 #ifdef FEATURE_WLAN_ESE
642 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == rrm_ctx->msgSource)
643 			status = sme_ese_send_beacon_req_scan_results(mac_ctx,
644 					measurement_index, session_id,
645 					freq_list[0], scanresults_arr,
646 					measurementdone, counter);
647 		else
648 #endif /* FEATURE_WLAN_ESE */
649 			status = sme_rrm_send_beacon_report_xmit_ind(mac_ctx,
650 					measurement_index, scanresults_arr,
651 					measurementdone, counter);
652 	}
653 
654 rrm_send_scan_results_done:
655 	if (scanresults_arr)
656 		qdf_mem_free(scanresults_arr);
657 	csr_scan_result_purge(mac_ctx, result_handle);
658 
659 	return status;
660 }
661 
662 /**
663  * sme_rrm_scan_request_callback() -Sends the beacon report xmit to PE
664  * @mac_handle: Opaque handle to the MAC context
665  * @pSmeRrmContext: SME rrm context for measurement request
666  * @sessionId: session id
667  * @scanId: Scan ID.
668  * @status: CSR Status.
669  *
670  * The sme module calls this callback function once it finish the scan request
671  * and this function send the beacon report xmit to PE and starts a timer of
672  * random interval to issue next request.
673  *
674  * Return : 0 for success, non zero for failure
675  */
sme_rrm_scan_request_callback(struct mac_context * mac,tpRrmSMEContext pSmeRrmContext,uint8_t sessionId,uint32_t scanId,eCsrScanStatus status)676 static QDF_STATUS sme_rrm_scan_request_callback(struct mac_context *mac,
677 						tpRrmSMEContext pSmeRrmContext,
678 						uint8_t sessionId,
679 						uint32_t scanId,
680 						eCsrScanStatus status)
681 {
682 	uint8_t num_chan;
683 	uint32_t *freq_list;
684 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
685 
686 	/*
687 	 * Even if RRM scan response is received after roaming to different AP
688 	 * the messege shall be posted to PE for rrm cleanup.
689 	 */
690 
691 	freq_list = pSmeRrmContext->channelList.freq_list;
692 	if (!freq_list) {
693 		sme_err("[802.11 RRM]: Global freq list is null");
694 		pSmeRrmContext->channelList.numOfChannels = 0;
695 		qdf_status = QDF_STATUS_E_FAILURE;
696 		goto end;
697 	}
698 	/* Sending the beacon report xmit for the all the valid channel
699 	 * scan results within randomization interval.
700 	 */
701 	num_chan = pSmeRrmContext->channelList.numOfChannels;
702 	sme_rrm_send_scan_result(mac, pSmeRrmContext->measurement_idx,
703 				 num_chan, &freq_list[0], true);
704 
705 	/* Clean up all context and send a
706 	 * message to PE with measurement done flag set.
707 	 */
708 	qdf_mem_free(pSmeRrmContext->channelList.freq_list);
709 	pSmeRrmContext->channelList.freq_list = NULL;
710 end:
711 	pSmeRrmContext->channelList.numOfChannels = 0;
712 	sme_reset_ese_bcn_req_in_progress(pSmeRrmContext);
713 
714 	return qdf_status;
715 }
716 
717 /**
718  * sme_rrm_send_chan_load_report_xmit_ind() -Sends the chan load report xmit
719  * to PE
720  * @mac: global mac context
721  * @rrm_sme_ctx: SME rrm context for measurement request
722  * @vdev_id: vdev id
723  * @is_report_success: need to send failure report or not
724  *
725  * The sme module calls this function once it finish the scan request
726  * and this function send the chan load report xmit to PE.
727  *
728  * Return : None
729  */
730 static void
sme_rrm_send_chan_load_report_xmit_ind(struct mac_context * mac,tpRrmSMEContext rrm_sme_ctx,uint8_t vdev_id,bool is_report_success)731 sme_rrm_send_chan_load_report_xmit_ind(struct mac_context *mac,
732 				       tpRrmSMEContext rrm_sme_ctx,
733 				       uint8_t vdev_id,
734 				       bool is_report_success)
735 {
736 	uint8_t measurement_index = rrm_sme_ctx->measurement_idx;
737 	struct chan_load_xmit_ind *chan_load_resp;
738 	uint16_t length;
739 	tpRrmSMEContext rrm_ctx = &mac->rrm.rrmSmeContext[measurement_index];
740 	const struct bonded_channel_freq *range;
741 	uint8_t chan_load = 0, temp_chan_load;
742 	qdf_freq_t start_freq, end_freq, op_freq;
743 	enum phy_ch_width req_chan_width;
744 
745 	length = sizeof(struct chan_load_xmit_ind);
746 	chan_load_resp = qdf_mem_malloc(length);
747 	if (!chan_load_resp)
748 		return;
749 
750 	chan_load_resp->messageType = eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND;
751 	chan_load_resp->is_report_success = is_report_success;
752 	chan_load_resp->length = length;
753 	chan_load_resp->measurement_idx = measurement_index;
754 	chan_load_resp->dialog_token = rrm_ctx->token;
755 	chan_load_resp->duration = rrm_ctx->duration[0];
756 	chan_load_resp->op_class = rrm_ctx->regClass;
757 	chan_load_resp->channel = rrm_ctx->chan_load_req_info.channel;
758 	chan_load_resp->rrm_scan_tsf = rrm_ctx->chan_load_req_info.rrm_scan_tsf;
759 
760 	op_freq = rrm_ctx->chan_load_req_info.req_freq;
761 	req_chan_width = rrm_ctx->chan_load_req_info.req_chan_width;
762 	if (req_chan_width == CH_WIDTH_INVALID) {
763 		sme_debug("Invalid scanned_ch_width");
764 		return;
765 	}
766 
767 	if (req_chan_width == CH_WIDTH_20MHZ) {
768 		start_freq = op_freq;
769 		end_freq = op_freq;
770 		sme_debug("cw %d: start_freq %d, end_freq %d", req_chan_width,
771 			  start_freq, end_freq);
772 	} else if (req_chan_width == CH_WIDTH_320MHZ) {
773 		if (!rrm_ctx->chan_load_req_info.bw_ind.is_bw_ind_element) {
774 			sme_debug("is_bw_ind_element is false");
775 			return;
776 		}
777 
778 		qdf_mem_copy(&chan_load_resp->bw_ind,
779 			     &rrm_ctx->chan_load_req_info.bw_ind,
780 			     sizeof(chan_load_resp->bw_ind));
781 		range = wlan_reg_get_bonded_chan_entry(op_freq,
782 			  rrm_ctx->chan_load_req_info.bw_ind.channel_width,
783 			  rrm_ctx->chan_load_req_info.bw_ind.center_freq);
784 		if (!range) {
785 			sme_debug("vdev %d : range is null for freq %d",
786 				  vdev_id, op_freq);
787 			return;
788 		}
789 
790 		start_freq = range->start_freq;
791 		end_freq = range->end_freq;
792 		sme_debug("cw %d: start_freq %d, end_freq %d", req_chan_width,
793 			  start_freq, end_freq);
794 	} else {
795 		if (rrm_ctx->chan_load_req_info.wide_bw.is_wide_bw_chan_switch) {
796 			qdf_mem_copy(&chan_load_resp->wide_bw,
797 				     &rrm_ctx->chan_load_req_info.wide_bw,
798 				     sizeof(chan_load_resp->wide_bw));
799 			req_chan_width =
800 			    rrm_ctx->chan_load_req_info.wide_bw.channel_width;
801 			sme_debug("Fill wide_bw_chan_switch IE for cw:%d",
802 				  req_chan_width);
803 		}
804 
805 		range =
806 		   wlan_reg_get_bonded_chan_entry(op_freq, req_chan_width, 0);
807 		if (!range) {
808 			sme_debug("range is NULL for freq %d, ch_width %d",
809 				  op_freq, req_chan_width);
810 			return;
811 		}
812 		start_freq = range->start_freq;
813 		end_freq = range->end_freq;
814 		sme_debug("cw %d: start_freq %d, end_freq %d",
815 			  req_chan_width, start_freq, end_freq);
816 	}
817 
818 	for (; start_freq <= end_freq;) {
819 		temp_chan_load =
820 			wlan_cp_stats_get_rx_clear_count(mac->psoc,
821 							 vdev_id,
822 							 start_freq);
823 		if (chan_load < temp_chan_load)
824 			chan_load = temp_chan_load;
825 
826 		start_freq += BW_20_MHZ;
827 	}
828 
829 	chan_load_resp->chan_load = chan_load;
830 
831 	sme_debug("SME Sending CHAN_LOAD_REPORT_RESP_XMIT_IND to PE");
832 	umac_send_mb_message_to_mac(chan_load_resp);
833 }
834 
sme_rrm_scan_event_callback(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)835 static void sme_rrm_scan_event_callback(struct wlan_objmgr_vdev *vdev,
836 			struct scan_event *event, void *arg)
837 {
838 	struct mac_context *mac_ctx;
839 	uint32_t scan_id;
840 	uint8_t vdev_id, i;
841 	eCsrScanStatus scan_status = eCSR_SCAN_FAILURE;
842 	bool success = false;
843 	tpRrmSMEContext smerrmctx;
844 
845 	mac_ctx = (struct mac_context *)arg;
846 	if (!mac_ctx) {
847 		sme_err("invalid mac_ctx");
848 		return;
849 	}
850 
851 	vdev_id = wlan_vdev_get_id(vdev);
852 	scan_id = event->scan_id;
853 
854 	qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SME, event->type,
855 		   event->vdev_id, event->scan_id);
856 
857 	if (!util_is_scan_completed(event, &success))
858 		return;
859 
860 	if (success)
861 		scan_status = eCSR_SCAN_SUCCESS;
862 
863 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
864 		smerrmctx = &mac_ctx->rrm.rrmSmeContext[i];
865 		if (smerrmctx->scan_id == scan_id)
866 			break;
867 
868 		if (i == (MAX_MEASUREMENT_REQUEST - 1))
869 			return;
870 	}
871 
872 	sme_debug("vdev: %d : Scan completed for scan_id:%d idx:%d, type:%d",
873 		  vdev_id, scan_id, smerrmctx->measurement_idx,
874 		  smerrmctx->measurement_type);
875 
876 	switch (smerrmctx->measurement_type) {
877 	case RRM_CHANNEL_LOAD:
878 		sme_rrm_send_chan_load_report_xmit_ind(mac_ctx, smerrmctx,
879 						       vdev_id, true);
880 		break;
881 	case RRM_BEACON_REPORT:
882 		sme_rrm_scan_request_callback(mac_ctx, smerrmctx, vdev_id,
883 					      scan_id, scan_status);
884 		break;
885 	default:
886 		sme_err("Unknown measurement_type: %d",
887 			smerrmctx->measurement_type);
888 		break;
889 	}
890 }
891 
892 #define RRM_CHAN_WEIGHT_CHAR_LEN 5
893 #define RRM_MAX_CHAN_TO_PRINT 39
894 
sme_rrm_issue_scan_req(struct mac_context * mac_ctx,uint8_t idx)895 QDF_STATUS sme_rrm_issue_scan_req(struct mac_context *mac_ctx, uint8_t idx)
896 {
897 	QDF_STATUS status = QDF_STATUS_SUCCESS;
898 	tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext[idx];
899 	uint32_t session_id;
900 	tSirScanType scan_type;
901 	uint8_t ch_idx;
902 	uint32_t *freq_list;
903 
904 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
905 			&sme_rrm_ctx->sessionBssId, &session_id);
906 	if (status != QDF_STATUS_SUCCESS) {
907 		sme_err("sme session ID not found for bssid= "QDF_MAC_ADDR_FMT,
908 			QDF_MAC_ADDR_REF(sme_rrm_ctx->sessionBssId.bytes));
909 		status = QDF_STATUS_E_FAILURE;
910 		goto send_ind;
911 	}
912 
913 	if ((sme_rrm_ctx->currentIndex) >=
914 			sme_rrm_ctx->channelList.numOfChannels) {
915 		sme_rrm_send_beacon_report_xmit_ind(mac_ctx, idx, NULL,
916 						    true, 0);
917 		sme_debug("done with the complete ch lt. finish and fee now");
918 		goto free_ch_lst;
919 	}
920 
921 	if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource ||
922 		eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource)
923 		scan_type = sme_rrm_ctx->measMode[sme_rrm_ctx->currentIndex];
924 	else
925 		scan_type = sme_rrm_ctx->measMode[0];
926 
927 	if ((eSIR_ACTIVE_SCAN == scan_type) ||
928 	    (eSIR_PASSIVE_SCAN == scan_type)) {
929 		uint32_t max_chan_time, buff_len, buff_num = 0, chan_count = 0;
930 		uint64_t current_time;
931 		struct scan_start_request *req;
932 		struct wlan_objmgr_vdev *vdev;
933 		uint16_t i;
934 		char *chan_buff = NULL;
935 
936 		if (!sme_rrm_ctx->channelList.numOfChannels ||
937 		    !sme_rrm_ctx->channelList.freq_list) {
938 			sme_err("[802.11 RRM]: Global freq list is null");
939 			status = QDF_STATUS_E_FAILURE;
940 			goto send_ind;
941 		}
942 
943 		req = qdf_mem_malloc(sizeof(*req));
944 		if (!req) {
945 			status = QDF_STATUS_E_NOMEM;
946 			goto send_ind;
947 		}
948 
949 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
950 						mac_ctx->psoc,
951 						session_id,
952 						WLAN_LEGACY_SME_ID);
953 		if (!vdev) {
954 			sme_err("VDEV is null %d", session_id);
955 			status = QDF_STATUS_E_INVAL;
956 			qdf_mem_free(req);
957 			goto send_ind;
958 		}
959 		wlan_scan_init_default_params(vdev, req);
960 		req->scan_req.scan_id = wlan_scan_get_scan_id(mac_ctx->psoc);
961 		sme_rrm_ctx->scan_id = req->scan_req.scan_id;
962 
963 		sme_debug("RRM_SCN: rrm_idx:%d scan_id:%d",
964 			  sme_rrm_ctx->measurement_idx, sme_rrm_ctx->scan_id);
965 		req->scan_req.scan_f_passive =
966 				(scan_type == eSIR_ACTIVE_SCAN) ? false : true;
967 		req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
968 		req->scan_req.scan_req_id = sme_rrm_ctx->req_id;
969 		qdf_mem_copy(&req->scan_req.bssid_list[0], sme_rrm_ctx->bssId,
970 				QDF_MAC_ADDR_SIZE);
971 		req->scan_req.num_bssid = 1;
972 		if (sme_rrm_ctx->ssId.length) {
973 			req->scan_req.num_ssids = 1;
974 			qdf_mem_copy(&req->scan_req.ssid[0].ssid,
975 					sme_rrm_ctx->ssId.ssId,
976 					sme_rrm_ctx->ssId.length);
977 			req->scan_req.ssid[0].length = sme_rrm_ctx->ssId.length;
978 		}
979 
980 		/*
981 		 * set min and max channel time
982 		 * sme_rrm_ctx->duration; Dont use min timeout.
983 		 */
984 		if (eRRM_MSG_SOURCE_ESE_UPLOAD == sme_rrm_ctx->msgSource ||
985 			eRRM_MSG_SOURCE_LEGACY_ESE == sme_rrm_ctx->msgSource)
986 			max_chan_time =
987 			      sme_rrm_ctx->duration[sme_rrm_ctx->currentIndex];
988 		else
989 			max_chan_time = sme_rrm_ctx->duration[0];
990 
991 		/*
992 		 * Use max_chan_time if max_chan_time is more than def value
993 		 * depending on type of scan.
994 		 */
995 		if (req->scan_req.scan_f_passive) {
996 			if (max_chan_time >= RRM_SCAN_MIN_DWELL_TIME) {
997 				req->scan_req.dwell_time_passive =
998 								max_chan_time;
999 				req->scan_req.dwell_time_passive_6g =
1000 								max_chan_time;
1001 			}
1002 			sme_debug("Passive Max Dwell Time(%d)",
1003 				  req->scan_req.dwell_time_passive);
1004 		} else {
1005 			if (max_chan_time >= RRM_SCAN_MIN_DWELL_TIME) {
1006 				req->scan_req.dwell_time_active = max_chan_time;
1007 				req->scan_req.dwell_time_active_2g =
1008 								max_chan_time;
1009 				req->scan_req.dwell_time_active_6g =
1010 								max_chan_time;
1011 			}
1012 			sme_debug("Active Max Dwell Time(%d) 2G Dwell time %d",
1013 				  req->scan_req.dwell_time_active,
1014 				  req->scan_req.dwell_time_active_2g);
1015 		}
1016 
1017 		req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
1018 		/*
1019 		 * For RRM scans timing is very important especially when the
1020 		 * request is for limited channels. There is no need for
1021 		 * firmware to rest for about 100-200 ms on the home channel.
1022 		 * Instead, it can start the scan right away which will make the
1023 		 * host to respond with the beacon report as quickly as
1024 		 * possible. Ensure that the scan requests are not back to back
1025 		 * and hence there is a check to see if the requests are atleast
1026 		 * 1 second apart.
1027 		 */
1028 		current_time = (uint64_t)qdf_mc_timer_get_system_time();
1029 		sme_debug("prev scan triggered before %llu ms, totalchannels %d",
1030 				current_time - rrm_scan_timer,
1031 				sme_rrm_ctx->channelList.numOfChannels);
1032 		if ((abs(current_time - rrm_scan_timer) > 1000) &&
1033 				(sme_rrm_ctx->channelList.numOfChannels == 1)) {
1034 			req->scan_req.max_rest_time = 1;
1035 			req->scan_req.min_rest_time = 1;
1036 			req->scan_req.idle_time = 1;
1037 		}
1038 
1039 		rrm_scan_timer = (uint64_t)qdf_mc_timer_get_system_time();
1040 
1041 		/* set requestType to full scan */
1042 		req->scan_req.chan_list.num_chan =
1043 			sme_rrm_ctx->channelList.numOfChannels;
1044 		buff_len = (QDF_MIN(req->scan_req.chan_list.num_chan,
1045 			    RRM_MAX_CHAN_TO_PRINT) * RRM_CHAN_WEIGHT_CHAR_LEN)
1046 			    + 1;
1047 		chan_buff = qdf_mem_malloc(buff_len);
1048 		if (!chan_buff) {
1049 			status = QDF_STATUS_E_NOMEM;
1050 			goto send_ind;
1051 		}
1052 		sme_debug("Number of chan %d active duration %d passive %d",
1053 			  req->scan_req.chan_list.num_chan,
1054 			  req->scan_req.dwell_time_active,
1055 			  req->scan_req.dwell_time_passive);
1056 
1057 		for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
1058 			req->scan_req.chan_list.chan[i].freq =
1059 			    (qdf_freq_t)sme_rrm_ctx->channelList.freq_list[i];
1060 			buff_num += qdf_scnprintf(chan_buff + buff_num,
1061 						  buff_len - buff_num, " %d",
1062 						  req->scan_req.chan_list.chan[i].freq);
1063 			chan_count++;
1064 			if (chan_count >= RRM_MAX_CHAN_TO_PRINT) {
1065 				sme_debug("RRM Scan Req for channels: %s",
1066 					  chan_buff);
1067 				buff_num = 0;
1068 				chan_count = 0;
1069 			}
1070 		}
1071 		if (buff_num)
1072 			sme_debug("RRM Freq scan req channels: %s", chan_buff);
1073 		qdf_mem_free(chan_buff);
1074 		/*
1075 		 * Fill RRM scan type for these requests. This is done
1076 		 * because in scan concurrency update params we update the
1077 		 * dwell time active which was not the expectation.
1078 		 * So doing a check of RRM scan request, we would not
1079 		 * update the dwell time.
1080 		 */
1081 		req->scan_req.scan_type = SCAN_TYPE_RRM;
1082 
1083 		status = wlan_scan_start(req);
1084 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1085 		if (QDF_IS_STATUS_ERROR(status))
1086 			goto send_ind;
1087 
1088 		return status;
1089 	} else if (eSIR_BEACON_TABLE == scan_type) {
1090 		/*
1091 		 * In beacon table mode, scan results are taken directly from
1092 		 * scan cache without issuing any scan request. So, it is not
1093 		 * proper to update rrm_scan_timer with latest time and hence
1094 		 * made it to zero to satisfy
1095 		 * pScanResult->timer >= rrm_scan_timer
1096 		 */
1097 		rrm_scan_timer = 0;
1098 		freq_list = sme_rrm_ctx->channelList.freq_list;
1099 		if (!freq_list) {
1100 			sme_err("[802.11 RRM]: Global freq list is null");
1101 			sme_reset_ese_bcn_req_in_progress(sme_rrm_ctx);
1102 			status = QDF_STATUS_E_FAILURE;
1103 			goto send_ind;
1104 		}
1105 
1106 		ch_idx = sme_rrm_ctx->currentIndex;
1107 		for (; ch_idx < sme_rrm_ctx->channelList.numOfChannels; ch_idx++) {
1108 			if ((ch_idx + 1) <
1109 			    sme_rrm_ctx->channelList.numOfChannels) {
1110 				sme_rrm_send_scan_result(mac_ctx, idx, 1,
1111 							 &freq_list[ch_idx],
1112 							 false);
1113 				/* Advance the current index. */
1114 				sme_rrm_ctx->currentIndex++;
1115 			} else {
1116 				/*
1117 				 * Done with the measurement. Clean up all
1118 				 * context and send a message to PE with
1119 				 * measurement done flag set.
1120 				 */
1121 				sme_rrm_send_scan_result(mac_ctx, idx, 1,
1122 							 &freq_list[ch_idx],
1123 							 true);
1124 				sme_reset_ese_bcn_req_in_progress(sme_rrm_ctx);
1125 				goto free_ch_lst;
1126 			}
1127 		}
1128 	}
1129 
1130 	sme_err("Unknown beacon report req mode(%d)", scan_type);
1131 	/*
1132 	 * Indicate measurement completion to PE
1133 	 * If this is not done, pCurrentReq pointer will not be freed
1134 	 * and PE will not handle subsequent Beacon requests
1135 	 */
1136 send_ind:
1137 	sme_rrm_send_beacon_report_xmit_ind(mac_ctx, idx, NULL, true, 0);
1138 free_ch_lst:
1139 	qdf_mem_free(sme_rrm_ctx->channelList.freq_list);
1140 	sme_rrm_ctx->channelList.freq_list = NULL;
1141 	sme_rrm_ctx->channelList.numOfChannels = 0;
1142 	return status;
1143 }
1144 
sme_rrm_fill_scan_channels(struct mac_context * mac,uint8_t * country,tpRrmSMEContext sme_rrm_context,uint8_t op_class,uint32_t num_channels)1145 static QDF_STATUS sme_rrm_fill_scan_channels(struct mac_context *mac,
1146 					     uint8_t *country,
1147 					     tpRrmSMEContext sme_rrm_context,
1148 					     uint8_t op_class,
1149 					     uint32_t num_channels)
1150 {
1151 	uint32_t num_chan = 0;
1152 	uint32_t i;
1153 	uint32_t *freq_list;
1154 	bool found;
1155 
1156 	freq_list = sme_rrm_context->channelList.freq_list;
1157 	found = false;
1158 	for (i = 0; i < num_channels; i++) {
1159 		found = wlan_reg_is_freq_in_country_opclass(mac->pdev,
1160 							    country,
1161 							    op_class,
1162 							    freq_list[i]);
1163 		if (found) {
1164 			freq_list[num_chan] = freq_list[i];
1165 			num_chan++;
1166 		}
1167 		found = false;
1168 	}
1169 
1170 	sme_rrm_context->channelList.numOfChannels = num_chan;
1171 	if (sme_rrm_context->channelList.numOfChannels == 0) {
1172 		qdf_mem_free(sme_rrm_context->channelList.freq_list);
1173 		sme_rrm_context->channelList.freq_list = NULL;
1174 		sme_err_rl("No channels populated with requested operation class and current country, Hence abort the rrm operation");
1175 		return QDF_STATUS_E_FAILURE;
1176 	}
1177 
1178 	return QDF_STATUS_SUCCESS;
1179 }
1180 
sme_rrm_get_meas_mode_string(uint8_t meas_mode)1181 static uint8_t *sme_rrm_get_meas_mode_string(uint8_t meas_mode)
1182 {
1183 	switch (meas_mode) {
1184 		CASE_RETURN_STRING(eSIR_PASSIVE_SCAN);
1185 		CASE_RETURN_STRING(eSIR_ACTIVE_SCAN);
1186 		CASE_RETURN_STRING(eSIR_BEACON_TABLE);
1187 	default:
1188 		return (uint8_t *)"UNKNOWN";
1189 		break;
1190 	}
1191 }
1192 
1193 /**
1194  * sme_rrm_fill_freq_list_for_channel_load() : Trigger wide band scan request
1195  * to measure channel load
1196  * @mac_ctx: global mac structure
1197  * @sme_rrm_ctx: pointer to sme rrm context structure
1198  * @vdev: vdev common object
1199  * @req: scan request config
1200  *
1201  * Return : QDF_STATUS
1202  */
1203 static QDF_STATUS
sme_rrm_fill_freq_list_for_channel_load(struct mac_context * mac_ctx,tpRrmSMEContext sme_rrm_ctx,struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)1204 sme_rrm_fill_freq_list_for_channel_load(struct mac_context *mac_ctx,
1205 					tpRrmSMEContext sme_rrm_ctx,
1206 					struct wlan_objmgr_vdev *vdev,
1207 					struct scan_start_request *req)
1208 {
1209 	struct bw_ind_element *bw_ind;
1210 	struct wide_bw_chan_switch *wide_bw;
1211 	uint16_t c_space = 0;
1212 	uint8_t country_code[REG_ALPHA2_LEN + 1];
1213 	enum phy_ch_width chan_width = CH_WIDTH_INVALID;
1214 	qdf_freq_t scan_freq;
1215 	uint8_t channel = sme_rrm_ctx->chan_load_req_info.channel;
1216 	qdf_freq_t cen320_freq = 0;
1217 
1218 	rrm_get_country_code_from_connected_profile(mac_ctx,
1219 						    wlan_vdev_get_id(vdev),
1220 						    country_code);
1221 	scan_freq = wlan_reg_country_chan_opclass_to_freq(mac_ctx->pdev,
1222 							  country_code,
1223 							  channel,
1224 							  sme_rrm_ctx->regClass,
1225 							  false);
1226 	if (!scan_freq) {
1227 		sme_debug("invalid scan freq");
1228 		return QDF_STATUS_E_INVAL;
1229 	}
1230 
1231 	bw_ind = &sme_rrm_ctx->chan_load_req_info.bw_ind;
1232 	wide_bw = &sme_rrm_ctx->chan_load_req_info.wide_bw;
1233 	if (!bw_ind->is_bw_ind_element && !wide_bw->is_wide_bw_chan_switch) {
1234 		if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
1235 					      sme_rrm_ctx->regClass))
1236 			c_space =
1237 			    wlan_reg_get_op_class_width(mac_ctx->pdev,
1238 							sme_rrm_ctx->regClass,
1239 							true);
1240 		else
1241 			c_space = wlan_reg_dmn_get_chanwidth_from_opclass_auto(
1242 							country_code,
1243 							channel,
1244 							sme_rrm_ctx->regClass);
1245 
1246 		sme_debug("op: %d, ch: %d freq:%d, cc %c%c 0x%x, c_space:%d",
1247 			  sme_rrm_ctx->regClass, channel, scan_freq,
1248 			  country_code[0], country_code[1], country_code[2],
1249 			  c_space);
1250 
1251 		switch (c_space) {
1252 		case 320:
1253 			fallthrough;
1254 		case 160:
1255 			chan_width = CH_WIDTH_160MHZ;
1256 			break;
1257 		case 80:
1258 			chan_width = CH_WIDTH_80MHZ;
1259 			break;
1260 		case 40:
1261 			chan_width = CH_WIDTH_40MHZ;
1262 			break;
1263 		case 20:
1264 		case 25:
1265 			chan_width = CH_WIDTH_20MHZ;
1266 			break;
1267 		default:
1268 			sme_err("invalid chan_space: %d", c_space);
1269 			return QDF_STATUS_E_FAILURE;
1270 		}
1271 	} else {
1272 		if (bw_ind->is_bw_ind_element) {
1273 			chan_width = bw_ind->channel_width;
1274 			cen320_freq = bw_ind->center_freq;
1275 		}
1276 
1277 		if (wide_bw->is_wide_bw_chan_switch)
1278 			chan_width = wide_bw->channel_width;
1279 	}
1280 
1281 	sme_rrm_ctx->chan_load_req_info.req_chan_width = chan_width;
1282 	return mlme_update_freq_in_scan_start_req(vdev, req, chan_width,
1283 						  scan_freq, cen320_freq);
1284 }
1285 
1286 /**
1287  * sme_rrm_issue_chan_load_measurement_scan() : Trigger wide band scan request
1288  * to measure channel load
1289  * @mac_ctx: global mac structure
1290  * @idx: measurement request index
1291  *
1292  * Return : QDF_STATUS
1293  */
1294 static QDF_STATUS
sme_rrm_issue_chan_load_measurement_scan(struct mac_context * mac_ctx,uint8_t idx)1295 sme_rrm_issue_chan_load_measurement_scan(struct mac_context *mac_ctx,
1296 					 uint8_t idx)
1297 {
1298 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1299 	tpRrmSMEContext sme_rrm_ctx = &mac_ctx->rrm.rrmSmeContext[idx];
1300 	uint32_t max_chan_time;
1301 	struct scan_start_request *req;
1302 	struct wlan_objmgr_vdev *vdev;
1303 	uint32_t vdev_id;
1304 
1305 	status = csr_roam_get_session_id_from_bssid(mac_ctx,
1306 						    &sme_rrm_ctx->sessionBssId,
1307 						    &vdev_id);
1308 	if (QDF_IS_STATUS_ERROR(status)) {
1309 		sme_err("sme session ID not found for bssid "QDF_MAC_ADDR_FMT"",
1310 			QDF_MAC_ADDR_REF(sme_rrm_ctx->sessionBssId.bytes));
1311 		goto send_ind;
1312 	}
1313 
1314 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id,
1315 						    WLAN_LEGACY_SME_ID);
1316 	if (!vdev) {
1317 		sme_err("VDEV is null %d", vdev_id);
1318 		status = QDF_STATUS_E_INVAL;
1319 		goto send_ind;
1320 	}
1321 
1322 	req = qdf_mem_malloc(sizeof(*req));
1323 	if (!req) {
1324 		status = QDF_STATUS_E_NOMEM;
1325 		goto error_handle;
1326 	}
1327 
1328 	status = wlan_scan_init_default_params(vdev, req);
1329 	if (QDF_IS_STATUS_ERROR(status))
1330 		goto error_handle;
1331 
1332 	req->scan_req.scan_id = wlan_scan_get_scan_id(mac_ctx->psoc);
1333 	sme_rrm_ctx->scan_id = req->scan_req.scan_id;
1334 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
1335 	req->scan_req.scan_req_id = sme_rrm_ctx->req_id;
1336 	req->scan_req.scan_f_passive = true;
1337 	max_chan_time = sme_rrm_ctx->duration[0];
1338 	req->scan_req.dwell_time_passive = max_chan_time;
1339 	req->scan_req.dwell_time_passive_6g = max_chan_time;
1340 	req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
1341 	req->scan_req.scan_type = SCAN_TYPE_RRM;
1342 	req->scan_req.scan_f_wide_band = true;
1343 	/*
1344 	 * FW report CCA busy for each possible 20Mhz subbands of the
1345 	 * wideband scan channel if below flag is true
1346 	 */
1347 	req->scan_req.scan_f_report_cca_busy_for_each_20mhz = true;
1348 
1349 	status = sme_rrm_fill_freq_list_for_channel_load(mac_ctx, sme_rrm_ctx,
1350 							 vdev, req);
1351 	if (QDF_IS_STATUS_ERROR(status))
1352 		goto error_handle;
1353 	sme_debug("vdev:%d, rrm_idx:%d scan_id:%d num chan: %d dwell_time: %d",
1354 		  req->scan_req.vdev_id, sme_rrm_ctx->measurement_idx,
1355 		  sme_rrm_ctx->scan_id,
1356 		  req->scan_req.chan_list.num_chan,
1357 		  req->scan_req.dwell_time_passive);
1358 	/* store jiffies to send it in channel load report */
1359 	sme_rrm_ctx->chan_load_req_info.rrm_scan_tsf =
1360 				(uint32_t)qdf_system_ticks();
1361 	status = wlan_scan_start(req);
1362 	if (QDF_IS_STATUS_ERROR(status))
1363 		goto error_handle;
1364 
1365 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1366 	return status;
1367 error_handle:
1368 	qdf_mem_free(req);
1369 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1370 send_ind:
1371 	sme_rrm_send_chan_load_report_xmit_ind(mac_ctx, sme_rrm_ctx,
1372 					       vdev_id, false);
1373 	rrm_cleanup(mac_ctx, idx);
1374 	return status;
1375 }
1376 
1377 /**
1378  * sme_rrm_process_chan_load_req_ind() -Process beacon report request
1379  * @mac: Global Mac structure
1380  * @msg_buf: a pointer to a buffer that maps to various structures base
1381  * on the message type.The beginning of the buffer can always
1382  * map to tSirSmeRsp.
1383  *
1384  * This is called to process the channel load report request from peer AP
1385  * forwarded through PE .
1386  *
1387  * Return : QDF_STATUS_SUCCESS - Validation is successful.
1388  */
sme_rrm_process_chan_load_req_ind(struct mac_context * mac,void * msg_buf)1389 static QDF_STATUS sme_rrm_process_chan_load_req_ind(struct mac_context *mac,
1390 						    void *msg_buf)
1391 {
1392 	struct ch_load_ind *chan_load;
1393 	tpRrmSMEContext sme_rrm_ctx;
1394 	tpRrmPEContext rrm_ctx;
1395 	struct channel_load_req_info *req_info;
1396 
1397 	chan_load = (struct ch_load_ind *)msg_buf;
1398 	sme_rrm_ctx = &mac->rrm.rrmSmeContext[chan_load->measurement_idx];
1399 	rrm_ctx = &mac->rrm.rrmPEContext;
1400 	qdf_mem_copy(sme_rrm_ctx->sessionBssId.bytes,
1401 		     chan_load->peer_addr.bytes, sizeof(struct qdf_mac_addr));
1402 
1403 	sme_rrm_ctx->token = chan_load->dialog_token;
1404 	sme_rrm_ctx->regClass = chan_load->op_class;
1405 	sme_rrm_ctx->randnIntvl = QDF_MAX(chan_load->randomization_intv,
1406 			mac->rrm.rrmConfig.max_randn_interval);
1407 	sme_rrm_ctx->currentIndex = 0;
1408 	qdf_mem_copy((uint8_t *)&sme_rrm_ctx->duration,
1409 		     (uint8_t *)&chan_load->meas_duration,
1410 		     SIR_ESE_MAX_MEAS_IE_REQS);
1411 	sme_rrm_ctx->measurement_type = RRM_CHANNEL_LOAD;
1412 	req_info = &sme_rrm_ctx->chan_load_req_info;
1413 	req_info->channel = chan_load->channel;
1414 	req_info->req_freq = chan_load->req_freq;
1415 
1416 	qdf_mem_copy(&req_info->bw_ind, &chan_load->bw_ind,
1417 		     sizeof(req_info->bw_ind));
1418 	qdf_mem_copy(&req_info->wide_bw, &chan_load->wide_bw,
1419 		     sizeof(req_info->wide_bw));
1420 
1421 	sme_debug("idx:%d, token: %d randnIntvl: %d meas_duration %d, rrm_ctx dur %d reg_class: %d, type: %d, channel: %d, freq: %d, [bw_ind present: %d, cw: %d, ccfs0: %d], [wide_bw present: %d, cw: %d]",
1422 		  chan_load->measurement_idx, sme_rrm_ctx->token,
1423 		  sme_rrm_ctx->randnIntvl,
1424 		  chan_load->meas_duration,
1425 		  sme_rrm_ctx->duration[0], sme_rrm_ctx->regClass,
1426 		  sme_rrm_ctx->measurement_type,
1427 		  req_info->channel, req_info->req_freq,
1428 		  req_info->bw_ind.is_bw_ind_element,
1429 		  req_info->bw_ind.channel_width,
1430 		  req_info->bw_ind.center_freq,
1431 		  req_info->wide_bw.is_wide_bw_chan_switch,
1432 		  req_info->wide_bw.channel_width);
1433 
1434 	return sme_rrm_issue_chan_load_measurement_scan(mac,
1435 						chan_load->measurement_idx);
1436 }
1437 
1438 /**
1439  * sme_rrm_process_beacon_report_req_ind() -Process beacon report request
1440  * @mac:- Global Mac structure
1441  * @msg_buf:- a pointer to a buffer that maps to various structures base
1442  *                  on the message type.The beginning of the buffer can always
1443  *                  map to tSirSmeRsp.
1444  *
1445  * This is called to process the Beacon
1446  * report request from peer AP forwarded through PE .
1447  *
1448  * Return : QDF_STATUS_SUCCESS - Validation is successful.
1449  */
sme_rrm_process_beacon_report_req_ind(struct mac_context * mac,void * msg_buf)1450 QDF_STATUS sme_rrm_process_beacon_report_req_ind(struct mac_context *mac,
1451 						 void *msg_buf)
1452 {
1453 	tpSirBeaconReportReqInd beacon_req = (tpSirBeaconReportReqInd)msg_buf;
1454 	tpRrmSMEContext sme_rrm_ctx;
1455 	uint32_t len = 0, i = 0, j = 0;
1456 	uint8_t country[WNI_CFG_COUNTRY_CODE_LEN];
1457 	uint32_t session_id;
1458 	struct csr_roam_session *session;
1459 	QDF_STATUS status;
1460 	uint32_t num_chan, local_num_channel;
1461 	bool chan_valid;
1462 	uint32_t *rrm_freq_list, *local_rrm_freq_list;
1463 	uint32_t bcn_chan_freq, local_bcn_chan_freq;
1464 	tpRrmPEContext rrm_ctx;
1465 
1466 	sme_rrm_ctx = &mac->rrm.rrmSmeContext[beacon_req->measurement_idx];
1467 	rrm_ctx = &mac->rrm.rrmPEContext;
1468 
1469 	status = csr_roam_get_session_id_from_bssid(mac, (struct qdf_mac_addr *)
1470 						    beacon_req->bssId,
1471 						    &session_id);
1472 	if (QDF_IS_STATUS_ERROR(status)) {
1473 		sme_err("sme session ID not found for bssid");
1474 		goto cleanup;
1475 	}
1476 
1477 	session = CSR_GET_SESSION(mac, session_id);
1478 	if (!session) {
1479 		sme_err("Invalid session id %d", session_id);
1480 		status = QDF_STATUS_E_FAILURE;
1481 		goto cleanup;
1482 	}
1483 
1484 	rrm_get_country_code_from_connected_profile(mac, session_id, country);
1485 
1486 	if (wlan_reg_is_6ghz_op_class(mac->pdev,
1487 				      beacon_req->channel_info.reg_class))
1488 		country[2] = OP_CLASS_GLOBAL;
1489 
1490 	sme_debug("RRM_SCN: Index:%d Request Reg class %d, AP's country code %c%c 0x%x, channel = %d",
1491 		  beacon_req->measurement_idx,
1492 		  beacon_req->channel_info.reg_class,
1493 		  country[0], country[1], country[2],
1494 		  beacon_req->channel_info.chan_num);
1495 
1496 	if (beacon_req->channel_list.num_channels > SIR_ESE_MAX_MEAS_IE_REQS) {
1497 		sme_err("Beacon report request numChannels:%u exceeds max num channels",
1498 			beacon_req->channel_list.num_channels);
1499 		status = QDF_STATUS_E_INVAL;
1500 		goto cleanup;
1501 	}
1502 
1503 	/* section 11.10.8.1 (IEEE Std 802.11k-2008) */
1504 	/* channel 0 and 255 has special meaning. */
1505 	if ((beacon_req->channel_info.chan_num == 0) ||
1506 	    ((beacon_req->channel_info.chan_num == 255) &&
1507 	     (beacon_req->channel_list.num_channels == 0))) {
1508 		/* Add all the channel in the regulatory domain. */
1509 		len = mac->mlme_cfg->reg.valid_channel_list_num;
1510 		if (sme_rrm_ctx->channelList.freq_list) {
1511 			qdf_mem_free(sme_rrm_ctx->channelList.freq_list);
1512 			sme_rrm_ctx->channelList.freq_list = NULL;
1513 		}
1514 		sme_rrm_ctx->channelList.freq_list =
1515 			qdf_mem_malloc(sizeof(uint32_t) * len);
1516 		if (!sme_rrm_ctx->channelList.freq_list) {
1517 			status = QDF_STATUS_E_NOMEM;
1518 			sme_rrm_ctx->channelList.numOfChannels = 0;
1519 			goto cleanup;
1520 		}
1521 
1522 		csr_get_cfg_valid_channels(
1523 			mac, sme_rrm_ctx->channelList.freq_list, &len);
1524 
1525 		if (beacon_req->channel_info.reg_class) {
1526 			if (sme_rrm_fill_scan_channels(
1527 				mac, country, sme_rrm_ctx,
1528 				beacon_req->channel_info.reg_class, len) !=
1529 			    QDF_STATUS_SUCCESS)
1530 				goto cleanup;
1531 		} else {
1532 			sme_rrm_ctx->channelList.numOfChannels = len;
1533 		}
1534 	} else {
1535 		len = 0;
1536 		sme_rrm_ctx->channelList.numOfChannels = 0;
1537 		num_chan = 0;
1538 
1539 		/* If valid channel is present. We first Measure on the given
1540 		 * channel and if there are additional channels present in
1541 		 * APchannelreport, measure on these also.
1542 		 */
1543 		if (beacon_req->channel_info.chan_num != 255)
1544 			len = 1;
1545 
1546 		len += beacon_req->channel_list.num_channels;
1547 
1548 		if (sme_rrm_ctx->channelList.freq_list) {
1549 			qdf_mem_free(sme_rrm_ctx->channelList.freq_list);
1550 			sme_rrm_ctx->channelList.freq_list = NULL;
1551 		}
1552 		sme_rrm_ctx->channelList.freq_list =
1553 			qdf_mem_malloc(sizeof(uint32_t) * len);
1554 		if (!sme_rrm_ctx->channelList.freq_list) {
1555 			sme_rrm_ctx->channelList.numOfChannels = 0;
1556 			status = QDF_STATUS_E_NOMEM;
1557 			goto cleanup;
1558 		}
1559 
1560 		rrm_freq_list = sme_rrm_ctx->channelList.freq_list;
1561 		bcn_chan_freq = beacon_req->channel_info.chan_freq;
1562 
1563 		if (beacon_req->channel_info.chan_num != 255) {
1564 			chan_valid =
1565 				wlan_roam_is_channel_valid(&mac->mlme_cfg->reg,
1566 							   bcn_chan_freq);
1567 
1568 			if (chan_valid) {
1569 				rrm_freq_list[num_chan] = bcn_chan_freq;
1570 				num_chan++;
1571 			} else {
1572 				sme_err("Invalid channel: %d",
1573 					beacon_req->channel_info.chan_num);
1574 			}
1575 		}
1576 
1577 		for (i = 0; i < beacon_req->channel_list.num_channels; i++) {
1578 			bcn_chan_freq =
1579 				beacon_req->channel_list.chan_freq_lst[i];
1580 			chan_valid =
1581 				wlan_roam_is_channel_valid(&mac->mlme_cfg->reg,
1582 							   bcn_chan_freq);
1583 
1584 			if (chan_valid) {
1585 				rrm_freq_list[num_chan] = bcn_chan_freq;
1586 				num_chan++;
1587 			}
1588 		}
1589 
1590 		sme_rrm_ctx->channelList.numOfChannels = num_chan;
1591 	}
1592 
1593 	local_rrm_freq_list = sme_rrm_ctx->channelList.freq_list;
1594 	local_num_channel = 0;
1595 	for (i = 0; i < sme_rrm_ctx->channelList.numOfChannels; i++) {
1596 		local_bcn_chan_freq = local_rrm_freq_list[i];
1597 		chan_valid = true;
1598 
1599 		if (beacon_req->measurement_idx > 0) {
1600 			for (j = 0; j < rrm_ctx->beacon_rpt_chan_num; j++) {
1601 				if (rrm_ctx->beacon_rpt_chan_list[j] ==
1602 				    local_bcn_chan_freq) {
1603 				/*
1604 				 * Ignore this channel, As this is already
1605 				 * included in previous request
1606 				 */
1607 					chan_valid = false;
1608 					break;
1609 				}
1610 			}
1611 		}
1612 
1613 		if (chan_valid) {
1614 			uint8_t beacon_rpt_chan_num;
1615 
1616 			beacon_rpt_chan_num = rrm_ctx->beacon_rpt_chan_num;
1617 			rrm_ctx->beacon_rpt_chan_list[beacon_rpt_chan_num] =
1618 						local_bcn_chan_freq;
1619 			rrm_ctx->beacon_rpt_chan_num++;
1620 
1621 			if (rrm_ctx->beacon_rpt_chan_num >=
1622 			    MAX_NUM_CHANNELS) {
1623 			    /* this should never happen */
1624 				sme_err("Reset beacon_rpt_chan_num : %d",
1625 					rrm_ctx->beacon_rpt_chan_num);
1626 				rrm_ctx->beacon_rpt_chan_num = 0;
1627 			}
1628 			local_rrm_freq_list[local_num_channel] =
1629 							local_bcn_chan_freq;
1630 			local_num_channel++;
1631 		}
1632 	}
1633 
1634 	if (local_num_channel == 0)
1635 		goto cleanup;
1636 
1637 	sme_rrm_ctx->channelList.numOfChannels = local_num_channel;
1638 
1639 	/* Copy session bssid */
1640 	qdf_mem_copy(sme_rrm_ctx->sessionBssId.bytes, beacon_req->bssId,
1641 		     sizeof(tSirMacAddr));
1642 
1643 	/* copy measurement bssid */
1644 	qdf_mem_copy(sme_rrm_ctx->bssId, beacon_req->macaddrBssid,
1645 		     sizeof(tSirMacAddr));
1646 
1647 	/* Copy ssid */
1648 	qdf_mem_copy(&sme_rrm_ctx->ssId, &beacon_req->ssId,
1649 		     sizeof(tAniSSID));
1650 
1651 	sme_rrm_ctx->token = beacon_req->uDialogToken;
1652 	sme_rrm_ctx->regClass = beacon_req->channel_info.reg_class;
1653 	sme_rrm_ctx->randnIntvl =
1654 		QDF_MAX(beacon_req->randomizationInterval,
1655 			mac->rrm.rrmConfig.max_randn_interval);
1656 	sme_rrm_ctx->currentIndex = 0;
1657 	sme_rrm_ctx->msgSource = beacon_req->msgSource;
1658 	qdf_mem_copy((uint8_t *)&sme_rrm_ctx->measMode,
1659 		     (uint8_t *)&beacon_req->fMeasurementtype,
1660 		     SIR_ESE_MAX_MEAS_IE_REQS);
1661 	qdf_mem_copy((uint8_t *)&sme_rrm_ctx->duration,
1662 		     (uint8_t *)&beacon_req->measurementDuration,
1663 		     SIR_ESE_MAX_MEAS_IE_REQS);
1664 
1665 	sme_rrm_ctx->measurement_type = RRM_BEACON_REPORT;
1666 
1667 	sme_debug("token: %d randnIntvl: %d msgSource: %d measurementduration %d, rrm_ctx duration %d Meas_mode: %s, type: %d",
1668 		  sme_rrm_ctx->token, sme_rrm_ctx->randnIntvl,
1669 		  sme_rrm_ctx->msgSource, beacon_req->measurementDuration[0],
1670 		  sme_rrm_ctx->duration[0],
1671 		  sme_rrm_get_meas_mode_string(sme_rrm_ctx->measMode[0]),
1672 		  sme_rrm_ctx->measurement_type);
1673 
1674 	return sme_rrm_issue_scan_req(mac, beacon_req->measurement_idx);
1675 
1676 cleanup:
1677 	if (beacon_req->msgSource == eRRM_MSG_SOURCE_11K) {
1678 		/* Copy session bssid */
1679 		qdf_mem_copy(sme_rrm_ctx->sessionBssId.bytes,
1680 			     beacon_req->bssId, sizeof(tSirMacAddr));
1681 
1682 		/* copy measurement bssid */
1683 		qdf_mem_copy(sme_rrm_ctx->bssId, beacon_req->macaddrBssid,
1684 			     sizeof(tSirMacAddr));
1685 		sme_rrm_ctx->token = beacon_req->uDialogToken;
1686 		sme_rrm_ctx->regClass =
1687 			beacon_req->channel_info.reg_class;
1688 		sme_rrm_ctx->randnIntvl =
1689 			QDF_MAX(beacon_req->randomizationInterval,
1690 			mac->rrm.rrmConfig.max_randn_interval);
1691 
1692 		sme_rrm_send_beacon_report_xmit_ind(mac,
1693 			     sme_rrm_ctx->measurement_idx, NULL, true, 0);
1694 	}
1695 
1696 	return status;
1697 }
1698 
1699 /**
1700  * sme_rrm_neighbor_report_request() - This is API can be used to trigger a
1701  *        Neighbor report from the peer.
1702  * @sessionId: session identifier on which the request should be made.
1703  * @pNeighborReq: a pointer to a neighbor report request.
1704  *
1705  * This is API can be used to trigger a  Neighbor report from the peer.
1706  *
1707  * Return: QDF_STATUS_SUCCESS - Validation is successful.
1708  */
sme_rrm_neighbor_report_request(struct mac_context * mac,uint8_t sessionId,tpRrmNeighborReq pNeighborReq,tpRrmNeighborRspCallbackInfo callbackInfo)1709 QDF_STATUS sme_rrm_neighbor_report_request(struct mac_context *mac, uint8_t
1710 					sessionId, tpRrmNeighborReq
1711 					pNeighborReq,
1712 					tpRrmNeighborRspCallbackInfo
1713 					callbackInfo)
1714 {
1715 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1716 	tpSirNeighborReportReqInd pMsg;
1717 
1718 	sme_debug("Request to send Neighbor report request received ");
1719 	if (!CSR_IS_SESSION_VALID(mac, sessionId)) {
1720 		sme_err("Invalid session %d", sessionId);
1721 		return QDF_STATUS_E_INVAL;
1722 	}
1723 
1724 	/* If already a report is pending, return failure */
1725 	if (true ==
1726 	    mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1727 	    isNeighborRspPending) {
1728 		sme_err("Neighbor request already pending.. Not allowed");
1729 		return QDF_STATUS_E_AGAIN;
1730 	}
1731 
1732 	pMsg = qdf_mem_malloc(sizeof(tSirNeighborReportReqInd));
1733 	if (!pMsg)
1734 		return QDF_STATUS_E_NOMEM;
1735 
1736 	rrm_ll_purge_neighbor_cache(mac,
1737 			    &mac->rrm.rrmSmeContext[0].neighborReportCache);
1738 
1739 	pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND;
1740 	pMsg->length = sizeof(tSirNeighborReportReqInd);
1741 	wlan_mlme_get_bssid_vdev_id(mac->pdev, sessionId,
1742 				    (struct qdf_mac_addr *)&pMsg->bssId);
1743 	pMsg->noSSID = pNeighborReq->no_ssid;
1744 	qdf_mem_copy(&pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid));
1745 
1746 	status = umac_send_mb_message_to_mac(pMsg);
1747 	if (status != QDF_STATUS_SUCCESS)
1748 		return QDF_STATUS_E_FAILURE;
1749 
1750 	/* Neighbor report request message sent successfully to PE.
1751 	 * Now register the callbacks
1752 	 */
1753 	mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1754 		neighborRspCallbackInfo.neighborRspCallback =
1755 			callbackInfo->neighborRspCallback;
1756 	mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1757 		neighborRspCallbackInfo.neighborRspCallbackContext =
1758 			callbackInfo->neighborRspCallbackContext;
1759 	mac->rrm.rrmSmeContext[0].neighborReqControlInfo.isNeighborRspPending =
1760 		true;
1761 
1762 	/* Start neighbor response wait timer now */
1763 	qdf_mc_timer_start(&mac->rrm.rrmSmeContext[0].neighborReqControlInfo.
1764 			   neighborRspWaitTimer, callbackInfo->timeout);
1765 
1766 	return QDF_STATUS_SUCCESS;
1767 }
1768 
1769 /**
1770  * rrm_calculate_neighbor_ap_roam_score() - calculates roam score
1771  * @mac_ctx:                mac global context
1772  * @pNeighborReportDesc:    Neighbor BSS Descriptor node for which roam score
1773  *                          should be calculated
1774  *
1775  * This API is called while handling individual neighbor reports from the APs
1776  * neighbor AP report to calculate the cumulative roam score before storing it
1777  * in neighbor cache.
1778  *
1779  * Return: void
1780  */
1781 static void
rrm_calculate_neighbor_ap_roam_score(struct mac_context * mac_ctx,tpRrmNeighborReportDesc nbr_report_desc)1782 rrm_calculate_neighbor_ap_roam_score(struct mac_context *mac_ctx,
1783 				tpRrmNeighborReportDesc nbr_report_desc)
1784 {
1785 	tpSirNeighborBssDescripton nbr_bss_desc;
1786 	uint32_t roam_score = 0;
1787 #ifdef FEATURE_WLAN_ESE
1788 	uint8_t session_id;
1789 	struct cm_roam_values_copy config;
1790 #endif
1791 
1792 	if (!nbr_report_desc) {
1793 		QDF_ASSERT(0);
1794 		return;
1795 	}
1796 
1797 	if (!nbr_report_desc->pNeighborBssDescription) {
1798 		QDF_ASSERT(0);
1799 		return;
1800 	}
1801 
1802 	nbr_bss_desc = nbr_report_desc->pNeighborBssDescription;
1803 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fMobilityDomain)
1804 		goto check_11r_assoc;
1805 
1806 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN;
1807 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameSecurityMode)
1808 		goto check_11r_assoc;
1809 
1810 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY;
1811 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fSameAuthenticator)
1812 		goto check_11r_assoc;
1813 
1814 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE;
1815 	if (!nbr_bss_desc->bssidInfo.rrmInfo.fCapRadioMeasurement)
1816 		goto check_11r_assoc;
1817 
1818 	roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM;
1819 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapSpectrumMeasurement)
1820 		roam_score +=
1821 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT;
1822 
1823 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapQos)
1824 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS;
1825 
1826 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapApsd)
1827 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD;
1828 
1829 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapDelayedBlockAck)
1830 		roam_score +=
1831 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA;
1832 
1833 	if (nbr_bss_desc->bssidInfo.rrmInfo.fCapImmediateBlockAck)
1834 		roam_score +=
1835 			RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA;
1836 
1837 	if (nbr_bss_desc->bssidInfo.rrmInfo.fApPreauthReachable)
1838 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY;
1839 
1840 check_11r_assoc:
1841 #ifdef FEATURE_WLAN_ESE
1842 	session_id = nbr_report_desc->sessionId;
1843 	wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session_id, IS_11R_CONNECTION,
1844 				   &config);
1845 	/* It has come in the report so its the best score */
1846 	if (!config.bool_value) {
1847 		/* IAPP Route so lets make use of this info save all AP, as the
1848 		 * list does not come all the time. Save and reuse till the next
1849 		 * AP List comes to us. Even save our own MAC address. Will be
1850 		 * useful next time around.
1851 		 */
1852 		roam_score += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST;
1853 	}
1854 #endif
1855 	nbr_report_desc->roamScore = roam_score;
1856 }
1857 
1858 /**
1859  * rrm_store_neighbor_rpt_by_roam_score()-store Neighbor BSS descriptor
1860  * @mac: Pointer to mac context
1861  * @pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache
1862  * @index: RRM sme context index
1863  *
1864  * This API is called to store a given
1865  * Neighbor BSS descriptor to the neighbor cache. This function
1866  * stores the neighbor BSS descriptors in such a way that descriptors
1867  * are sorted by roamScore in descending order
1868  *
1869  * Return: void.
1870  */
rrm_store_neighbor_rpt_by_roam_score(struct mac_context * mac,tpRrmNeighborReportDesc pNeighborReportDesc,uint8_t index)1871 static void rrm_store_neighbor_rpt_by_roam_score(struct mac_context *mac,
1872 				tpRrmNeighborReportDesc pNeighborReportDesc,
1873 				uint8_t index)
1874 {
1875 	tpRrmSMEContext pSmeRrmContext = &mac->rrm.rrmSmeContext[0];
1876 	tListElem *pEntry;
1877 	tRrmNeighborReportDesc *pTempNeighborReportDesc;
1878 
1879 	if (!pNeighborReportDesc) {
1880 		QDF_ASSERT(0);
1881 		return;
1882 	}
1883 	if (!pNeighborReportDesc->pNeighborBssDescription) {
1884 		QDF_ASSERT(0);
1885 		return;
1886 	}
1887 
1888 	if (csr_ll_is_list_empty
1889 		    (&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) {
1890 		sme_err("Neighbor report cache is empty.. Adding a entry now");
1891 		/* Neighbor list cache is empty. Insert this entry
1892 		 * in the tail
1893 		 */
1894 		csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache,
1895 				   &pNeighborReportDesc->List, LL_ACCESS_LOCK);
1896 		return;
1897 	}
1898 	/* Should store the neighbor BSS description in the order
1899 	 * sorted by roamScore in descending order. APs with highest
1900 	 * roamScore should be the 1st entry in the list
1901 	 */
1902 	pEntry = csr_ll_peek_head(&pSmeRrmContext->neighborReportCache,
1903 				LL_ACCESS_LOCK);
1904 	while (pEntry) {
1905 		pTempNeighborReportDesc = GET_BASE_ADDR(pEntry,
1906 					tRrmNeighborReportDesc, List);
1907 		if (pTempNeighborReportDesc->roamScore <
1908 				pNeighborReportDesc->roamScore)
1909 			break;
1910 		pEntry = csr_ll_next(&pSmeRrmContext->
1911 				neighborReportCache, pEntry, LL_ACCESS_LOCK);
1912 		}
1913 
1914 	if (pEntry)
1915 		/* This BSS roamscore is better than something in the
1916 		 * list. Insert this before that one
1917 		 */
1918 		csr_ll_insert_entry(&pSmeRrmContext->neighborReportCache,
1919 					pEntry, &pNeighborReportDesc->List,
1920 					LL_ACCESS_LOCK);
1921 	else
1922 		/* All the entries in the list has a better roam Score
1923 		 * than this one. Insert this at the last
1924 		 */
1925 		csr_ll_insert_tail(&pSmeRrmContext->neighborReportCache,
1926 					&pNeighborReportDesc->List,
1927 					LL_ACCESS_LOCK);
1928 }
1929 
1930 /**
1931  * sme_rrm_process_neighbor_report() -Process the Neighbor report received
1932  *                                                     from PE
1933  * @mac - Global MAC structure
1934  * @msg_buf - a pointer to a buffer that maps to various structures base
1935  *                  on the message type.
1936  *                  The beginning of the buffer can always map to tSirSmeRsp.
1937  * This is called to process the Neighbor report received from PE.
1938  *
1939  * Return: QDF_STATUS_SUCCESS - Validation is successful
1940  */
sme_rrm_process_neighbor_report(struct mac_context * mac,void * msg_buf)1941 static QDF_STATUS sme_rrm_process_neighbor_report(struct mac_context *mac,
1942 						  void *msg_buf)
1943 {
1944 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1945 	tpSirNeighborReportInd neighbor_rpt = (tpSirNeighborReportInd)msg_buf;
1946 	tpRrmNeighborReportDesc neighbor_rpt_desc;
1947 	uint8_t i = 0;
1948 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1949 
1950 	/* Purge the cache on reception of unsolicited neighbor report */
1951 	if (!mac->rrm.rrmSmeContext[neighbor_rpt->measurement_idx].
1952 	    neighborReqControlInfo.isNeighborRspPending)
1953 		rrm_ll_purge_neighbor_cache(mac,
1954 			&mac->rrm.rrmSmeContext[neighbor_rpt->measurement_idx].
1955 			neighborReportCache);
1956 
1957 	for (i = 0; i < neighbor_rpt->numNeighborReports; i++) {
1958 		neighbor_rpt_desc =
1959 			qdf_mem_malloc(sizeof(tRrmNeighborReportDesc));
1960 		if (!neighbor_rpt_desc) {
1961 			status = QDF_STATUS_E_NOMEM;
1962 			goto end;
1963 
1964 		}
1965 
1966 		neighbor_rpt_desc->pNeighborBssDescription =
1967 			qdf_mem_malloc(sizeof(tSirNeighborBssDescription));
1968 		if (!neighbor_rpt_desc->pNeighborBssDescription) {
1969 			qdf_mem_free(neighbor_rpt_desc);
1970 			status = QDF_STATUS_E_NOMEM;
1971 			goto end;
1972 		}
1973 		qdf_mem_copy(neighbor_rpt_desc->pNeighborBssDescription,
1974 			     &neighbor_rpt->sNeighborBssDescription[i],
1975 			     sizeof(tSirNeighborBssDescription));
1976 
1977 		sme_debug("Received neighbor report with Neighbor BSSID: "
1978 			QDF_MAC_ADDR_FMT,
1979 			QDF_MAC_ADDR_REF(
1980 			       neighbor_rpt->sNeighborBssDescription[i].bssId));
1981 
1982 		rrm_calculate_neighbor_ap_roam_score(mac, neighbor_rpt_desc);
1983 
1984 		if (neighbor_rpt_desc->roamScore > 0) {
1985 			rrm_store_neighbor_rpt_by_roam_score(
1986 					mac, neighbor_rpt_desc,
1987 					neighbor_rpt->measurement_idx);
1988 		} else {
1989 			sme_err("Roam score of BSSID  " QDF_MAC_ADDR_FMT
1990 				" is 0, Ignoring..",
1991 				QDF_MAC_ADDR_REF(neighbor_rpt->
1992 					       sNeighborBssDescription[i].
1993 					       bssId));
1994 
1995 			qdf_mem_free(
1996 				neighbor_rpt_desc->pNeighborBssDescription);
1997 			qdf_mem_free(neighbor_rpt_desc);
1998 		}
1999 	}
2000 end:
2001 
2002 	if (!csr_ll_count(
2003 		&mac->rrm.rrmSmeContext[neighbor_rpt->measurement_idx].
2004 		neighborReportCache))
2005 		qdf_status = QDF_STATUS_E_FAILURE;
2006 
2007 	rrm_indicate_neighbor_report_result(mac, qdf_status);
2008 
2009 	return status;
2010 }
2011 
2012 /**
2013  * sme_rrm_msg_processor()-Process RRM message
2014  * @mac - Pointer to the global MAC parameter structure.
2015  * @msg_type - the type of msg passed by PE as defined in wni_api.h
2016  * @msg_buf - a pointer to a buffer that maps to various structures base
2017  *                  on the message type.
2018  *                  The beginning of the buffer can always map to tSirSmeRsp.
2019  * sme_process_msg() calls this function for the
2020  * messages that are handled by SME RRM module.
2021  *
2022  * Return: QDF_STATUS_SUCCESS - Validation is successful.
2023  */
sme_rrm_msg_processor(struct mac_context * mac,uint16_t msg_type,void * msg_buf)2024 QDF_STATUS sme_rrm_msg_processor(struct mac_context *mac, uint16_t msg_type,
2025 				 void *msg_buf)
2026 {
2027 	sme_debug("Msg = %d for RRM measurement", msg_type);
2028 
2029 	/* switch on the msg type & make the state transition accordingly */
2030 	switch (msg_type) {
2031 	case eWNI_SME_NEIGHBOR_REPORT_IND:
2032 		sme_rrm_process_neighbor_report(mac, msg_buf);
2033 		break;
2034 
2035 	case eWNI_SME_BEACON_REPORT_REQ_IND:
2036 		sme_rrm_process_beacon_report_req_ind(mac, msg_buf);
2037 		break;
2038 
2039 	case eWNI_SME_CHAN_LOAD_REQ_IND:
2040 		sme_rrm_process_chan_load_req_ind(mac, msg_buf);
2041 		break;
2042 
2043 	default:
2044 		sme_err("Unknown msg type: %d", msg_type);
2045 		break;
2046 	}
2047 
2048 	return QDF_STATUS_SUCCESS;
2049 }
2050 
2051 /**
2052  * rrm_neighbor_rsp_timeout_handler() - Timer handler to handlet the timeout
2053  * @mac - The handle returned by mac_open.
2054  *
2055  * Timer handler to handle the timeout condition when a neighbor request is sent
2056  * and no neighbor response is received from the AP
2057  *
2058  * Return: NULL
2059  */
rrm_neighbor_rsp_timeout_handler(void * userData)2060 static void rrm_neighbor_rsp_timeout_handler(void *userData)
2061 {
2062 	struct mac_context *mac = (struct mac_context *) userData;
2063 
2064 	sme_warn("Neighbor Response timed out");
2065 	rrm_indicate_neighbor_report_result(mac, QDF_STATUS_E_FAILURE);
2066 }
2067 
2068 /**
2069  * rrm_change_default_config_param() - Changing default config param to new
2070  * @mac - The handle returned by mac_open.
2071  *
2072  * Return: None
2073  */
rrm_change_default_config_param(struct mac_context * mac)2074 static void rrm_change_default_config_param(struct mac_context *mac)
2075 {
2076 	mac->rrm.rrmConfig.rrm_enabled =
2077 			mac->mlme_cfg->rrm_config.rrm_enabled;
2078 	mac->rrm.rrmConfig.sap_rrm_enabled =
2079 			mac->mlme_cfg->rrm_config.sap_rrm_enabled;
2080 	mac->rrm.rrmConfig.max_randn_interval =
2081 			mac->mlme_cfg->rrm_config.rrm_rand_interval;
2082 
2083 	qdf_mem_copy(&mac->rrm.rrmConfig.rm_capability,
2084 		     &mac->mlme_cfg->rrm_config.rm_capability,
2085 		     RMENABLEDCAP_MAX_LEN);
2086 }
2087 
2088 /**
2089  * rrm_open() - Initialize all RRM module
2090  * @ mac: The handle returned by mac_open.
2091  *
2092  * Initialize all RRM module.
2093  *
2094  * Return: QDF_STATUS
2095  */
rrm_open(struct mac_context * mac)2096 QDF_STATUS rrm_open(struct mac_context *mac)
2097 {
2098 
2099 	QDF_STATUS qdf_status;
2100 	tpRrmSMEContext pSmeRrmContext;
2101 	QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
2102 	uint8_t i;
2103 
2104 	mac->rrm.rrmConfig.max_randn_interval = 50;        /* ms */
2105 
2106 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2107 		pSmeRrmContext = &mac->rrm.rrmSmeContext[i];
2108 
2109 		qdf_status =
2110 		    qdf_mc_timer_init(&pSmeRrmContext->neighborReqControlInfo.
2111 				      neighborRspWaitTimer, QDF_TIMER_TYPE_SW,
2112 				      rrm_neighbor_rsp_timeout_handler,
2113 				      (void *)mac);
2114 
2115 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
2116 			sme_err("Fail to init neighbor rsp wait timer");
2117 			return QDF_STATUS_E_FAILURE;
2118 		}
2119 
2120 		pSmeRrmContext->measurement_idx = i;
2121 		pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending =
2122 						false;
2123 
2124 		qdf_ret_status =
2125 			csr_ll_open(&pSmeRrmContext->neighborReportCache);
2126 		if (QDF_STATUS_SUCCESS != qdf_ret_status) {
2127 			sme_err("Fail to open neighbor cache result");
2128 			return QDF_STATUS_E_FAILURE;
2129 		}
2130 	}
2131 
2132 	rrm_change_default_config_param(mac);
2133 
2134 	return QDF_STATUS_SUCCESS;
2135 }
2136 
2137 /**
2138  * rrm_close() - Release all RRM modules and their resources.
2139  * @mac - The handle returned by mac_open.
2140  *
2141  * Release all RRM modules and their resources.
2142  *
2143  * Return: QDF_STATUS
2144  *           QDF_STATUS_E_FAILURE  success
2145  *           QDF_STATUS_SUCCESS  failure
2146  */
2147 
rrm_close(struct mac_context * mac)2148 QDF_STATUS rrm_close(struct mac_context *mac)
2149 {
2150 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
2151 	tpRrmSMEContext pSmeRrmContext;
2152 	uint8_t i;
2153 
2154 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2155 		pSmeRrmContext = &mac->rrm.rrmSmeContext[i];
2156 
2157 		if (pSmeRrmContext->channelList.freq_list) {
2158 			qdf_mem_free(pSmeRrmContext->channelList.freq_list);
2159 			pSmeRrmContext->channelList.freq_list = NULL;
2160 			pSmeRrmContext->channelList.numOfChannels = 0;
2161 		}
2162 
2163 		if (QDF_TIMER_STATE_RUNNING ==
2164 		    qdf_mc_timer_get_current_state(&pSmeRrmContext->
2165 						   neighborReqControlInfo.
2166 						   neighborRspWaitTimer)) {
2167 			qdf_status = qdf_mc_timer_stop(&pSmeRrmContext->
2168 						neighborReqControlInfo.
2169 						neighborRspWaitTimer);
2170 			if (QDF_IS_STATUS_ERROR(qdf_status))
2171 				sme_err("Timer stop fail");
2172 		}
2173 
2174 		qdf_status = qdf_mc_timer_destroy(
2175 				&pSmeRrmContext->neighborReqControlInfo.
2176 				neighborRspWaitTimer);
2177 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
2178 			sme_err("Fail to destroy timer");
2179 
2180 		rrm_ll_purge_neighbor_cache(
2181 				mac, &pSmeRrmContext->neighborReportCache);
2182 		csr_ll_close(&pSmeRrmContext->neighborReportCache);
2183 	}
2184 
2185 	return qdf_status;
2186 
2187 }
2188 
rrm_start(struct mac_context * mac_ctx)2189 QDF_STATUS rrm_start(struct mac_context *mac_ctx)
2190 {
2191 	tpRrmSMEContext smerrmctx;
2192 	wlan_scan_requester req_id;
2193 	uint8_t i;
2194 
2195 
2196 	/* Register with scan component */
2197 	req_id = wlan_scan_register_requester(mac_ctx->psoc,
2198 					      "RRM",
2199 					      sme_rrm_scan_event_callback,
2200 					      mac_ctx);
2201 
2202 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2203 		smerrmctx = &mac_ctx->rrm.rrmSmeContext[i];
2204 		smerrmctx->req_id = req_id;
2205 	}
2206 
2207 	return QDF_STATUS_SUCCESS;
2208 }
2209 
rrm_stop(struct mac_context * mac_ctx)2210 QDF_STATUS rrm_stop(struct mac_context *mac_ctx)
2211 {
2212 	tpRrmSMEContext smerrmctx;
2213 	wlan_scan_requester req_id;
2214 	uint8_t i;
2215 
2216 	for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) {
2217 		smerrmctx = &mac_ctx->rrm.rrmSmeContext[i];
2218 		req_id = smerrmctx->req_id;
2219 		smerrmctx->req_id = 0;
2220 	}
2221 
2222 	wlan_scan_unregister_requester(mac_ctx->psoc, req_id);
2223 
2224 	return QDF_STATUS_SUCCESS;
2225 }
2226