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