blob: 68f0aeeef87422b4678462b28dfb82b11030e8b6 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/** ------------------------------------------------------------------------- *
29 ------------------------------------------------------------------------- *
30
31 \file csr_api_scan.c
32
33 Implementation for the Common Scan interfaces.
34 ========================================================================== */
35
36#include "ani_global.h"
37
38#include "cds_mq.h"
39#include "csr_inside_api.h"
40#include "sme_inside.h"
41#include "sms_debug.h"
42
43#include "csr_support.h"
44
45#include "host_diag_core_log.h"
46#include "host_diag_core_event.h"
47
48#include "cds_reg_service.h"
49#include "wma_types.h"
50#include "cds_utils.h"
51#include "cfg_api.h"
52#include "lim_api.h"
53#include "wma.h"
54
55#include "cds_concurrency.h"
56#include "wlan_hdd_main.h"
57
58#define MIN_CHN_TIME_TO_FIND_GO 100
59#define MAX_CHN_TIME_TO_FIND_GO 100
60#define DIRECT_SSID_LEN 7
61
62/* Purpose of HIDDEN_TIMER
63** When we remove hidden ssid from the profile i.e., forget the SSID via GUI that SSID shouldn't see in the profile
64** For above requirement we used timer limit, logic is explained below
65** Timer value is initialsed to current time when it receives corresponding probe response of hidden SSID (The probe request is
66** received regularly till SSID in the profile. Once it is removed from profile probe request is not sent.) when we receive probe response
67** for broadcast probe request, during update SSID with saved SSID we will diff current time with saved SSID time if it is greater than 1 min
68** then we are not updating with old one
69*/
70
71#define HIDDEN_TIMER (1*60*1000)
72#define CSR_SCAN_RESULT_RSSI_WEIGHT 80 /* must be less than 100, represent the persentage of new RSSI */
73
74#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL 140
75#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL 120
76
77#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 30
78#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 20
79
80#define PCL_ADVANTAGE 30
81#define PCL_RSSI_THRESHOLD -75
82
83#define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \
84 ((pMac)->scan.nBssLimit <= (csr_ll_count(&(pMac)->scan.scanResultList)))
85
86void csr_scan_get_result_timer_handler(void *);
87static void csr_scan_result_cfg_aging_timer_handler(void *pv);
88static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType,
89 tCsrScanRequest *pScanRequest);
90#ifdef WLAN_AP_STA_CONCURRENCY
91static void csr_sta_ap_conc_timer_handler(void *);
92#endif
93bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId);
94CDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand);
95void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList,
96 uint8_t NumChannels);
97void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList,
98 uint32_t cfgId);
99void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode);
100void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList);
101void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
102 eCsrScanStatus scanStatus);
103static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac, uint8_t *pChannels,
104 uint8_t numChn,
105 tSirBssDescription *pBssDesc,
106 tDot11fBeaconIEs **ppIes);
107bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel);
108void csr_prune_channel_list_for_mode(tpAniSirGlobal pMac,
109 tCsrChannel *pChannelList);
110
111#define CSR_IS_SOCIAL_CHANNEL(channel) \
112 (((channel) == 1) || ((channel) == 6) || ((channel) == 11))
113
114static void csr_release_scan_cmd_pending_list(tpAniSirGlobal pMac)
115{
116 tListElem *pEntry;
117 tSmeCmd *pCommand;
118
119 while ((pEntry =
120 csr_ll_remove_head(&pMac->scan.scanCmdPendingList,
121 LL_ACCESS_LOCK)) != NULL) {
122 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
123 if (eSmeCsrCommandMask & pCommand->command) {
124 csr_abort_command(pMac, pCommand, true);
125 } else {
126 sms_log(pMac, LOGE, FL("Error: Received command : %d"),
127 pCommand->command);
128 }
129 }
130}
131
132/* pResult is invalid calling this function. */
133void csr_free_scan_result_entry(tpAniSirGlobal pMac, tCsrScanResult *pResult)
134{
135 if (NULL != pResult->Result.pvIes) {
136 cdf_mem_free(pResult->Result.pvIes);
137 }
138 cdf_mem_free(pResult);
139}
140
141static CDF_STATUS csr_ll_scan_purge_result(tpAniSirGlobal pMac,
142 tDblLinkList *pList)
143{
144 CDF_STATUS status = CDF_STATUS_SUCCESS;
145 tListElem *pEntry;
146 tCsrScanResult *pBssDesc;
147
148 csr_ll_lock(pList);
149
150 while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) {
151 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
152 csr_free_scan_result_entry(pMac, pBssDesc);
153 }
154
155 csr_ll_unlock(pList);
156
157 return status;
158}
159
160CDF_STATUS csr_scan_open(tpAniSirGlobal mac_ctx)
161{
162 CDF_STATUS status;
163
164 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanResultList);
165 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.tempScanResults);
166 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList24);
167 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList5G);
168#ifdef WLAN_AP_STA_CONCURRENCY
169 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanCmdPendingList);
170#endif
171 mac_ctx->scan.fFullScanIssued = false;
172 mac_ctx->scan.nBssLimit = CSR_MAX_BSS_SUPPORT;
173#ifdef WLAN_AP_STA_CONCURRENCY
174 status = cdf_mc_timer_init(&mac_ctx->scan.hTimerStaApConcTimer,
175 CDF_TIMER_TYPE_SW,
176 csr_sta_ap_conc_timer_handler,
177 mac_ctx);
178 if (!CDF_IS_STATUS_SUCCESS(status)) {
179 sms_log(mac_ctx, LOGE,
180 FL("Mem Alloc failed for hTimerStaApConcTimer timer"));
181 return status;
182 }
183#endif
184 status = cdf_mc_timer_init(&mac_ctx->scan.hTimerResultCfgAging,
185 CDF_TIMER_TYPE_SW,
186 csr_scan_result_cfg_aging_timer_handler,
187 mac_ctx);
188 if (!CDF_IS_STATUS_SUCCESS(status))
189 sms_log(mac_ctx, LOGE,
190 FL("Mem Alloc failed for CFG ResultAging timer"));
191
192 return status;
193}
194
195CDF_STATUS csr_scan_close(tpAniSirGlobal pMac)
196{
197 csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults);
198 csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList);
199#ifdef WLAN_AP_STA_CONCURRENCY
200 csr_release_scan_cmd_pending_list(pMac);
201#endif
202 csr_ll_close(&pMac->scan.scanResultList);
203 csr_ll_close(&pMac->scan.tempScanResults);
204#ifdef WLAN_AP_STA_CONCURRENCY
205 csr_ll_close(&pMac->scan.scanCmdPendingList);
206#endif
207 csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList24);
208 csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList5G);
209 csr_ll_close(&pMac->scan.channelPowerInfoList24);
210 csr_ll_close(&pMac->scan.channelPowerInfoList5G);
211 csr_scan_disable(pMac);
212 cdf_mc_timer_destroy(&pMac->scan.hTimerResultCfgAging);
213#ifdef WLAN_AP_STA_CONCURRENCY
214 cdf_mc_timer_destroy(&pMac->scan.hTimerStaApConcTimer);
215#endif
216 return CDF_STATUS_SUCCESS;
217}
218
219CDF_STATUS csr_scan_enable(tpAniSirGlobal pMac)
220{
221
222 pMac->scan.fScanEnable = true;
223
224 return CDF_STATUS_SUCCESS;
225}
226
227CDF_STATUS csr_scan_disable(tpAniSirGlobal pMac)
228{
229
230 csr_scan_stop_timers(pMac);
231 pMac->scan.fScanEnable = false;
232
233 return CDF_STATUS_SUCCESS;
234}
235
236/* Set scan timing parameters according to state of other driver sessions */
237/* No validation of the parameters is performed. */
238static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType,
239 tCsrScanRequest *pScanRequest)
240{
241#ifdef WLAN_AP_STA_CONCURRENCY
242 if (csr_is_any_session_connected(pMac)) {
243 /* Reset passive scan time as per ini parameter. */
244 cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
245 pMac->roam.configParam.nPassiveMaxChnTimeConc);
246 /* If multi-session, use the appropriate default scan times */
247 if (scanType == eSIR_ACTIVE_SCAN) {
248 pScanRequest->maxChnTime =
249 pMac->roam.configParam.nActiveMaxChnTimeConc;
250 pScanRequest->minChnTime =
251 pMac->roam.configParam.nActiveMinChnTimeConc;
252 } else {
253 pScanRequest->maxChnTime =
254 pMac->roam.configParam.nPassiveMaxChnTimeConc;
255 pScanRequest->minChnTime =
256 pMac->roam.configParam.nPassiveMinChnTimeConc;
257 }
258 pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc;
259
260 /* Return so that fields set above will not be overwritten. */
261 return;
262 }
263#endif
264
265 /* This portion of the code executed if multi-session not supported */
266 /* (WLAN_AP_STA_CONCURRENCY not defined) or no multi-session. */
267 /* Use the "regular" (non-concurrency) default scan timing. */
268 cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
269 pMac->roam.configParam.nPassiveMaxChnTime);
270 if (pScanRequest->scanType == eSIR_ACTIVE_SCAN) {
271 pScanRequest->maxChnTime =
272 pMac->roam.configParam.nActiveMaxChnTime;
273 pScanRequest->minChnTime =
274 pMac->roam.configParam.nActiveMinChnTime;
275 } else {
276 pScanRequest->maxChnTime =
277 pMac->roam.configParam.nPassiveMaxChnTime;
278 pScanRequest->minChnTime =
279 pMac->roam.configParam.nPassiveMinChnTime;
280 }
281#ifdef WLAN_AP_STA_CONCURRENCY
282 /* No rest time if no sessions are connected. */
283 pScanRequest->restTime = 0;
284#endif
285}
286
287/**
288 * csr_scan_2g_only_request() - This function will update the scan request with
289 * only 2.4GHz valid channel list.
290 * @mac_ctx: Pointer to Global MAC structure
291 * @scan_cmd scan cmd
292 * @scan_req scan req
293 *
294 * This function will update the scan request with only 2.4GHz valid channel
295 * list.
296 *
297 * @Return: status of operation
298 */
299static CDF_STATUS
300csr_scan_2g_only_request(tpAniSirGlobal mac_ctx,
301 tSmeCmd *scan_cmd,
302 tCsrScanRequest *scan_req)
303{
304 uint8_t idx, lst_sz = 0;
305
306 CDF_ASSERT(scan_cmd && scan_req);
307 /* To silence the KW tool null check is added */
308 if ((scan_cmd == NULL) || (scan_req == NULL)) {
309 sms_log(mac_ctx, LOGE,
310 FL(" Scan Cmd or Scan Request is NULL "));
311 return CDF_STATUS_E_INVAL;
312 }
313
314 if (eCSR_SCAN_REQUEST_FULL_SCAN != scan_req->requestType)
315 return CDF_STATUS_SUCCESS;
316
317 sms_log(mac_ctx, LOG1,
318 FL("Scanning only 2G Channels during first scan"));
319
320 /* Contsruct valid Supported 2.4 GHz Channel List */
321 if (NULL == scan_req->ChannelInfo.ChannelList) {
322 scan_req->ChannelInfo.ChannelList =
323 cdf_mem_malloc(NUM_24GHZ_CHANNELS);
324 if (NULL == scan_req->ChannelInfo.ChannelList) {
325 sms_log(mac_ctx, LOGE, FL("Memory allocation failed."));
326 return CDF_STATUS_E_NOMEM;
327 }
328 for (idx = 1; idx <= NUM_24GHZ_CHANNELS; idx++) {
329 if (csr_is_supported_channel(mac_ctx, idx)) {
330 scan_req->ChannelInfo.ChannelList[lst_sz] = idx;
331 lst_sz++;
332 }
333 }
334 } else {
335 for (idx = 0;
336 idx < scan_req->ChannelInfo.numOfChannels;
337 idx++) {
338 if (scan_req->ChannelInfo.ChannelList[idx] <=
339 CDS_24_GHZ_CHANNEL_14
340 && csr_is_supported_channel(mac_ctx,
341 scan_req->ChannelInfo.ChannelList[idx])) {
342 scan_req->ChannelInfo.ChannelList[lst_sz] =
343 scan_req->ChannelInfo.ChannelList[idx];
344 lst_sz++;
345 }
346 }
347 }
348 scan_req->ChannelInfo.numOfChannels = lst_sz;
349 return CDF_STATUS_SUCCESS;
350}
351
352static void
353csr_set_scan_reason(tSmeCmd *scan_cmd, eCsrRequestType req_type)
354{
355 switch (req_type) {
356 case eCSR_SCAN_REQUEST_11D_SCAN:
357 scan_cmd->u.scanCmd.reason = eCsrScan11d1;
358 break;
359#ifdef SOFTAP_CHANNEL_RANGE
360 case eCSR_SCAN_SOFTAP_CHANNEL_RANGE:
361#endif
362 case eCSR_SCAN_REQUEST_FULL_SCAN:
363 case eCSR_SCAN_P2P_DISCOVERY:
364 scan_cmd->u.scanCmd.reason = eCsrScanUserRequest;
365 break;
366 case eCSR_SCAN_HO_PROBE_SCAN:
367 scan_cmd->u.scanCmd.reason = eCsrScanProbeBss;
368 break;
369 case eCSR_SCAN_P2P_FIND_PEER:
370 scan_cmd->u.scanCmd.reason = eCsrScanP2PFindPeer;
371 break;
372 default:
373 break;
374 }
375}
376
377static CDF_STATUS
378csr_issue_11d_scan(tpAniSirGlobal mac_ctx, tSmeCmd *scan_cmd,
379 tCsrScanRequest *scan_req, uint16_t session_id)
380{
381 CDF_STATUS status;
382 tSmeCmd *scan_11d_cmd = NULL;
383 tCsrScanRequest tmp_rq;
384 tCsrChannelInfo *pChnInfo = &tmp_rq.ChannelInfo;
385 uint32_t numChn = mac_ctx->scan.base_channels.numChannels;
386 tCsrRoamSession *csr_session = CSR_GET_SESSION(mac_ctx, session_id);
387
388 if (csr_session == NULL) {
389 sms_log(mac_ctx, LOGE, FL("session %d not found"),
390 session_id);
391 CDF_ASSERT(0);
392 return CDF_STATUS_E_FAILURE;
393 }
394
395 if (!(((false == mac_ctx->first_scan_done)
396 && (eCSR_SCAN_REQUEST_11D_SCAN != scan_req->requestType))
397#ifdef SOFTAP_CHANNEL_RANGE
398 && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != scan_req->requestType)
399#endif
400 && (false == mac_ctx->scan.fEnableBypass11d)))
401 return CDF_STATUS_SUCCESS;
402
403 cdf_mem_set(&tmp_rq, sizeof(tCsrScanRequest), 0);
404 scan_11d_cmd = csr_get_command_buffer(mac_ctx);
405 if (!scan_11d_cmd) {
406 sms_log(mac_ctx, LOGE, FL("scan_11d_cmd failed"));
407 return CDF_STATUS_E_FAILURE;
408 }
409
410 cdf_mem_set(&scan_11d_cmd->u.scanCmd, sizeof(tScanCmd), 0);
411 pChnInfo->ChannelList = cdf_mem_malloc(numChn);
412 if (NULL == pChnInfo->ChannelList) {
413 sms_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
414 return CDF_STATUS_E_NOMEM;
415 }
416 cdf_mem_copy(pChnInfo->ChannelList,
417 mac_ctx->scan.base_channels.channelList, numChn);
418
419 pChnInfo->numOfChannels = (uint8_t) numChn;
420 scan_11d_cmd->command = eSmeCommandScan;
421 scan_11d_cmd->u.scanCmd.callback = mac_ctx->scan.callback11dScanDone;
422 scan_11d_cmd->u.scanCmd.pContext = NULL;
423 wma_get_scan_id(&scan_11d_cmd->u.scanCmd.scanID);
424 tmp_rq.BSSType = eCSR_BSS_TYPE_ANY;
425 tmp_rq.scan_id = scan_11d_cmd->u.scanCmd.scanID;
426
427 status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
428 CDF_TIMER_TYPE_SW,
429 csr_scan_active_list_timeout_handle, &scan_11d_cmd);
430
431 if (csr_is11d_supported(mac_ctx)) {
432 tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan;
433 if (scan_req->bcnRptReqScan)
434 tmp_rq.scanType = scan_req->scanType ?
435 eSIR_PASSIVE_SCAN : scan_req->scanType;
436 else
437 tmp_rq.scanType = eSIR_PASSIVE_SCAN;
438 tmp_rq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
439 scan_11d_cmd->u.scanCmd.reason = eCsrScan11d1;
440 tmp_rq.maxChnTime =
441 mac_ctx->roam.configParam.nPassiveMaxChnTime;
442 tmp_rq.minChnTime =
443 mac_ctx->roam.configParam.nPassiveMinChnTime;
444 } else {
445 tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan;
446 if (scan_req->bcnRptReqScan)
447 tmp_rq.scanType = scan_req->scanType;
448 else
449 tmp_rq.scanType = eSIR_ACTIVE_SCAN;
450 tmp_rq.requestType = scan_req->requestType;
451 scan_11d_cmd->u.scanCmd.reason = scan_cmd->u.scanCmd.reason;
452 tmp_rq.maxChnTime = mac_ctx->roam.configParam.nActiveMaxChnTime;
453 tmp_rq.minChnTime = mac_ctx->roam.configParam.nActiveMinChnTime;
454 }
455 if (mac_ctx->roam.configParam.nInitialDwellTime) {
456 tmp_rq.maxChnTime = mac_ctx->roam.configParam.nInitialDwellTime;
457 sms_log(mac_ctx, LOG1, FL("11d scan, updating dwell time for first scan %u"),
458 tmp_rq.maxChnTime);
459 }
460
461 status = csr_scan_copy_request(mac_ctx,
462 &scan_11d_cmd->u.scanCmd.u.scanRequest, &tmp_rq);
463 /* Free the channel list */
464 cdf_mem_free(pChnInfo->ChannelList);
465 pChnInfo->ChannelList = NULL;
466 if (!CDF_IS_STATUS_SUCCESS(status)) {
467 sms_log(mac_ctx, LOGE, FL("csr_scan_copy_request failed"));
468 return CDF_STATUS_E_FAILURE;
469 }
470
471 mac_ctx->scan.scanProfile.numOfChannels =
472 scan_11d_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
473
474
475 status = csr_queue_sme_command(mac_ctx, scan_11d_cmd, false);
476 if (!CDF_IS_STATUS_SUCCESS(status)) {
477 sms_log(mac_ctx, LOGE, FL("Failed to send message status = %d"),
478 status);
479 return CDF_STATUS_E_FAILURE;
480 }
481 return CDF_STATUS_SUCCESS;
482}
483
484CDF_STATUS csr_scan_request(tpAniSirGlobal pMac, uint16_t sessionId,
485 tCsrScanRequest *scan_req,
486 csr_scan_completeCallback callback, void *pContext)
487{
488 CDF_STATUS status = CDF_STATUS_E_FAILURE;
489 tSmeCmd *scan_cmd = NULL;
490 tCsrScanRequest *pTempScanReq = NULL;
491 tCsrConfig *cfg_prm = &pMac->roam.configParam;
492
493 if (scan_req == NULL) {
494 sms_log(pMac, LOGE, FL("scan_req is NULL"));
495 CDF_ASSERT(0);
496 return status;
497 }
498
499 /*
500 * During group formation, the P2P client scans for GO with the specific
501 * SSID. There will be chances of GO switching to other channels because
502 * of scan or to STA channel in case of STA+GO MCC scenario. So to
503 * increase the possibility of client to find the GO, the dwell time of
504 * scan is increased to 100ms.
505 * If the scan request is for specific SSId the length of SSID will be
506 * greater than 7 as SSID for p2p search contains "DIRECT-")
507 */
508 if (scan_req->p2pSearch
509 && scan_req->SSIDs.numOfSSIDs
510 && (NULL != scan_req->SSIDs.SSIDList)
511 && (scan_req->SSIDs.SSIDList->SSID.length > DIRECT_SSID_LEN)) {
512 sms_log(pMac, LOG1, FL("P2P: Increasing the min and max Dwell time to %d for specific SSID scan %.*s"),
513 MAX_CHN_TIME_TO_FIND_GO,
514 scan_req->SSIDs.SSIDList->SSID.length,
515 scan_req->SSIDs.SSIDList->SSID.ssId);
516 scan_req->maxChnTime = MAX_CHN_TIME_TO_FIND_GO;
517 scan_req->minChnTime = MIN_CHN_TIME_TO_FIND_GO;
518 }
519
520 if (!pMac->scan.fScanEnable) {
521 sms_log(pMac, LOGE, FL("SId: %d Scanning not enabled Scan type=%u, numOfSSIDs=%d P2P search=%d"),
522 sessionId, scan_req->requestType,
523 scan_req->SSIDs.numOfSSIDs,
524 scan_req->p2pSearch);
525 goto release_cmd;
526 }
527
528 scan_cmd = csr_get_command_buffer(pMac);
529 if (!scan_cmd) {
530 sms_log(pMac, LOGE, FL("scan_cmd is NULL"));
531 goto release_cmd;
532 }
533
534 cdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0);
535 scan_cmd->command = eSmeCommandScan;
536 scan_cmd->sessionId = sessionId;
537 if (scan_cmd->sessionId >= CSR_ROAM_SESSION_MAX)
538 sms_log(pMac, LOGE, FL("Invalid Sme SessionID: %d"), sessionId);
539 scan_cmd->u.scanCmd.callback = callback;
540 scan_cmd->u.scanCmd.pContext = pContext;
541 csr_set_scan_reason(scan_cmd, scan_req->requestType);
542 if (scan_req->minChnTime == 0 && scan_req->maxChnTime == 0) {
543 /* The caller doesn't set the time correctly. Set it here */
544 csr_set_default_scan_timing(pMac, scan_req->scanType, scan_req);
545 sms_log(pMac, LOG1,
546 FL("Setting default min %d and max %d ChnTime"),
547 scan_req->minChnTime, scan_req->maxChnTime);
548 }
549#ifdef WLAN_AP_STA_CONCURRENCY
550 /* Need to set restTime only if at least one session is connected */
551 if (scan_req->restTime == 0 && csr_is_any_session_connected(pMac)) {
552 scan_req->restTime = cfg_prm->nRestTimeConc;
553 if (scan_req->scanType == eSIR_ACTIVE_SCAN) {
554 scan_req->maxChnTime = cfg_prm->nActiveMaxChnTimeConc;
555 scan_req->minChnTime = cfg_prm->nActiveMinChnTimeConc;
556 } else {
557 scan_req->maxChnTime = cfg_prm->nPassiveMaxChnTimeConc;
558 scan_req->minChnTime = cfg_prm->nPassiveMinChnTimeConc;
559 }
560 }
561#endif
562 /* Increase dwell time in case P2P Search and Miracast is not present */
563 if (scan_req->p2pSearch && scan_req->ChannelInfo.numOfChannels
564 == P2P_SOCIAL_CHANNELS && (!(pMac->sme.miracast_value))) {
565 scan_req->maxChnTime += P2P_SEARCH_DWELL_TIME_INCREASE;
566 }
567 scan_cmd->u.scanCmd.scanID = scan_req->scan_id;
568 /*
569 * If it is the first scan request from HDD, CSR checks if it is for 11d
570 * If it is not, CSR will save the scan request in the pending cmd queue
571 * & issue an 11d scan request to PE.
572 */
573 status = csr_issue_11d_scan(pMac, scan_cmd, scan_req, sessionId);
574 if (status != CDF_STATUS_SUCCESS)
575 goto release_cmd;
576
577 /*
578 * Scan only 2G Channels if set in ini file. This is mainly to reduce
579 * the First Scan duration once we turn on Wifi
580 */
581 if (pMac->scan.fFirstScanOnly2GChnl
582 && false == pMac->first_scan_done) {
583 csr_scan_2g_only_request(pMac, scan_cmd, scan_req);
584 pMac->first_scan_done = true;
585 }
586
587
588 if (cfg_prm->nInitialDwellTime) {
589 scan_req->maxChnTime = cfg_prm->nInitialDwellTime;
590 cfg_prm->nInitialDwellTime = 0;
591 sms_log(pMac, LOG1, FL("updating dwell time for first scan %u"),
592 scan_req->maxChnTime);
593 }
594
595 status = csr_scan_copy_request(pMac, &scan_cmd->u.scanCmd.u.scanRequest,
596 scan_req);
597 /*
598 * Reset the variable after the first scan is queued after loading the
599 * driver. The purpose of this parameter is that DFS channels are
600 * skipped during the first scan after loading the driver. The above API
601 * builds the target scan request in which this variable is used.
602 */
603 cfg_prm->initial_scan_no_dfs_chnl = 0;
604 if (!CDF_IS_STATUS_SUCCESS(status)) {
605 sms_log(pMac, LOGE,
606 FL("fail to copy request status = %d"), status);
607 goto release_cmd;
608 }
609
610 pTempScanReq = &scan_cmd->u.scanCmd.u.scanRequest;
611 pMac->scan.scanProfile.numOfChannels =
612 pTempScanReq->ChannelInfo.numOfChannels;
613 status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
614 CDF_TIMER_TYPE_SW,
615 csr_scan_active_list_timeout_handle, scan_cmd);
616 sms_log(pMac, LOG1,
617 FL("SId=%d scanId=%d Scan reason=%u numSSIDs=%d numChan=%d P2P search=%d minCT=%d maxCT=%d uIEFieldLen=%d"),
618 sessionId, scan_cmd->u.scanCmd.scanID,
619 scan_cmd->u.scanCmd.reason, pTempScanReq->SSIDs.numOfSSIDs,
620 pTempScanReq->ChannelInfo.numOfChannels,
621 pTempScanReq->p2pSearch, pTempScanReq->minChnTime,
622 pTempScanReq->maxChnTime, pTempScanReq->uIEFieldLen);
623
624 status = csr_queue_sme_command(pMac, scan_cmd, false);
625 if (!CDF_IS_STATUS_SUCCESS(status)) {
626 sms_log(pMac, LOGE,
627 FL("fail to send message status = %d"), status);
628 }
629
630release_cmd:
631 if (!CDF_IS_STATUS_SUCCESS(status) && scan_cmd) {
632 sms_log(pMac, LOGE, FL(" SId: %d Failed with status=%d"
633 " Scan reason=%u numOfSSIDs=%d"
634 " P2P search=%d scanId=%d"),
635 sessionId, status, scan_cmd->u.scanCmd.reason,
636 scan_req->SSIDs.numOfSSIDs, scan_req->p2pSearch,
637 scan_cmd->u.scanCmd.scanID);
638 csr_release_command_scan(pMac, scan_cmd);
639 }
640
641 return status;
642}
643
644CDF_STATUS csr_issue_roam_after_lostlink_scan(tpAniSirGlobal pMac,
645 uint32_t sessionId,
646 eCsrRoamReason reason)
647{
648 CDF_STATUS status = CDF_STATUS_E_FAILURE;
649 tScanResultHandle hBSSList = NULL;
650 tCsrScanResultFilter *pScanFilter = NULL;
651 uint32_t roamId = 0;
652 tCsrRoamProfile *pProfile = NULL;
653 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
654
655 if (!pSession) {
656 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
657 return CDF_STATUS_E_FAILURE;
658 }
659
660 sms_log(pMac, LOG1, FL("Entry"));
661 if (pSession->fCancelRoaming) {
662 sms_log(pMac, LOGW, FL("lost link roaming canceled"));
663 status = CDF_STATUS_SUCCESS;
664 goto free_filter;
665 }
666 /* Here is the profile we need to connect to */
667 pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
668 if (NULL == pScanFilter) {
669 status = CDF_STATUS_E_NOMEM;
670 goto free_filter;
671 }
672 cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
673 if (NULL == pSession->pCurRoamProfile) {
674 pScanFilter->EncryptionType.numEntries = 1;
675 pScanFilter->EncryptionType.encryptionType[0] =
676 eCSR_ENCRYPT_TYPE_NONE;
677 } else {
678 /*
679 * We have to make a copy of pCurRoamProfile because it will
680 * be free inside csr_roam_issue_connect
681 */
682 pProfile = cdf_mem_malloc(sizeof(tCsrRoamProfile));
683 if (NULL == pProfile) {
684 status = CDF_STATUS_E_NOMEM;
685 goto free_filter;
686 }
687 cdf_mem_set(pProfile, sizeof(tCsrRoamProfile), 0);
688 status = csr_roam_copy_profile(pMac, pProfile,
689 pSession->pCurRoamProfile);
690 if (!CDF_IS_STATUS_SUCCESS(status))
691 goto free_filter;
692 status = csr_roam_prepare_filter_from_profile(pMac, pProfile,
693 pScanFilter);
694 } /* We have a profile */
695 roamId = GET_NEXT_ROAM_ID(&pMac->roam);
696 if (!CDF_IS_STATUS_SUCCESS(status))
697 goto free_filter;
698
699 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
700 if (!CDF_IS_STATUS_SUCCESS(status))
701 goto free_filter;
702
703 if (eCsrLostLink1 == reason) {
704 /* if possible put the last connected BSS in beginning */
705 csr_move_bss_to_head_from_bssid(pMac,
706 &pSession->connectedProfile.bssid, hBSSList);
707 }
708 status = csr_roam_issue_connect(pMac, sessionId, pProfile, hBSSList,
709 reason, roamId, true, true);
710 if (!CDF_IS_STATUS_SUCCESS(status)) {
711 csr_scan_result_purge(pMac, hBSSList);
712 }
713
714free_filter:
715 if (pScanFilter) {
716 /* we need to free memory for filter if profile exists */
717 csr_free_scan_filter(pMac, pScanFilter);
718 cdf_mem_free(pScanFilter);
719 }
720 if (NULL != pProfile) {
721 csr_release_profile(pMac, pProfile);
722 cdf_mem_free(pProfile);
723 }
724 return status;
725}
726
727CDF_STATUS csr_scan_handle_failed_lostlink1(tpAniSirGlobal pMac,
728 uint32_t sessionId)
729{
730 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
731
732 if (!pSession) {
733 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
734 return CDF_STATUS_E_FAILURE;
735 }
736 sms_log(pMac, LOGW, "Lost link scan 1 failed");
737 if (pSession->fCancelRoaming)
738 return CDF_STATUS_E_FAILURE;
739 if (!pSession->pCurRoamProfile)
740 return csr_scan_request_lost_link3(pMac, sessionId);
741 /*
742 * We fail lostlink1 but there may be other BSS in the cached result
743 * fit the profile. Give it a try first
744 */
745 if (pSession->pCurRoamProfile->SSIDs.numOfSSIDs == 0 ||
746 pSession->pCurRoamProfile->SSIDs.numOfSSIDs > 1)
747 /* try lostlink scan2 */
748 return csr_scan_request_lost_link2(pMac, sessionId);
749 if (!pSession->pCurRoamProfile->ChannelInfo.ChannelList
750 || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) {
751 /* go straight to lostlink scan3 */
752 return csr_scan_request_lost_link3(pMac, sessionId);
753 }
754 return CDF_STATUS_SUCCESS;
755}
756
757CDF_STATUS csr_scan_handle_failed_lostlink2(tpAniSirGlobal pMac,
758 uint32_t sessionId)
759{
760 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
761
762 if (!pSession) {
763 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
764 return CDF_STATUS_E_FAILURE;
765 }
766
767 sms_log(pMac, LOGW, "Lost link scan 2 failed");
768 if (pSession->fCancelRoaming)
769 return CDF_STATUS_E_FAILURE;
770
771 if (!pSession->pCurRoamProfile
772 || !pSession->pCurRoamProfile->ChannelInfo.ChannelList
773 || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) {
774 /* try lostlink scan3 */
775 return csr_scan_request_lost_link3(pMac, sessionId);
776 }
777 return CDF_STATUS_E_FAILURE;
778}
779
780CDF_STATUS csr_scan_handle_failed_lostlink3(tpAniSirGlobal pMac,
781 uint32_t sessionId)
782{
783 sms_log(pMac, LOGW, "Lost link scan 3 failed");
784 return CDF_STATUS_SUCCESS;
785}
786
787static CDF_STATUS
788csr_update_lost_link1_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
789 tCsrRoamSession *pSession, uint32_t session_id)
790{
791 uint8_t i, num_ch = 0;
792 tScanResultHandle bss_lst = NULL;
793 tCsrScanResultInfo *scan_result = NULL;
794 tCsrScanResultFilter *scan_filter = NULL;
795 CDF_STATUS status = CDF_STATUS_SUCCESS;
796 tCsrSSIDs *ssid_list = &cmd->u.scanCmd.u.scanRequest.SSIDs;
797 tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo;
798
799 cmd->command = eSmeCommandScan;
800 cmd->sessionId = (uint8_t) session_id;
801 cmd->u.scanCmd.reason = eCsrScanLostLink1;
802 cmd->u.scanCmd.callback = NULL;
803 cmd->u.scanCmd.pContext = NULL;
804 cmd->u.scanCmd.u.scanRequest.maxChnTime =
805 mac_ctx->roam.configParam.nActiveMaxChnTime;
806 cmd->u.scanCmd.u.scanRequest.minChnTime =
807 mac_ctx->roam.configParam.nActiveMinChnTime;
808 cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
809 wma_get_scan_id(&cmd->u.scanCmd.scanID);
810 status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
811 CDF_TIMER_TYPE_SW,
812 csr_scan_active_list_timeout_handle, &cmd);
813 cmd->u.scanCmd.u.scanRequest.scan_id =
814 cmd->u.scanCmd.scanID;
815
816 if (pSession->connectedProfile.SSID.length) {
817 /*
818 * on error: following memory will be released by call to
819 * csr_release_command_scan in the end
820 */
821 ssid_list->SSIDList = cdf_mem_malloc(sizeof(tCsrSSIDInfo));
822 if (NULL == ssid_list->SSIDList)
823 return CDF_STATUS_E_NOMEM;
824 ssid_list->numOfSSIDs = 1;
825 cdf_mem_copy(&ssid_list->SSIDList[0].SSID,
826 &pSession->connectedProfile.SSID,
827 sizeof(tSirMacSSid));
828 } else {
829 ssid_list->numOfSSIDs = 0;
830 }
831
832 if (!pSession->pCurRoamProfile)
833 return CDF_STATUS_SUCCESS;
834
835 scan_filter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
836 if (NULL == scan_filter)
837 return CDF_STATUS_E_NOMEM;
838
839 cdf_mem_set(scan_filter, sizeof(tCsrScanResultFilter), 0);
840 status = csr_roam_prepare_filter_from_profile(mac_ctx,
841 pSession->pCurRoamProfile, scan_filter);
842 if (!CDF_IS_STATUS_SUCCESS(status))
843 goto free_lost_link1_local_mem;
844
845 if (!(CDF_IS_STATUS_SUCCESS(csr_scan_get_result(mac_ctx, scan_filter,
846 &bss_lst)) && bss_lst)) {
847 if (csr_roam_is_channel_valid(mac_ctx,
848 pSession->connectedProfile.operationChannel)) {
849 ch_info->ChannelList = cdf_mem_malloc(1);
850 if (NULL == ch_info->ChannelList) {
851 status = CDF_STATUS_E_NOMEM;
852 goto free_lost_link1_local_mem;
853 }
854 ch_info->ChannelList[0] =
855 pSession->connectedProfile.operationChannel;
856 ch_info->numOfChannels = 1;
857 }
858 return status;
859 }
860
861 /* on error: this mem will be released by csr_release_command_scan */
862 ch_info->ChannelList = cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN);
863 if (NULL == ch_info->ChannelList) {
864 status = CDF_STATUS_E_NOMEM;
865 goto free_lost_link1_local_mem;
866 }
867
868 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
869 while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) {
870 for (i = 0; i < num_ch; i++) {
871 if (ch_info->ChannelList[i] ==
872 scan_result->BssDescriptor.channelId)
873 break;
874 }
875 if (i == num_ch)
876 ch_info->ChannelList[num_ch++] =
877 scan_result->BssDescriptor.channelId;
878 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
879 }
880 /* Include the last connected BSS' channel */
881 if (csr_roam_is_channel_valid(mac_ctx,
882 pSession->connectedProfile.operationChannel)) {
883 for (i = 0; i < num_ch; i++) {
884 if (ch_info->ChannelList[i] ==
885 pSession->connectedProfile.operationChannel)
886 break;
887 }
888 if (i == num_ch)
889 ch_info->ChannelList[num_ch++] =
890 pSession->connectedProfile.operationChannel;
891 }
892 ch_info->numOfChannels = num_ch;
893free_lost_link1_local_mem:
894 if (scan_filter) {
895 csr_free_scan_filter(mac_ctx, scan_filter);
896 cdf_mem_free(scan_filter);
897 }
898 if (bss_lst)
899 csr_scan_result_purge(mac_ctx, bss_lst);
900 return status;
901}
902
903/**
904 * csr_scan_request_lost_link1() - start scan on link lost 1
905 * @mac_ctx: mac global context
906 * @session_id: session id
907 *
908 * Lostlink1 scan is to actively scan the last connected profile's SSID on all
909 * matched BSS channels. If no roam profile (it should not), it is like
910 * lostlinkscan3
911 *
912 * Return: status of operation
913 */
914CDF_STATUS
915csr_scan_request_lost_link1(tpAniSirGlobal mac_ctx, uint32_t session_id)
916{
917 CDF_STATUS status = CDF_STATUS_SUCCESS;
918 tSmeCmd *cmd = NULL;
919 tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
920
921 if (!session) {
922 sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id);
923 return CDF_STATUS_E_FAILURE;
924 }
925
926 sms_log(mac_ctx, LOGW, FL("Entry"));
927 cmd = csr_get_command_buffer(mac_ctx);
928 if (!cmd) {
929 status = CDF_STATUS_E_RESOURCES;
930 goto release_lost_link1_cmd;
931 }
932 cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
933 status = csr_update_lost_link1_cmd(mac_ctx, cmd, session, session_id);
934 if (!CDF_IS_STATUS_SUCCESS(status))
935 goto release_lost_link1_cmd;
936
937 cdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid,
938 sizeof(struct cdf_mac_addr), 0xFF);
939 status = csr_queue_sme_command(mac_ctx, cmd, false);
940 if (!CDF_IS_STATUS_SUCCESS(status)) {
941 sms_log(mac_ctx, LOGE,
942 FL("fail to send message status = %d"), status);
943 }
944
945release_lost_link1_cmd:
946 if (!CDF_IS_STATUS_SUCCESS(status)) {
947 sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
948 if (cmd)
949 csr_release_command_scan(mac_ctx, cmd);
950 status = csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
951 }
952 return status;
953}
954
955static CDF_STATUS
956csr_update_lost_link2_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
957 uint32_t session_id, tCsrRoamSession *session)
958{
959 CDF_STATUS status = CDF_STATUS_SUCCESS;
960 uint8_t i, num_ch = 0;
961 tScanResultHandle bss_lst = NULL;
962 tCsrScanResultInfo *scan_result = NULL;
963 tCsrScanResultFilter *scan_fltr = NULL;
964 tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo;
965
966 cmd->command = eSmeCommandScan;
967 cmd->sessionId = (uint8_t) session_id;
968 cmd->u.scanCmd.reason = eCsrScanLostLink2;
969 cmd->u.scanCmd.callback = NULL;
970 cmd->u.scanCmd.pContext = NULL;
971 cmd->u.scanCmd.u.scanRequest.maxChnTime =
972 mac_ctx->roam.configParam.nActiveMaxChnTime;
973 cmd->u.scanCmd.u.scanRequest.minChnTime =
974 mac_ctx->roam.configParam.nActiveMinChnTime;
975 cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
976 wma_get_scan_id(&cmd->u.scanCmd.scanID);
977 cmd->u.scanCmd.u.scanRequest.scan_id =
978 cmd->u.scanCmd.scanID;
979 if (!session->pCurRoamProfile)
980 return CDF_STATUS_SUCCESS;
981 status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
982 CDF_TIMER_TYPE_SW,
983 csr_scan_active_list_timeout_handle, &cmd);
984 scan_fltr = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
985 if (NULL == scan_fltr)
986 return CDF_STATUS_E_NOMEM;
987
988 cdf_mem_set(scan_fltr, sizeof(tCsrScanResultFilter), 0);
989 status = csr_roam_prepare_filter_from_profile(mac_ctx,
990 session->pCurRoamProfile, scan_fltr);
991 if (!CDF_IS_STATUS_SUCCESS(status))
992 goto free_lost_link2_local_mem;
993
994 status = csr_scan_get_result(mac_ctx, scan_fltr, &bss_lst);
995 if (!CDF_IS_STATUS_SUCCESS(status))
996 goto free_lost_link2_local_mem;
997
998 if (!bss_lst)
999 goto free_lost_link2_local_mem;
1000
1001 ch_info->ChannelList = cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN);
1002 if (NULL == ch_info->ChannelList) {
1003 status = CDF_STATUS_E_NOMEM;
1004 goto free_lost_link2_local_mem;
1005 }
1006 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
1007 while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) {
1008 for (i = 0; i < num_ch; i++) {
1009 if (ch_info->ChannelList[i] ==
1010 scan_result->BssDescriptor.channelId)
1011 break;
1012 }
1013 if (i == num_ch)
1014 ch_info->ChannelList[num_ch++] =
1015 scan_result->BssDescriptor.channelId;
1016 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
1017 }
1018 ch_info->numOfChannels = num_ch;
1019
1020free_lost_link2_local_mem:
1021 if (scan_fltr) {
1022 csr_free_scan_filter(mac_ctx, scan_fltr);
1023 cdf_mem_free(scan_fltr);
1024 }
1025 if (bss_lst)
1026 csr_scan_result_purge(mac_ctx, bss_lst);
1027 return status;
1028}
1029
1030/**
1031 * csr_scan_request_lost_link2() - start scan on link lost 2
1032 * @mac_ctx: mac global context
1033 * @session_id: session id
1034 *
1035 * Lostlink2 scan is to actively scan the all SSIDs of the last roaming
1036 * profile's on all matched BSS channels. Since MAC doesn't support multiple
1037 * SSID, we scan all SSIDs and filter them afterwards
1038 *
1039 * Return: status of operation
1040 */
1041CDF_STATUS
1042csr_scan_request_lost_link2(tpAniSirGlobal mac_ctx, uint32_t session_id)
1043{
1044 CDF_STATUS status = CDF_STATUS_SUCCESS;
1045 tSmeCmd *cmd = NULL;
1046 tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
1047
1048 if (!session) {
1049 sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id);
1050 return CDF_STATUS_E_FAILURE;
1051 }
1052
1053 sms_log(mac_ctx, LOGW, FL(" called"));
1054 cmd = csr_get_command_buffer(mac_ctx);
1055 if (!cmd) {
1056 status = CDF_STATUS_E_RESOURCES;
1057 goto release_lost_link2_cmd;
1058 }
1059 cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
1060 status = csr_update_lost_link2_cmd(mac_ctx, cmd, session_id, session);
1061 if (!CDF_IS_STATUS_SUCCESS(status))
1062 goto release_lost_link2_cmd;
1063
1064 cdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid,
1065 sizeof(struct cdf_mac_addr), 0xFF);
1066 /* Put to the head in pending queue */
1067 status = csr_queue_sme_command(mac_ctx, cmd, true);
1068 if (!CDF_IS_STATUS_SUCCESS(status)) {
1069 sms_log(mac_ctx, LOGE,
1070 FL("fail to send message status = %d"), status);
1071 goto release_lost_link2_cmd;
1072 }
1073
1074release_lost_link2_cmd:
1075 if (!CDF_IS_STATUS_SUCCESS(status)) {
1076 sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
1077 if (cmd)
1078 csr_release_command_scan(mac_ctx, cmd);
1079 status = csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
1080 }
1081 return status;
1082}
1083
1084/**
1085 * csr_scan_request_lost_link3() - To actively scan all valid channels
1086 * @mac_ctx: mac global context
1087 * @session_id: session id
1088 *
1089 * Return: status of operation
1090 */
1091CDF_STATUS
1092csr_scan_request_lost_link3(tpAniSirGlobal mac_ctx, uint32_t session_id)
1093{
1094 CDF_STATUS status = CDF_STATUS_SUCCESS;
1095 tSmeCmd *cmd;
1096
1097 sms_log(mac_ctx, LOGW, FL(" called"));
1098 do {
1099 cmd = csr_get_command_buffer(mac_ctx);
1100 if (!cmd) {
1101 status = CDF_STATUS_E_RESOURCES;
1102 break;
1103 }
1104 cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
1105 cmd->command = eSmeCommandScan;
1106 cmd->sessionId = (uint8_t) session_id;
1107 cmd->u.scanCmd.reason = eCsrScanLostLink3;
1108 cmd->u.scanCmd.callback = NULL;
1109 cmd->u.scanCmd.pContext = NULL;
1110 cmd->u.scanCmd.u.scanRequest.maxChnTime =
1111 mac_ctx->roam.configParam.nActiveMaxChnTime;
1112 cmd->u.scanCmd.u.scanRequest.minChnTime =
1113 mac_ctx->roam.configParam.nActiveMinChnTime;
1114 cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
1115 wma_get_scan_id(&cmd->u.scanCmd.scanID);
1116 status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
1117 CDF_TIMER_TYPE_SW,
1118 csr_scan_active_list_timeout_handle, &cmd);
1119 cmd->u.scanCmd.u.scanRequest.scan_id =
1120 cmd->u.scanCmd.scanID;
1121 cdf_set_macaddr_broadcast(&cmd->u.scanCmd.u.scanRequest.bssid);
1122 /* Put to the head of pending queue */
1123 status = csr_queue_sme_command(mac_ctx, cmd, true);
1124 if (!CDF_IS_STATUS_SUCCESS(status)) {
1125 sms_log(mac_ctx, LOGE,
1126 FL("fail to send message status = %d"), status);
1127 break;
1128 }
1129 } while (0);
1130 if (!CDF_IS_STATUS_SUCCESS(status)) {
1131 sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
1132 if (cmd)
1133 csr_release_command_scan(mac_ctx, cmd);
1134 }
1135
1136 return status;
1137}
1138
1139CDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal pMac,
1140 tSmeCmd *pCommand)
1141{
1142 CDF_STATUS status = CDF_STATUS_E_FAILURE;
1143 tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE;
1144 tCsrScanResultFilter *pScanFilter = NULL;
1145 tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
1146 uint32_t sessionId = pCommand->sessionId;
1147
1148 do {
1149 /* If this scan is for LFR */
1150 if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) {
1151 /* notify LFR state m/c */
1152 status = csr_neighbor_roam_sssid_scan_done(pMac,
1153 sessionId, CDF_STATUS_SUCCESS);
1154 if (CDF_STATUS_SUCCESS != status)
1155 csr_neighbor_roam_start_lfr_scan(pMac,
1156 sessionId);
1157 status = CDF_STATUS_SUCCESS;
1158 break;
1159 }
1160 /*
1161 * If there is roam command waiting, ignore this roam because
1162 * the newer roam command is the one to execute
1163 */
1164 if (csr_is_roam_command_waiting_for_session(pMac, sessionId)) {
1165 sms_log(pMac, LOGW,
1166 FL("aborts because roam command waiting"));
1167 break;
1168 }
1169 if (pProfile == NULL)
1170 break;
1171 pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
1172 if (NULL == pScanFilter) {
1173 status = CDF_STATUS_E_NOMEM;
1174 break;
1175 }
1176 cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
1177 status = csr_roam_prepare_filter_from_profile(pMac, pProfile,
1178 pScanFilter);
1179 if (!CDF_IS_STATUS_SUCCESS(status))
1180 break;
1181 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
1182 if (!CDF_IS_STATUS_SUCCESS(status))
1183 break;
1184 status = csr_roam_issue_connect(pMac, sessionId, pProfile,
1185 hBSSList, eCsrHddIssued,
1186 pCommand->u.scanCmd.roamId,
1187 true, true);
1188 } while (0);
1189
1190 if (!CDF_IS_STATUS_SUCCESS(status)) {
1191 if (CSR_INVALID_SCANRESULT_HANDLE != hBSSList) {
1192 csr_scan_result_purge(pMac, hBSSList);
1193 }
1194 /* We haven't done anything to this profile */
1195 csr_roam_call_callback(pMac, sessionId, NULL,
1196 pCommand->u.scanCmd.roamId,
1197 eCSR_ROAM_ASSOCIATION_FAILURE,
1198 eCSR_ROAM_RESULT_FAILURE);
1199 }
1200 if (pScanFilter) {
1201 csr_free_scan_filter(pMac, pScanFilter);
1202 cdf_mem_free(pScanFilter);
1203 }
1204 return status;
1205}
1206
1207CDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal pMac,
1208 tSmeCmd *pCommand)
1209{
1210 CDF_STATUS status = CDF_STATUS_SUCCESS;
1211 uint32_t sessionId = pCommand->sessionId;
1212 tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
1213 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
1214 eCsrRoamResult roam_result;
1215
1216 if (!pSession) {
1217 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
1218 return CDF_STATUS_E_FAILURE;
1219 }
1220 /* If this scan is for LFR */
1221 if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) {
1222 /* notify LFR state m/c */
1223 status = csr_neighbor_roam_sssid_scan_done(pMac, sessionId,
1224 CDF_STATUS_E_FAILURE);
1225 if (CDF_STATUS_SUCCESS != status)
1226 csr_neighbor_roam_start_lfr_scan(pMac, sessionId);
1227 return CDF_STATUS_SUCCESS;
1228 }
1229#ifdef WLAN_DEBUG
1230 if (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1) {
1231 char str[36];
1232 tSirMacSSid *ptr_ssid =
1233 &pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID;
1234 cdf_mem_copy(str, ptr_ssid->ssId, ptr_ssid->length);
1235 str[ptr_ssid->length] = 0;
1236 sms_log(pMac, LOGW, FL("SSID = %s"), str);
1237 }
1238#endif
1239 /*
1240 * Check whether it is for start ibss. No need to do anything if it
1241 * is a JOIN request
1242 */
1243 if (pProfile && CSR_IS_START_IBSS(pProfile)) {
1244 status = csr_roam_issue_connect(pMac, sessionId, pProfile, NULL,
1245 eCsrHddIssued, pCommand->u.scanCmd.roamId,
1246 true, true);
1247 if (!CDF_IS_STATUS_SUCCESS(status)) {
1248 sms_log(pMac, LOGE,
1249 FL("failed to issue startIBSS, status: 0x%08X"),
1250 status);
1251 csr_roam_call_callback(pMac, sessionId, NULL,
1252 pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED,
1253 eCSR_ROAM_RESULT_FAILURE);
1254 }
1255 return status;
1256 }
1257 roam_result = eCSR_ROAM_RESULT_FAILURE;
1258 if (NULL != pProfile && csr_is_bss_type_ibss(pProfile->BSSType)) {
1259 roam_result = eCSR_ROAM_RESULT_IBSS_START_FAILED;
1260 goto roam_completion;
1261 }
1262 /* Only indicate assoc_completion if we indicate assoc_start. */
1263 if (pSession->bRefAssocStartCnt > 0) {
1264 tCsrRoamInfo *pRoamInfo = NULL, roamInfo;
1265
1266 cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
1267 pRoamInfo = &roamInfo;
1268 if (pCommand->u.roamCmd.pRoamBssEntry) {
1269 tCsrScanResult *pScanResult = GET_BASE_ADDR(
1270 pCommand->u.roamCmd.pRoamBssEntry,
1271 tCsrScanResult, Link);
1272 roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor;
1273 }
1274 roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
1275 roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
1276 pSession->bRefAssocStartCnt--;
1277 csr_roam_call_callback(pMac, sessionId, pRoamInfo,
1278 pCommand->u.scanCmd.roamId,
1279 eCSR_ROAM_ASSOCIATION_COMPLETION,
1280 eCSR_ROAM_RESULT_FAILURE);
1281 } else {
1282 csr_roam_call_callback(pMac, sessionId, NULL,
1283 pCommand->u.scanCmd.roamId,
1284 eCSR_ROAM_ASSOCIATION_FAILURE,
1285 eCSR_ROAM_RESULT_FAILURE);
1286 }
1287roam_completion:
1288 csr_roam_completion(pMac, sessionId, NULL, pCommand, roam_result,
1289 false);
1290 return status;
1291}
1292
1293CDF_STATUS csr_scan_result_purge(tpAniSirGlobal pMac,
1294 tScanResultHandle hScanList)
1295{
1296 CDF_STATUS status = CDF_STATUS_E_INVAL;
1297 tScanResultList *pScanList = (tScanResultList *) hScanList;
1298
1299 if (pScanList) {
1300 status = csr_ll_scan_purge_result(pMac, &pScanList->List);
1301 csr_ll_close(&pScanList->List);
1302 cdf_mem_free(pScanList);
1303 }
1304 return status;
1305}
1306
1307/**
1308 * csr_derive_prefer_value_from_rssi() - to derive prefer value
1309 * @mac_ctx: Global MAC Context
1310 * @rssi: RSSI of the BSS
1311 *
1312 * This routine will derive preferred value from given rssi
1313 *
1314 * Return: value between 0 to 14
1315 */
1316static int csr_derive_prefer_value_from_rssi(tpAniSirGlobal mac_ctx, int rssi)
1317{
1318 int i = CSR_NUM_RSSI_CAT - 1, pref_val = 0;
1319 while (i >= 0) {
1320 if (rssi >= mac_ctx->roam.configParam.RSSICat[i]) {
1321 pref_val = mac_ctx->roam.configParam.BssPreferValue[i];
1322 break;
1323 }
1324 i--;
1325 };
1326 return pref_val;
1327}
1328
1329/**
1330 * is_channel_found_in_pcl() - to check if channel is present in pcl
1331 * @mac_ctx: Global MAC Context
1332 * @channel_id: channel of bss
1333 * @filter: pointer to filter created through profile
1334 *
1335 * to check if provided channel is present in pcl
1336 *
1337 * Return: true or false
1338 */
1339static bool is_channel_found_in_pcl(tpAniSirGlobal mac_ctx, int channel_id,
1340 tCsrScanResultFilter *filter)
1341{
1342 int i;
1343 bool status = false;
1344
1345 if (NULL == filter)
1346 return status;
1347
1348 for (i = 0; i < filter->pcl_channels.numChannels; i++) {
1349 if (filter->pcl_channels.channelList[i] == channel_id) {
1350 status = true;
1351 break;
1352 }
1353 }
1354 return status;
1355}
1356/**
1357 * csr_get_altered_rssi() - Artificially increase/decrease RSSI
1358 * @mac_ctx: Global MAC Context pointer.
1359 * @rssi: Actual RSSI of the AP.
1360 * @channel_id: Channel on which the AP is parked.
1361 * @bssid: BSSID of the AP to connect to.
1362 *
1363 * This routine will apply the boost and penalty parameters
1364 * if the channel_id is of 5G band and it will also apply
1365 * the preferred bssid score if there is a match between
1366 * the bssid and the global preferred bssid list.
1367 *
1368 * Return: The modified RSSI Value
1369 */
1370static int csr_get_altered_rssi(tpAniSirGlobal mac_ctx, int rssi,
1371 uint8_t channel_id, struct cdf_mac_addr *bssid)
1372{
1373 int modified_rssi;
1374 int boost_factor;
1375 int penalty_factor;
1376 int i;
1377 struct roam_ext_params *roam_params;
1378 struct cdf_mac_addr fav_bssid;
1379 struct cdf_mac_addr local_bssid;
1380
1381 modified_rssi = rssi;
1382 cdf_mem_zero(&local_bssid.bytes, CDF_MAC_ADDR_SIZE);
1383 if (bssid)
1384 cdf_mem_copy(local_bssid.bytes, bssid->bytes,
1385 CDF_MAC_ADDR_SIZE);
1386 roam_params = &mac_ctx->roam.configParam.roam_params;
1387 /*
1388 * If the 5G pref feature is enabled, apply the roaming
1389 * parameters to boost or penalize the rssi.
1390 * Boost Factor = boost_factor * (Actual RSSI - boost Threshold)
1391 * Penalty Factor = penalty factor * (penalty threshold - Actual RSSI)
1392 */
1393 if (CSR_IS_SELECT_5G_PREFERRED(mac_ctx) &&
1394 CDS_IS_CHANNEL_5GHZ(channel_id)) {
1395 if (rssi > roam_params->raise_rssi_thresh_5g) {
1396 /* Check and boost the threshold*/
1397 boost_factor = roam_params->raise_factor_5g *
1398 (rssi - roam_params->raise_rssi_thresh_5g);
1399 /* Check and penalize the threshold */
1400 modified_rssi += CSR_MIN(roam_params->max_raise_rssi_5g,
1401 boost_factor);
1402 } else if (rssi < roam_params->drop_rssi_thresh_5g) {
1403 penalty_factor = roam_params->drop_factor_5g *
1404 (roam_params->drop_rssi_thresh_5g - rssi);
1405 modified_rssi -= CSR_MAX(roam_params->max_drop_rssi_5g,
1406 penalty_factor);
1407 }
1408 sms_log(mac_ctx, LOG2,
1409 FL("5G BSSID"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"),
1410 MAC_ADDR_ARRAY(local_bssid.bytes),
1411 rssi, modified_rssi, channel_id);
1412 }
1413 /*
1414 * Check if there are preferred bssid and then apply the
1415 * preferred score
1416 */
1417 cdf_mem_zero(&fav_bssid.bytes, CDF_MAC_ADDR_SIZE);
1418 if (roam_params->num_bssid_favored) {
1419 for (i = 0; i < roam_params->num_bssid_favored; i++) {
1420 cdf_mem_copy(fav_bssid.bytes,
1421 &roam_params->bssid_favored[i],
1422 CDF_MAC_ADDR_SIZE);
1423 if (!cdf_is_macaddr_equal(&fav_bssid, bssid))
1424 continue;
1425 modified_rssi += roam_params->bssid_favored_factor[i];
1426 sms_log(mac_ctx, LOG2,
1427 FL("Pref"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"),
1428 MAC_ADDR_ARRAY(local_bssid.bytes),
1429 rssi, modified_rssi, channel_id);
1430 }
1431 }
1432 return modified_rssi;
1433}
1434
1435/**
1436 * csr_get_bss_prefer_value() - Get the preference value for BSS
1437 * @mac_ctx: Global MAC Context
1438 * @rssi: RSSI of the BSS
1439 * @bssid: BSSID to which the preference value is returned
1440 * @channel_id: Channel on which the AP is parked
1441 *
1442 * Each BSS descriptor should be assigned a preference value ranging from
1443 * 14-0, which will be used as an RSSI bucket score while sorting the
1444 * scan results.
1445 *
1446 * Return: Preference value for the BSSID
1447 */
1448static uint32_t csr_get_bss_prefer_value(tpAniSirGlobal mac_ctx, int rssi,
1449 struct cdf_mac_addr *bssid, int channel_id)
1450{
1451 uint32_t ret = 0;
1452 int modified_rssi;
1453
1454 /*
1455 * The RSSI does not get modified in case the 5G
1456 * preference or preferred BSSID is not applicable
1457 */
1458 modified_rssi = csr_get_altered_rssi(mac_ctx, rssi, channel_id, bssid);
1459 ret = csr_derive_prefer_value_from_rssi(mac_ctx, modified_rssi);
1460
1461 return ret;
1462}
1463
1464/* Return a CapValue base on the capabilities of a BSS */
1465static uint32_t csr_get_bss_cap_value(tpAniSirGlobal pMac,
1466 tSirBssDescription *pBssDesc,
1467 tDot11fBeaconIEs *pIes)
1468{
1469 uint32_t ret = CSR_BSS_CAP_VALUE_NONE;
1470#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
1471 if (CSR_IS_ROAM_PREFER_5GHZ(pMac) || CSR_IS_SELECT_5G_PREFERRED(pMac)) {
1472 if ((pBssDesc) && CDS_IS_CHANNEL_5GHZ(pBssDesc->channelId)) {
1473 ret += CSR_BSS_CAP_VALUE_5GHZ;
1474 }
1475 }
1476#endif
1477 /*
1478 * if strict select 5GHz is non-zero then ignore the capability checking
1479 */
1480 if (pIes && !CSR_IS_SELECT_5GHZ_MARGIN(pMac)) {
1481 /* We only care about 11N capability */
1482 if (pIes->VHTCaps.present)
1483 ret += CSR_BSS_CAP_VALUE_VHT;
1484 else if (pIes->HTCaps.present)
1485 ret += CSR_BSS_CAP_VALUE_HT;
1486 if (CSR_IS_QOS_BSS(pIes)) {
1487 ret += CSR_BSS_CAP_VALUE_WMM;
1488 /* Give advantage to UAPSD */
1489 if (CSR_IS_UAPSD_BSS(pIes)) {
1490 ret += CSR_BSS_CAP_VALUE_UAPSD;
1491 }
1492 }
1493 }
1494
1495 return ret;
1496}
1497
1498/**
1499 * csr_is_better_rssi() - Is bss1 better than bss2
1500 * @mac_ctx: Global MAC Context pointer.
1501 * @bss1: Pointer to the first BSS.
1502 * @bss2: Pointer to the second BSS.
1503 *
1504 * This routine helps in determining the preference value
1505 * of a particular BSS in the scan result which is further
1506 * used in the sorting logic of the final candidate AP's.
1507 *
1508 * Return: true, if bss1 is better than bss2
1509 * false, if bss2 is better than bss1.
1510 */
1511static bool csr_is_better_rssi(tpAniSirGlobal mac_ctx,
1512 tCsrScanResult *bss1, tCsrScanResult *bss2)
1513{
1514 bool ret;
1515 int rssi1, rssi2;
1516 struct cdf_mac_addr local_mac;
1517
1518 rssi1 = bss1->Result.BssDescriptor.rssi;
1519 rssi2 = bss2->Result.BssDescriptor.rssi;
1520 /*
1521 * Apply the boost and penlty logic and check
1522 * which is the best RSSI
1523 */
1524 cdf_mem_zero(&local_mac.bytes, CDF_MAC_ADDR_SIZE);
1525 cdf_mem_copy(&local_mac.bytes,
1526 &bss1->Result.BssDescriptor.bssId, CDF_MAC_ADDR_SIZE);
1527 rssi1 = csr_get_altered_rssi(mac_ctx, rssi1,
1528 bss1->Result.BssDescriptor.channelId,
1529 &local_mac);
1530 cdf_mem_copy(&local_mac.bytes,
1531 &bss2->Result.BssDescriptor.bssId, CDF_MAC_ADDR_SIZE);
1532 rssi2 = csr_get_altered_rssi(mac_ctx, rssi2,
1533 bss2->Result.BssDescriptor.channelId,
1534 &local_mac);
1535 if (CSR_IS_BETTER_RSSI(rssi1, rssi2))
1536 ret = true;
1537 else
1538 ret = false;
1539 return ret;
1540}
1541
1542/**
1543 * csr_is_better_bss() - Is bss1 better than bss2
1544 * @mac_ctx: Global MAC Context pointer.
1545 * @bss1: Pointer to the first BSS.
1546 * @bss2: Pointer to the second BSS.
1547 *
1548 * This routine helps in determining the preference value
1549 * of a particular BSS in the scan result which is further
1550 * used in the sorting logic of the final candidate AP's.
1551 *
1552 * Return: true, if bss1 is better than bss2
1553 * false, if bss2 is better than bss1.
1554 */
1555static bool csr_is_better_bss(tpAniSirGlobal mac_ctx,
1556 tCsrScanResult *bss1, tCsrScanResult *bss2)
1557{
1558 bool ret;
1559
1560 if (CSR_IS_BETTER_PREFER_VALUE(bss1->preferValue, bss2->preferValue)) {
1561 ret = true;
1562 } else if (CSR_IS_EQUAL_PREFER_VALUE
1563 (bss1->preferValue, bss2->preferValue)) {
1564 if (CSR_IS_BETTER_CAP_VALUE(bss1->capValue, bss2->capValue))
1565 ret = true;
1566 else if (CSR_IS_EQUAL_CAP_VALUE
1567 (bss1->capValue, bss2->capValue)) {
1568 if (csr_is_better_rssi(mac_ctx, bss1, bss2))
1569 ret = true;
1570 else
1571 ret = false;
1572 } else {
1573 ret = false;
1574 }
1575 } else {
1576 ret = false;
1577 }
1578
1579 return ret;
1580}
1581
1582#ifdef FEATURE_WLAN_LFR
1583/* Add the channel to the occupiedChannels array */
1584static void csr_scan_add_to_occupied_channels(tpAniSirGlobal pMac,
1585 tCsrScanResult *pResult,
1586 uint8_t sessionId,
1587 tCsrChannel *occupied_ch,
1588 tDot11fBeaconIEs *pIes)
1589{
1590 CDF_STATUS status;
1591 uint8_t ch;
1592 uint8_t num_occupied_ch = occupied_ch->numChannels;
1593 uint8_t *occupied_ch_lst = occupied_ch->channelList;
1594
1595 ch = pResult->Result.BssDescriptor.channelId;
1596 if (csr_is_channel_present_in_list(occupied_ch_lst, num_occupied_ch, ch)
1597 || !csr_neighbor_roam_connected_profile_match(pMac, sessionId,
1598 pResult, pIes))
1599 return;
1600
1601 status = csr_add_to_channel_list_front(occupied_ch_lst,
1602 num_occupied_ch, ch);
1603 if (CDF_IS_STATUS_SUCCESS(status)) {
1604 occupied_ch->numChannels++;
1605 sms_log(pMac, LOG2,
1606 FL("Added channel %d to the list (count=%d)"),
1607 ch, occupied_ch->numChannels);
1608 if (occupied_ch->numChannels >
1609 CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN)
1610 occupied_ch->numChannels =
1611 CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN;
1612 }
1613}
1614#endif
1615
1616/* Put the BSS into the scan result list */
1617/* pIes can not be NULL */
1618static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult,
1619 tDot11fBeaconIEs *pIes, uint32_t sessionId)
1620{
1621#ifdef FEATURE_WLAN_LFR
1622 tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
1623 &pMac->roam.neighborRoamInfo[sessionId];
1624#endif
1625
1626 struct cdf_mac_addr bssid;
1627 uint8_t channel_id = pResult->Result.BssDescriptor.channelId;
1628 cdf_mem_zero(&bssid.bytes, CDF_MAC_ADDR_SIZE);
1629 cdf_mem_copy(bssid.bytes, &pResult->Result.BssDescriptor.bssId,
1630 CDF_MAC_ADDR_SIZE);
1631 pResult->preferValue = csr_get_bss_prefer_value(pMac,
1632 (int)pResult->Result.BssDescriptor.rssi,
1633 &bssid, channel_id);
1634 pResult->capValue = csr_get_bss_cap_value(pMac,
1635 &pResult->Result.BssDescriptor, pIes);
1636 csr_ll_insert_tail(&pMac->scan.scanResultList, &pResult->Link,
1637 LL_ACCESS_LOCK);
1638#ifdef FEATURE_WLAN_LFR
1639 if (0 == pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) {
1640 /*
1641 * Build the occupied channel list, only if
1642 * "gNeighborScanChannelList" is NOT set in the cfg.ini file
1643 */
1644 csr_scan_add_to_occupied_channels(pMac, pResult, sessionId,
1645 &pMac->scan.occupiedChannels[sessionId], pIes);
1646 }
1647#endif
1648}
1649
1650static void
1651csr_parser_scan_result_for_5ghz_preference(tpAniSirGlobal pMac,
1652 tCsrScanResultFilter *pFilter)
1653{
1654 bool fMatch;
1655 CDF_STATUS status;
1656 tListElem *pEntry;
1657 tDot11fBeaconIEs *pIes;
1658 tCsrScanResult *pBssDesc;
1659 uint8_t i = 0;
1660
1661 /* Find out the best AP Rssi going thru the scan results */
1662 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
1663 while (NULL != pEntry) {
1664 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
1665 fMatch = false;
1666
1667 for (i = 0; pFilter && (i < pFilter->SSIDs.numOfSSIDs); i++) {
1668 fMatch = csr_is_ssid_match(pMac,
1669 pFilter->SSIDs.SSIDList[i].SSID.ssId,
1670 pFilter->SSIDs.SSIDList[i].SSID.length,
1671 pBssDesc->Result.ssId.ssId,
1672 pBssDesc->Result.ssId.length, true);
1673 if (!fMatch)
1674 continue;
1675
1676 pIes = (tDot11fBeaconIEs *)(pBssDesc->Result.pvIes);
1677 /* At this time, Result.pvIes may be NULL */
1678 status = csr_get_parsed_bss_description_ies(pMac,
1679 &pBssDesc->Result.BssDescriptor, &pIes);
1680 if (!pIes && (!CDF_IS_STATUS_SUCCESS(status)))
1681 continue;
1682
1683 sms_log(pMac, LOG1, FL("SSID Matched"));
1684 if (pFilter->bOSENAssociation) {
1685 fMatch = true;
1686 sms_log(pMac, LOG1, FL("Security Matched"));
1687 if ((pBssDesc->Result.pvIes == NULL) && pIes)
1688 cdf_mem_free(pIes);
1689 continue;
1690 }
1691#ifdef WLAN_FEATURE_11W
1692 fMatch = csr_is_security_match(pMac, &pFilter->authType,
1693 &pFilter->EncryptionType,
1694 &pFilter->mcEncryptionType,
1695 &pFilter->MFPEnabled,
1696 &pFilter->MFPRequired,
1697 &pFilter->MFPCapable,
1698 &pBssDesc->Result.BssDescriptor,
1699 pIes, NULL, NULL, NULL);
1700#else
1701 fMatch = csr_is_security_match(pMac, &pFilter->authType,
1702 &pFilter->EncryptionType,
1703 &pFilter->mcEncryptionType,
1704 NULL, NULL, NULL,
1705 &pBssDesc->Result.BssDescriptor,
1706 pIes, NULL, NULL, NULL);
1707#endif
1708 if ((pBssDesc->Result.pvIes == NULL) && pIes)
1709 cdf_mem_free(pIes);
1710 if (fMatch)
1711 sms_log(pMac, LOG1, FL("Security Matched"));
1712 } /* for loop ends */
1713
1714 if (fMatch
1715 && (pBssDesc->Result.BssDescriptor.rssi >
1716 pMac->scan.inScanResultBestAPRssi)) {
1717 sms_log(pMac, LOG1,
1718 FL("Best AP Rssi changed from %d to %d"),
1719 pMac->scan.inScanResultBestAPRssi,
1720 pBssDesc->Result.BssDescriptor.rssi);
1721 pMac->scan.inScanResultBestAPRssi =
1722 pBssDesc->Result.BssDescriptor.rssi;
1723 }
1724 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
1725 LL_ACCESS_NOLOCK);
1726 }
1727}
1728
1729static void
1730csr_prefer_5ghz(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter)
1731{
1732 tListElem *pEntry;
1733 tCsrScanResult *pBssDesc;
1734 struct roam_ext_params *roam_params = NULL;
1735
1736 if (!pMac->roam.configParam.nSelect5GHzMargin &&
1737 !CSR_IS_SELECT_5G_PREFERRED(pMac))
1738 return;
1739
1740 pMac->scan.inScanResultBestAPRssi = -128;
1741 roam_params = &pMac->roam.configParam.roam_params;
1742#ifdef WLAN_DEBUG_ROAM_OFFLOAD
1743 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
1744 FL("nSelect5GHzMargin"));
1745#endif
1746 csr_ll_lock(&pMac->scan.scanResultList);
1747 /*
1748 * For 5G preference feature, there is no
1749 * need to check the filter match and also re-program the
1750 * RSSI bucket categories, since we use the RSSI values
1751 * while setting the preference value for the BSS.
1752 * There is no need to check the match for roaming since
1753 * it is already done.
1754 */
1755 if (!CSR_IS_SELECT_5G_PREFERRED(pMac))
1756 csr_parser_scan_result_for_5ghz_preference(pMac, pFilter);
1757 if (-128 != pMac->scan.inScanResultBestAPRssi ||
1758 CSR_IS_SELECT_5G_PREFERRED(pMac)) {
1759 sms_log(pMac, LOG1, FL("Best AP Rssi is %d"),
1760 pMac->scan.inScanResultBestAPRssi);
1761 /* Modify Rssi category based on best AP Rssi */
1762 if (-128 != pMac->scan.inScanResultBestAPRssi)
1763 csr_assign_rssi_for_category(pMac,
1764 pMac->scan.inScanResultBestAPRssi,
1765 pMac->roam.configParam.bCatRssiOffset);
1766 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList,
1767 LL_ACCESS_NOLOCK);
1768 while (NULL != pEntry) {
1769 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
1770 /*
1771 * re-assign preference value based on modified
1772 * rssi bucket (or) 5G Preference feature.
1773 */
1774 pBssDesc->preferValue = csr_get_bss_prefer_value(pMac,
1775 (int)pBssDesc->Result.BssDescriptor.rssi,
1776 (struct cdf_mac_addr *)
1777 &pBssDesc->Result.BssDescriptor.bssId,
1778 pBssDesc->Result.BssDescriptor.channelId);
1779
1780 sms_log(pMac, LOG2, FL("BSSID("MAC_ADDRESS_STR") Rssi(%d) Chnl(%d) PrefVal(%u) SSID=%.*s"),
1781 MAC_ADDR_ARRAY(
1782 pBssDesc->Result.BssDescriptor.bssId),
1783 pBssDesc->Result.BssDescriptor.rssi,
1784 pBssDesc->Result.BssDescriptor.channelId,
1785 pBssDesc->preferValue,
1786 pBssDesc->Result.ssId.length,
1787 pBssDesc->Result.ssId.ssId);
1788 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
1789 LL_ACCESS_NOLOCK);
1790 }
1791 }
1792 csr_ll_unlock(&pMac->scan.scanResultList);
1793}
1794
1795static CDF_STATUS
1796csr_save_ies(tpAniSirGlobal pMac,
1797 tCsrScanResultFilter *pFilter,
1798 tCsrScanResult *pBssDesc,
1799 tDot11fBeaconIEs **pNewIes,
1800 bool *fMatch,
1801 eCsrEncryptionType *uc,
1802 eCsrEncryptionType *mc,
1803 eCsrAuthType *auth)
1804{
1805 CDF_STATUS status = CDF_STATUS_SUCCESS;
1806 tDot11fBeaconIEs *pIes = NULL;
1807
1808 if (!pFilter)
1809 return status;
1810 *fMatch = csr_match_bss(pMac, &pBssDesc->Result.BssDescriptor,
1811 pFilter, auth, uc, mc, &pIes);
1812#ifdef WLAN_DEBUG_ROAM_OFFLOAD
1813 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
1814 FL("csr_match_bss fmatch %d"), *fMatch);
1815#endif
1816 if (NULL == pIes)
1817 return status;
1818 /* Only save it when matching */
1819 if (!(*fMatch) && !pBssDesc->Result.pvIes) {
1820 cdf_mem_free(pIes);
1821 return status;
1822 }
1823 if (!pBssDesc->Result.pvIes) {
1824 /*
1825 * csr_match_bss allocates the memory. Simply pass it and it
1826 * is freed later
1827 */
1828 *pNewIes = pIes;
1829 return status;
1830 }
1831 /*
1832 * The pIes is allocated by someone else. make a copy
1833 * Only to save parsed IEs if caller provides a filter. Most likely the
1834 * caller is using to for association, hence save the parsed IEs
1835 */
1836 *pNewIes = cdf_mem_malloc(sizeof(tDot11fBeaconIEs));
1837 if (NULL == *pNewIes) {
1838 status = CDF_STATUS_E_NOMEM;
1839 sms_log(pMac, LOGE, FL("fail to allocate memory for IEs"));
1840 /* Need to free memory allocated by csr_match_bss */
1841 if (!pBssDesc->Result.pvIes)
1842 cdf_mem_free(pIes);
1843 return status;
1844 }
1845 cdf_mem_copy(*pNewIes, pIes, sizeof(tDot11fBeaconIEs));
1846 return status;
1847}
1848
1849static CDF_STATUS
1850csr_save_scan_entry(tpAniSirGlobal pMac,
1851 tCsrScanResultFilter *pFilter,
1852 bool fMatch,
1853 tCsrScanResult *pBssDesc,
1854 tDot11fBeaconIEs *pNewIes,
1855 tScanResultList *pRetList,
1856 uint32_t *count,
1857 eCsrEncryptionType uc,
1858 eCsrEncryptionType mc,
1859 eCsrAuthType *auth)
1860{
1861 CDF_STATUS status = CDF_STATUS_SUCCESS;
1862 tCsrScanResult *pResult;
1863 uint32_t bssLen, allocLen;
1864 /* To sort the list */
1865 tListElem *pTmpEntry;
1866 tCsrScanResult *pTmpResult;
1867
1868 if (!(NULL == pFilter || fMatch))
1869 return status;
1870
1871 bssLen = pBssDesc->Result.BssDescriptor.length +
1872 sizeof(pBssDesc->Result.BssDescriptor.length);
1873 allocLen = sizeof(tCsrScanResult) + bssLen;
1874 pResult = cdf_mem_malloc(allocLen);
1875 if (NULL == pResult) {
1876 status = CDF_STATUS_E_NOMEM;
1877 sms_log(pMac, LOGE,
1878 FL("fail to allocate memory for scan result, len=%d"),
1879 allocLen);
1880 if (pNewIes)
1881 cdf_mem_free(pNewIes);
1882 return status;
1883 }
1884 cdf_mem_set(pResult, allocLen, 0);
1885 pResult->capValue = pBssDesc->capValue;
1886 pResult->preferValue = pBssDesc->preferValue;
1887 pResult->ucEncryptionType = uc;
1888 pResult->mcEncryptionType = mc;
1889 pResult->authType = *auth;
1890 pResult->Result.ssId = pBssDesc->Result.ssId;
1891 pResult->Result.timer = pBssDesc->Result.timer;
1892 /* save the pIes for later use */
1893 pResult->Result.pvIes = pNewIes;
1894 /* save bss description */
1895 cdf_mem_copy(&pResult->Result.BssDescriptor,
1896 &pBssDesc->Result.BssDescriptor,
1897 bssLen);
1898 /*
1899 * No need to lock pRetList because it is locally allocated and no
1900 * outside can access it at this time
1901 */
1902 if (csr_ll_is_list_empty(&pRetList->List, LL_ACCESS_NOLOCK)) {
1903 csr_ll_insert_tail(&pRetList->List, &pResult->Link,
1904 LL_ACCESS_NOLOCK);
1905 (*count)++;
1906 return status;
1907 }
1908
1909 pTmpEntry = csr_ll_peek_head(&pRetList->List, LL_ACCESS_NOLOCK);
1910 while (pTmpEntry) {
1911 pTmpResult = GET_BASE_ADDR(pTmpEntry, tCsrScanResult, Link);
1912 if (csr_is_better_bss(pMac, pResult, pTmpResult)) {
1913 csr_ll_insert_entry(&pRetList->List, pTmpEntry,
1914 &pResult->Link, LL_ACCESS_NOLOCK);
1915 /* To indicate we are done */
1916 pResult = NULL;
1917 break;
1918 }
1919 pTmpEntry = csr_ll_next(&pRetList->List,
1920 pTmpEntry, LL_ACCESS_NOLOCK);
1921 }
1922 if (pResult != NULL) {
1923 /* This one is not better than any one */
1924 csr_ll_insert_tail(&pRetList->List, &pResult->Link,
1925 LL_ACCESS_NOLOCK);
1926 }
1927 (*count)++;
1928 return status;
1929}
1930
1931/**
1932 * csr_calc_pref_val_by_pcl() - to calculate preferred value
1933 * @mac_ctx: mac context
1934 * @filter: filter to find match from scan result
1935 * @bss_descr: pointer to bss descriptor
1936 *
1937 * this routine calculates the new preferred value to be given to
1938 * provided bss if its channel falls under preferred channel list.
1939 * Thump rule is higer the RSSI better the boost.
1940 *
1941 * Return: success or failure
1942 */
1943static CDF_STATUS csr_calc_pref_val_by_pcl(tpAniSirGlobal mac_ctx,
1944 tCsrScanResultFilter *filter,
1945 tCsrScanResult *bss_descr)
1946{
1947 int temp_rssi = 0, new_pref_val = 0;
1948 int orig_pref_val = 0;
1949
1950 if (NULL == mac_ctx || NULL == bss_descr)
1951 return CDF_STATUS_E_FAILURE;
1952
1953 if (mac_ctx->policy_manager_enabled &&
1954 is_channel_found_in_pcl(mac_ctx,
1955 bss_descr->Result.BssDescriptor.channelId, filter) &&
1956 (bss_descr->Result.BssDescriptor.rssi > PCL_RSSI_THRESHOLD)) {
1957 orig_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx,
1958 bss_descr->Result.BssDescriptor.rssi);
1959 temp_rssi = bss_descr->Result.BssDescriptor.rssi +
1960 (PCL_ADVANTAGE/(CSR_NUM_RSSI_CAT -
1961 orig_pref_val));
1962 if (temp_rssi > 0)
1963 temp_rssi = 0;
1964 new_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx,
1965 temp_rssi);
1966
1967 sms_log(mac_ctx, LOG1,
1968 FL("%pM: rssi:%d org pref=%d temp rssi:%d new pref=%d pref=%d updated pref=%d"),
1969 bss_descr->Result.BssDescriptor.bssId,
1970 bss_descr->Result.BssDescriptor.rssi,
1971 orig_pref_val, temp_rssi, new_pref_val,
1972 bss_descr->preferValue,
1973 CSR_MAX(new_pref_val, bss_descr->preferValue));
1974
1975 bss_descr->preferValue =
1976 CSR_MAX(new_pref_val, bss_descr->preferValue);
1977 }
1978 return CDF_STATUS_SUCCESS;
1979}
1980
1981static CDF_STATUS
1982csr_parse_scan_results(tpAniSirGlobal pMac,
1983 tCsrScanResultFilter *pFilter,
1984 tScanResultList *pRetList,
1985 uint32_t *count)
1986{
1987 CDF_STATUS status = CDF_STATUS_SUCCESS;
1988 tListElem *pEntry;
1989 bool fMatch = false;
1990 tCsrScanResult *pBssDesc = NULL;
1991 tDot11fBeaconIEs *pIes, *pNewIes = NULL;
1992 eCsrEncryptionType uc, mc;
1993 eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1994 uint32_t len = 0;
1995 enum cds_con_mode new_mode;
1996
1997
1998 csr_ll_lock(&pMac->scan.scanResultList);
1999
2000 if (pFilter) {
2001 if (cds_map_concurrency_mode(pMac->hHdd,
2002 &pFilter->csrPersona, &new_mode)) {
2003 status = cds_get_pcl(pMac->hHdd, new_mode,
2004 &pFilter->pcl_channels.channelList[0], &len);
2005 pFilter->pcl_channels.numChannels = (uint8_t)len;
2006 }
2007 }
2008
2009 if (CDF_STATUS_E_FAILURE == status)
2010 sms_log(pMac, CDF_TRACE_LEVEL_ERROR,
2011 FL("Retrieving pcl failed from HDD"));
2012 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
2013 while (pEntry) {
2014 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2015 pIes = (tDot11fBeaconIEs *) (pBssDesc->Result.pvIes);
2016 /*
2017 * if pBssDesc->Result.pvIes is NULL, we need to free any memory
2018 * allocated by csr_match_bss for any error condition,
2019 * otherwiase, it will be freed later
2020 */
2021 fMatch = false;
2022 pNewIes = NULL;
2023 status = csr_save_ies(pMac, pFilter, pBssDesc, &pNewIes,
2024 &fMatch, &uc, &mc, &auth);
2025 if (!CDF_IS_STATUS_SUCCESS(status))
2026 break;
2027 /*
2028 * Modify the prefer value to honor PCL list
2029 */
2030 if (pFilter && pFilter->pcl_channels.numChannels > 0)
2031 csr_calc_pref_val_by_pcl(pMac, pFilter, pBssDesc);
2032 status = csr_save_scan_entry(pMac, pFilter, fMatch, pBssDesc,
2033 pNewIes, pRetList, count, uc, mc,
2034 &auth);
2035 if (!CDF_IS_STATUS_SUCCESS(status))
2036 break;
2037 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
2038 LL_ACCESS_NOLOCK);
2039 } /* while */
2040 csr_ll_unlock(&pMac->scan.scanResultList);
2041 return status;
2042}
2043
2044CDF_STATUS csr_scan_get_result(tpAniSirGlobal pMac,
2045 tCsrScanResultFilter *pFilter,
2046 tScanResultHandle *phResult)
2047{
2048 CDF_STATUS status;
2049 tScanResultList *pRetList;
2050 uint32_t count = 0;
2051
2052 if (phResult)
2053 *phResult = CSR_INVALID_SCANRESULT_HANDLE;
2054
2055 csr_prefer_5ghz(pMac, pFilter);
2056
2057 pRetList = cdf_mem_malloc(sizeof(tScanResultList));
2058 if (NULL == pRetList)
2059 return CDF_STATUS_E_NOMEM;
2060
2061 cdf_mem_set(pRetList, sizeof(tScanResultList), 0);
2062 csr_ll_open(pMac->hHdd, &pRetList->List);
2063 pRetList->pCurEntry = NULL;
2064 status = csr_parse_scan_results(pMac, pFilter, pRetList, &count);
2065 sms_log(pMac, LOG2, FL("return %d BSS"), csr_ll_count(&pRetList->List));
2066 if (!CDF_IS_STATUS_SUCCESS(status) || (phResult == NULL)) {
2067 /* Fail or No one wants the result. */
2068 csr_scan_result_purge(pMac, (tScanResultHandle) pRetList);
2069 } else {
2070 if (0 == count) {
2071 /* We are here meaning the there is no match */
2072 csr_ll_close(&pRetList->List);
2073 cdf_mem_free(pRetList);
2074 status = CDF_STATUS_E_NULL_VALUE;
2075 } else if (phResult) {
2076 *phResult = pRetList;
2077 }
2078 }
2079 return status;
2080}
2081
2082/*
2083 * NOTE: This routine is being added to make
2084 * sure that scan results are not being flushed
2085 * while roaming. If the scan results are flushed,
2086 * we are unable to recover from
2087 * csr_roam_roaming_state_disassoc_rsp_processor.
2088 * If it is needed to remove this routine,
2089 * first ensure that we recover gracefully from
2090 * csr_roam_roaming_state_disassoc_rsp_processor if
2091 * csr_scan_get_result returns with a failure because
2092 * of not being able to find the roaming BSS.
2093 */
2094bool csr_scan_flush_denied(tpAniSirGlobal pMac)
2095{
2096 uint8_t sessionId;
2097
2098 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
2099 if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
2100 if (csr_neighbor_middle_of_roaming(pMac, sessionId))
2101 return 1;
2102 }
2103 }
2104 return 0;
2105}
2106
2107CDF_STATUS csr_scan_flush_result(tpAniSirGlobal pMac)
2108{
2109 bool isFlushDenied = csr_scan_flush_denied(pMac);
2110
2111 if (isFlushDenied) {
2112 sms_log(pMac, LOGW, "%s: scan flush denied in roam state %d",
2113 __func__, isFlushDenied);
2114 return CDF_STATUS_E_FAILURE;
2115 }
2116
2117 sms_log(pMac, LOG4, "%s: Flushing all scan results", __func__);
2118 csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults);
2119 csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList);
2120 return CDF_STATUS_SUCCESS;
2121}
2122
2123CDF_STATUS csr_scan_flush_selective_result(tpAniSirGlobal pMac, bool flushP2P)
2124{
2125 CDF_STATUS status = CDF_STATUS_SUCCESS;
2126 tListElem *pEntry, *pFreeElem;
2127 tCsrScanResult *pBssDesc;
2128 tDblLinkList *pList = &pMac->scan.scanResultList;
2129
2130 csr_ll_lock(pList);
2131
2132 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
2133 while (pEntry != NULL) {
2134 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2135 if (flushP2P == cdf_mem_compare(pBssDesc->Result.ssId.ssId,
2136 "DIRECT-", 7)) {
2137 pFreeElem = pEntry;
2138 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2139 csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK);
2140 csr_free_scan_result_entry(pMac, pBssDesc);
2141 continue;
2142 }
2143 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2144 }
2145
2146 csr_ll_unlock(pList);
2147
2148 return status;
2149}
2150
2151void csr_scan_flush_bss_entry(tpAniSirGlobal pMac,
2152 tpSmeCsaOffloadInd pCsaOffloadInd)
2153{
2154 tListElem *pEntry, *pFreeElem;
2155 tCsrScanResult *pBssDesc;
2156 tDblLinkList *pList = &pMac->scan.scanResultList;
2157
2158 csr_ll_lock(pList);
2159
2160 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
2161 while (pEntry != NULL) {
2162 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2163 if (cdf_mem_compare(pBssDesc->Result.BssDescriptor.bssId,
2164 pCsaOffloadInd->bssId, sizeof(tSirMacAddr))) {
2165 pFreeElem = pEntry;
2166 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2167 csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK);
2168 csr_free_scan_result_entry(pMac, pBssDesc);
2169 sms_log(pMac, LOG1, FL("Removed BSS entry:%pM"),
2170 pCsaOffloadInd->bssId);
2171 continue;
2172 }
2173
2174 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2175 }
2176
2177 csr_ll_unlock(pList);
2178}
2179
2180/**
2181 * csr_check11d_channel
2182 *
2183 ***FUNCTION:
2184 * This function is called from csr_scan_filter_results function and
2185 * compare channel number with given channel list.
2186 *
2187 ***LOGIC:
2188 * Check Scan result channel number with CFG channel list
2189 *
2190 ***ASSUMPTIONS:
2191 *
2192 *
2193 ***NOTE:
2194 *
2195 * @param channelId channel number
2196 * @param pChannelList Pointer to channel list
2197 * @param numChannels Number of channel in channel list
2198 *
2199 * @return Status
2200 */
2201
2202CDF_STATUS csr_check11d_channel(uint8_t channelId, uint8_t *pChannelList,
2203 uint32_t numChannels)
2204{
2205 CDF_STATUS status = CDF_STATUS_E_FAILURE;
2206 uint8_t i = 0;
2207
2208 for (i = 0; i < numChannels; i++) {
2209 if (pChannelList[i] == channelId) {
2210 status = CDF_STATUS_SUCCESS;
2211 break;
2212 }
2213 }
2214 return status;
2215}
2216
2217/**
2218 * csr_scan_filter_results
2219 *
2220 ***FUNCTION:
2221 * This function is called from csr_apply_country_information function and
2222 * filter scan result based on valid channel list number.
2223 *
2224 ***LOGIC:
2225 * Get scan result from scan list and Check Scan result channel number
2226 * with 11d channel list if channel number is found in 11d channel list
2227 * then do not remove scan result entry from scan list
2228 *
2229 ***ASSUMPTIONS:
2230 *
2231 *
2232 ***NOTE:
2233 *
2234 * @param pMac Pointer to Global MAC structure
2235 *
2236 * @return Status
2237 */
2238
2239CDF_STATUS csr_scan_filter_results(tpAniSirGlobal pMac)
2240{
2241 CDF_STATUS status = CDF_STATUS_SUCCESS;
2242 tListElem *pEntry, *pTempEntry;
2243 tCsrScanResult *pBssDesc;
2244 uint32_t len = sizeof(pMac->roam.validChannelList);
2245
2246 /* Get valid channels list from CFG */
2247 if (!CDF_IS_STATUS_SUCCESS(csr_get_cfg_valid_channels(pMac,
2248 pMac->roam.
2249 validChannelList,
2250 &len))) {
2251 sms_log(pMac, LOGE, "Failed to get Channel list from CFG");
2252 }
2253
2254 csr_ll_lock(&pMac->scan.scanResultList);
2255 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
2256 while (pEntry) {
2257 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2258 pTempEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
2259 LL_ACCESS_NOLOCK);
2260 if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId,
2261 pMac->roam.validChannelList, len)) {
2262 /* Remove Scan result which does not have 11d channel */
2263 if (csr_ll_remove_entry(&pMac->scan.scanResultList,
2264 pEntry, LL_ACCESS_NOLOCK)) {
2265 csr_free_scan_result_entry(pMac, pBssDesc);
2266 }
2267 } else {
2268 sms_log(pMac, LOG1, FL("%d is a Valid channel"),
2269 pBssDesc->Result.BssDescriptor.channelId);
2270 }
2271 pEntry = pTempEntry;
2272 }
2273
2274 csr_ll_unlock(&pMac->scan.scanResultList);
2275 csr_ll_lock(&pMac->scan.tempScanResults);
2276
2277 pEntry = csr_ll_peek_head(&pMac->scan.tempScanResults,
2278 LL_ACCESS_NOLOCK);
2279 while (pEntry) {
2280 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2281 pTempEntry = csr_ll_next(&pMac->scan.tempScanResults, pEntry,
2282 LL_ACCESS_NOLOCK);
2283 if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId,
2284 pMac->roam.validChannelList, len)) {
2285 /* Remove Scan result which does not have 11d channel */
2286 if (csr_ll_remove_entry
2287 (&pMac->scan.tempScanResults, pEntry,
2288 LL_ACCESS_NOLOCK)) {
2289 csr_free_scan_result_entry(pMac, pBssDesc);
2290 }
2291 } else {
2292 sms_log(pMac, LOG1, FL("%d is a Valid channel"),
2293 pBssDesc->Result.BssDescriptor.channelId);
2294 }
2295 pEntry = pTempEntry;
2296 }
2297
2298 csr_ll_unlock(&pMac->scan.tempScanResults);
2299 return status;
2300}
2301
2302CDF_STATUS csr_scan_copy_result_list(tpAniSirGlobal pMac, tScanResultHandle hIn,
2303 tScanResultHandle *phResult)
2304{
2305 CDF_STATUS status = CDF_STATUS_SUCCESS;
2306 tScanResultList *pRetList, *pInList = (tScanResultList *) hIn;
2307 tCsrScanResult *pResult, *pScanResult;
2308 uint32_t count = 0;
2309 tListElem *pEntry;
2310 uint32_t bssLen, allocLen;
2311
2312 if (phResult) {
2313 *phResult = CSR_INVALID_SCANRESULT_HANDLE;
2314 }
2315 pRetList = cdf_mem_malloc(sizeof(tScanResultList));
2316 if (NULL == pRetList)
2317 status = CDF_STATUS_E_NOMEM;
2318 else {
2319 cdf_mem_set(pRetList, sizeof(tScanResultList), 0);
2320 csr_ll_open(pMac->hHdd, &pRetList->List);
2321 pRetList->pCurEntry = NULL;
2322 csr_ll_lock(&pMac->scan.scanResultList);
2323 csr_ll_lock(&pInList->List);
2324
2325 pEntry = csr_ll_peek_head(&pInList->List, LL_ACCESS_NOLOCK);
2326 while (pEntry) {
2327 pScanResult =
2328 GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2329 bssLen =
2330 pScanResult->Result.BssDescriptor.length +
2331 sizeof(pScanResult->Result.BssDescriptor.length);
2332 allocLen = sizeof(tCsrScanResult) + bssLen;
2333 pResult = cdf_mem_malloc(allocLen);
2334 if (NULL == pResult)
2335 status = CDF_STATUS_E_NOMEM;
2336 else
2337 status = CDF_STATUS_SUCCESS;
2338 if (!CDF_IS_STATUS_SUCCESS(status)) {
2339 csr_scan_result_purge(pMac,
2340 (tScanResultHandle *)
2341 pRetList);
2342 count = 0;
2343 break;
2344 }
2345 cdf_mem_set(pResult, allocLen, 0);
2346 cdf_mem_copy(&pResult->Result.BssDescriptor,
2347 &pScanResult->Result.BssDescriptor,
2348 bssLen);
2349 if (pScanResult->Result.pvIes) {
2350 pResult->Result.pvIes =
2351 cdf_mem_malloc(sizeof(tDot11fBeaconIEs));
2352 if (NULL == pResult->Result.pvIes)
2353 status = CDF_STATUS_E_NOMEM;
2354 else
2355 status = CDF_STATUS_SUCCESS;
2356 if (!CDF_IS_STATUS_SUCCESS(status)) {
2357 /* Free the memory we allocate above first */
2358 cdf_mem_free(pResult);
2359 csr_scan_result_purge(pMac,
2360 (tScanResultHandle *)
2361 pRetList);
2362 count = 0;
2363 break;
2364 }
2365 cdf_mem_copy(pResult->Result.pvIes,
2366 pScanResult->Result.pvIes,
2367 sizeof(tDot11fBeaconIEs));
2368 }
2369 csr_ll_insert_tail(&pRetList->List, &pResult->Link,
2370 LL_ACCESS_LOCK);
2371 count++;
2372 pEntry =
2373 csr_ll_next(&pInList->List, pEntry, LL_ACCESS_NOLOCK);
2374 } /* while */
2375 csr_ll_unlock(&pInList->List);
2376 csr_ll_unlock(&pMac->scan.scanResultList);
2377
2378 if (CDF_IS_STATUS_SUCCESS(status)) {
2379 if (0 == count) {
2380 csr_ll_close(&pRetList->List);
2381 cdf_mem_free(pRetList);
2382 status = CDF_STATUS_E_NULL_VALUE;
2383 } else if (phResult) {
2384 *phResult = pRetList;
2385 }
2386 }
2387 } /* Allocated pRetList */
2388
2389 return status;
2390}
2391
2392CDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac,
2393 void *pMsgBuf)
2394{
2395 CDF_STATUS status = CDF_STATUS_SUCCESS;
2396 tSirMbMsg *pMsg = (tSirMbMsg *) pMsgBuf;
2397 tCsrRoamSession *pSession;
2398 tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
2399 tCsrRoamInfo roamInfo;
2400 tCsrRoamInfo *pRoamInfo = NULL;
2401 uint32_t sessionId;
2402
2403 if (eWNI_SME_SCAN_RSP == pMsg->type)
2404 return csr_scan_sme_scan_response(pMac, pMsgBuf);
2405
2406 if (pMsg->type != eWNI_SME_UPPER_LAYER_ASSOC_CNF) {
2407 if (csr_is_any_session_in_connect_state(pMac)) {
2408 /*
2409 * In case of we are connected, we need to check whether
2410 * connect status changes because scan may also run
2411 * while connected.
2412 */
2413 csr_roam_check_for_link_status_change(pMac,
2414 (tSirSmeRsp *) pMsgBuf);
2415 } else {
2416 sms_log(pMac, LOGW,
2417 FL("Message [0x%04x] received in wrong state"),
2418 pMsg->type);
2419 }
2420 return status;
2421 }
2422
2423 sms_log(pMac, LOG1,
2424 FL("Scanning: ASSOC cnf can be given to upper layer"));
2425 cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
2426 pRoamInfo = &roamInfo;
2427 pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *) pMsgBuf;
2428 status = csr_roam_get_session_id_from_bssid(pMac,
2429 (struct cdf_mac_addr *)pUpperLayerAssocCnf->bssId, &sessionId);
2430 pSession = CSR_GET_SESSION(pMac, sessionId);
2431
2432 if (!pSession) {
2433 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
2434 return CDF_STATUS_E_FAILURE;
2435 }
2436
2437 /* send the status code as Success */
2438 pRoamInfo->statusCode = eSIR_SME_SUCCESS;
2439 pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
2440 pRoamInfo->staId = (uint8_t) pUpperLayerAssocCnf->aid;
2441 pRoamInfo->rsnIELen = (uint8_t) pUpperLayerAssocCnf->rsnIE.length;
2442 pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata;
2443 pRoamInfo->addIELen = (uint8_t) pUpperLayerAssocCnf->addIE.length;
2444 pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata;
2445 cdf_mem_copy(pRoamInfo->peerMac.bytes,
2446 pUpperLayerAssocCnf->peerMacAddr,
2447 CDF_MAC_ADDR_SIZE);
2448 cdf_mem_copy(&pRoamInfo->bssid.bytes, pUpperLayerAssocCnf->bssId,
2449 CDF_MAC_ADDR_SIZE);
2450 pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta;
2451 if (CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile)) {
2452 pMac->roam.roamSession[sessionId].connectState =
2453 eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED;
2454 pRoamInfo->fReassocReq = pUpperLayerAssocCnf->reassocReq;
2455 status = csr_roam_call_callback(pMac, sessionId,
2456 pRoamInfo, 0,
2457 eCSR_ROAM_INFRA_IND,
2458 eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
2459 }
2460 if (CSR_IS_WDS_AP(pRoamInfo->u.pConnectedProfile)) {
2461 cdf_sleep(100);
2462 pMac->roam.roamSession[sessionId].connectState =
2463 eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED;
2464 status = csr_roam_call_callback(pMac, sessionId, pRoamInfo, 0,
2465 eCSR_ROAM_WDS_IND,
2466 eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);
2467 }
2468 return status;
2469}
2470
2471void csr_check_n_save_wsc_ie(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr,
2472 tSirBssDescription *pOldBssDescr)
2473{
2474 int idx, len;
2475 uint8_t *pbIe;
2476
2477 /* If failed to remove, assuming someone else got it. */
2478 if ((pNewBssDescr->fProbeRsp != pOldBssDescr->fProbeRsp) &&
2479 (0 == pNewBssDescr->WscIeLen)) {
2480 idx = 0;
2481 len = pOldBssDescr->length - sizeof(tSirBssDescription) +
2482 sizeof(uint16_t) + sizeof(uint32_t) -
2483 DOT11F_IE_WSCPROBERES_MIN_LEN - 2;
2484 pbIe = (uint8_t *) pOldBssDescr->ieFields;
2485 /* Save WPS IE if it exists */
2486 pNewBssDescr->WscIeLen = 0;
2487 while (idx < len) {
2488 if ((DOT11F_EID_WSCPROBERES == pbIe[0]) &&
2489 (0x00 == pbIe[2]) && (0x50 == pbIe[3])
2490 && (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) {
2491 /* Founrd it */
2492 if ((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >=
2493 pbIe[1]) {
2494 cdf_mem_copy(pNewBssDescr->
2495 WscIeProbeRsp, pbIe,
2496 pbIe[1] + 2);
2497 pNewBssDescr->WscIeLen = pbIe[1] + 2;
2498 }
2499 break;
2500 }
2501 idx += pbIe[1] + 2;
2502 pbIe += pbIe[1] + 2;
2503 }
2504 }
2505}
2506
2507/* pIes may be NULL */
2508bool csr_remove_dup_bss_description(tpAniSirGlobal pMac,
2509 tSirBssDescription *bss_dscp,
2510 tDot11fBeaconIEs *pIes, tAniSSID *pSsid,
2511 v_TIME_t *timer, bool fForced)
2512{
2513 tListElem *pEntry;
2514 tCsrScanResult *scan_entry;
2515 bool fRC = false;
2516 int8_t scan_entry_rssi = 0;
2517
2518 /*
2519 * Walk through all the chained BssDescriptions. If we find a chained
2520 * BssDescription that matches the BssID of the BssDescription passed
2521 * in, then these must be duplicate scan results for this Bss. In that
2522 * case, remove the 'old' Bss description from the linked list.
2523 */
2524 csr_ll_lock(&pMac->scan.scanResultList);
2525 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
2526
2527 while (pEntry) {
2528 scan_entry = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2529 /*
2530 * we have a duplicate scan results only when BSSID, SSID,
2531 * Channel and NetworkType matches
2532 */
2533 if (csr_is_duplicate_bss_description(pMac,
2534 &scan_entry->Result.BssDescriptor,
2535 bss_dscp, pIes, fForced)) {
2536 /*
2537 * Following is mathematically a = (aX + b(100-X))/100
2538 * where:
2539 * a = bss_dscp->rssi, b = scan_entry_rssi
2540 * and X = CSR_SCAN_RESULT_RSSI_WEIGHT
2541 */
2542 scan_entry_rssi = scan_entry->Result.BssDescriptor.rssi;
2543 bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi *
2544 CSR_SCAN_RESULT_RSSI_WEIGHT) +
2545 ((int32_t) scan_entry_rssi *
2546 (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100);
2547 /* Remove the old entry from the list */
2548 if (csr_ll_remove_entry
2549 (&pMac->scan.scanResultList, pEntry,
2550 LL_ACCESS_NOLOCK)) {
2551 /*
2552 * we need to free the memory associated with
2553 * this node. If failed to remove, assuming
2554 * someone else got it.
2555 */
2556 *pSsid = scan_entry->Result.ssId;
2557 *timer = scan_entry->Result.timer;
2558 csr_check_n_save_wsc_ie(pMac, bss_dscp,
2559 &scan_entry->Result.
2560 BssDescriptor);
2561 csr_free_scan_result_entry(pMac, scan_entry);
2562 } else {
2563 sms_log(pMac, LOGW, FL("fail to remove entry"));
2564 }
2565 fRC = true;
2566 /*
2567 * If we found a match, we can stop looking through
2568 * the list.
2569 */
2570 break;
2571 }
2572 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
2573 LL_ACCESS_NOLOCK);
2574 }
2575
2576 csr_ll_unlock(&pMac->scan.scanResultList);
2577 return fRC;
2578}
2579
2580CDF_STATUS csr_add_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId,
2581 tSirBssDescription *pBssDesc,
2582 tDot11fBeaconIEs *pIes)
2583{
2584 CDF_STATUS status = CDF_STATUS_E_FAILURE;
2585 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
2586 tPmkidCandidateInfo *pmkid_info = NULL;
2587#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
2588 WLAN_HOST_DIAG_EVENT_DEF(secEvent,
2589 host_event_wlan_security_payload_type);
2590#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
2591 if (!pSession) {
2592 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
2593 return CDF_STATUS_E_FAILURE;
2594 }
2595
2596 sms_log(pMac, LOGW, FL("NumPmkidCandidate = %d"),
2597 pSession->NumPmkidCandidate);
2598 if (!pIes)
2599 return status;
2600 /* check if this is a RSN BSS */
2601 if (!pIes->RSN.present)
2602 return status;
2603
2604 if (pSession->NumPmkidCandidate >= CSR_MAX_PMKID_ALLOWED)
2605 return CDF_STATUS_E_FAILURE;
2606
2607 /* BSS is capable of doing pre-authentication */
2608#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
2609 cdf_mem_set(&secEvent, sizeof(host_event_wlan_security_payload_type),
2610 0);
2611 secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND;
2612 secEvent.encryptionModeMulticast = (uint8_t)diag_enc_type_from_csr_type(
2613 pSession->connectedProfile.mcEncryptionType);
2614 secEvent.encryptionModeUnicast = (uint8_t)diag_enc_type_from_csr_type(
2615 pSession->connectedProfile.EncryptionType);
2616 cdf_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid.bytes,
2617 CDF_MAC_ADDR_SIZE);
2618 secEvent.authMode = (uint8_t)diag_auth_type_from_csr_type(
2619 pSession->connectedProfile.AuthType);
2620 WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
2621#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
2622
2623 pmkid_info = &pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate];
2624 /* if yes, then add to PMKIDCandidateList */
2625 cdf_mem_copy(pmkid_info->BSSID.bytes, pBssDesc->bssId,
2626 CDF_MAC_ADDR_SIZE);
2627 /* Bit 0 offirst byte - PreAuthentication Capability */
2628 if ((pIes->RSN.RSN_Cap[0] >> 0) & 0x1)
2629 pmkid_info->preAuthSupported = true;
2630 else
2631 pmkid_info->preAuthSupported = false;
2632 pSession->NumPmkidCandidate++;
2633 return status;
2634}
2635
2636/*
2637 * This function checks whether new AP is found for the current connected
2638 * profile. If it is found, it return the sessionId, else it return invalid
2639 * sessionID
2640 */
2641CDF_STATUS csr_process_bss_desc_for_pmkid_list(tpAniSirGlobal pMac,
2642 tSirBssDescription *pBssDesc,
2643 tDot11fBeaconIEs *pIes,
2644 uint8_t sessionId)
2645{
2646 tCsrRoamSession *pSession;
2647 tDot11fBeaconIEs *pIesLocal = pIes;
2648 CDF_STATUS status = CDF_STATUS_E_FAILURE;
2649
2650 if (!(pIesLocal ||
2651 CDF_IS_STATUS_SUCCESS(
2652 csr_get_parsed_bss_description_ies(pMac, pBssDesc,
2653 &pIesLocal))))
2654 return status;
2655
2656 if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
2657 if (!pIes)
2658 cdf_mem_free(pIesLocal);
2659 return status;
2660 }
2661
2662 pSession = CSR_GET_SESSION(pMac, sessionId);
2663 if (csr_is_conn_state_connected_infra(pMac, sessionId)
2664 && (eCSR_AUTH_TYPE_RSN == pSession->connectedProfile.AuthType)
2665 && csr_match_bss_to_connect_profile(pMac,
2666 &pSession->connectedProfile,
2667 pBssDesc, pIesLocal)) {
2668 /* This new BSS fits the current profile connected */
2669 status = csr_add_pmkid_candidate_list(pMac, sessionId,
2670 pBssDesc, pIesLocal);
2671 if (!CDF_IS_STATUS_SUCCESS(status))
2672 sms_log(pMac, LOGE,
2673 FL("csr_add_pmkid_candidate_list failed"));
2674 else
2675 status = CDF_STATUS_SUCCESS;
2676 }
2677
2678 if (!pIes)
2679 cdf_mem_free(pIesLocal);
2680
2681 return status;
2682}
2683
2684#ifdef FEATURE_WLAN_WAPI
2685CDF_STATUS csr_add_bkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId,
2686 tSirBssDescription *pBssDesc,
2687 tDot11fBeaconIEs *pIes)
2688{
2689 CDF_STATUS status = CDF_STATUS_E_FAILURE;
2690 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
2691
2692 if (!pSession) {
2693 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
2694 return CDF_STATUS_E_FAILURE;
2695 }
2696
2697 sms_log(pMac, LOGW,
2698 "csr_add_bkid_candidate_list called pMac->scan.NumBkidCandidate = %d",
2699 pSession->NumBkidCandidate);
2700 if (pIes) {
2701 /* check if this is a WAPI BSS */
2702 if (pIes->WAPI.present) {
2703 /* Check if the BSS is capable of doing pre-authentication */
2704 if (pSession->NumBkidCandidate < CSR_MAX_BKID_ALLOWED) {
2705
2706 /* if yes, then add to BKIDCandidateList */
2707 cdf_mem_copy(pSession->
2708 BkidCandidateInfo[pSession->
2709 NumBkidCandidate].
2710 BSSID.bytes, pBssDesc->bssId,
2711 CDF_MAC_ADDR_SIZE);
2712 if (pIes->WAPI.preauth) {
2713 pSession->BkidCandidateInfo[pSession->
2714 NumBkidCandidate].
2715 preAuthSupported = true;
2716 } else {
2717 pSession->BkidCandidateInfo[pSession->
2718 NumBkidCandidate].
2719 preAuthSupported = false;
2720 }
2721 pSession->NumBkidCandidate++;
2722 } else {
2723 status = CDF_STATUS_E_FAILURE;
2724 }
2725 }
2726 }
2727
2728 return status;
2729}
2730
2731/*
2732 * This function checks whether new AP is found for the current connected
2733 * profile, if so add to BKIDCandidateList
2734 */
2735bool csr_process_bss_desc_for_bkid_list(tpAniSirGlobal pMac,
2736 tSirBssDescription *pBssDesc,
2737 tDot11fBeaconIEs *pIes)
2738{
2739 bool fRC = false;
2740 tDot11fBeaconIEs *pIesLocal = pIes;
2741 uint32_t sessionId;
2742 tCsrRoamSession *pSession;
2743 CDF_STATUS status;
2744
2745 if (!(pIesLocal ||
2746 CDF_IS_STATUS_SUCCESS(
2747 csr_get_parsed_bss_description_ies(pMac, pBssDesc,
2748 &pIesLocal))))
2749 return fRC;
2750
2751 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
2752 if (!CSR_IS_SESSION_VALID(pMac, sessionId))
2753 continue;
2754 pSession = CSR_GET_SESSION(pMac, sessionId);
2755 if (csr_is_conn_state_connected_infra(pMac, sessionId)
2756 && (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE ==
2757 pSession->connectedProfile.AuthType)
2758 && csr_match_bss_to_connect_profile(pMac,
2759 &pSession->connectedProfile,
2760 pBssDesc, pIesLocal)) {
2761 /* this new BSS fits the current profile connected */
2762 status = csr_add_bkid_candidate_list(pMac, sessionId,
2763 pBssDesc, pIesLocal);
2764 if (CDF_IS_STATUS_SUCCESS(status))
2765 fRC = true;
2766 }
2767 }
2768 if (!pIes)
2769 cdf_mem_free(pIesLocal);
2770 return fRC;
2771}
2772
2773#endif
2774
2775static void
2776csr_remove_from_tmp_list(tpAniSirGlobal mac_ctx,
2777 uint8_t reason,
2778 uint8_t session_id)
2779{
2780 CDF_STATUS status;
2781 tListElem *entry;
2782 tCsrScanResult *bss_dscp;
2783 tDot11fBeaconIEs *local_ie = NULL;
2784 bool dup_bss;
2785 tAniSSID tmpSsid;
2786 v_TIME_t timer = 0;
2787
2788 tmpSsid.length = 0;
2789 while ((entry = csr_ll_remove_tail(&mac_ctx->scan.tempScanResults,
2790 LL_ACCESS_LOCK)) != NULL) {
2791 bss_dscp = GET_BASE_ADDR(entry, tCsrScanResult, Link);
2792 sms_log(mac_ctx, LOG2,
2793 FL("...Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = -%d"),
2794 MAC_ADDR_ARRAY(bss_dscp->Result.BssDescriptor.
2795 bssId),
2796 bss_dscp->Result.BssDescriptor.channelId,
2797 bss_dscp->Result.BssDescriptor.rssi * (-1));
2798
2799 /* At this time, bss_dscp->Result.pvIes may be NULL */
2800 local_ie = (tDot11fBeaconIEs *)(bss_dscp->Result.pvIes);
2801 status = csr_get_parsed_bss_description_ies(mac_ctx,
2802 &bss_dscp->Result.BssDescriptor, &local_ie);
2803 if (!(local_ie || CDF_IS_STATUS_SUCCESS(status))) {
2804 sms_log(mac_ctx, LOGE, FL("Cannot pared IEs"));
2805 csr_free_scan_result_entry(mac_ctx, bss_dscp);
2806 continue;
2807 }
2808 dup_bss = csr_remove_dup_bss_description(mac_ctx,
2809 &bss_dscp->Result.BssDescriptor,
2810 local_ie, &tmpSsid, &timer, false);
2811 /*
2812 * Check whether we have reach out limit, but don't lose the
2813 * LFR candidates came from FW
2814 */
2815 if (CSR_SCAN_IS_OVER_BSS_LIMIT(mac_ctx)) {
2816 sms_log(mac_ctx, LOGW, FL("BSS limit reached"));
2817 if ((bss_dscp->Result.pvIes == NULL) && local_ie)
2818 cdf_mem_free(local_ie);
2819 csr_free_scan_result_entry(mac_ctx, bss_dscp);
2820 /* Continue because there may be duplicated BSS */
2821 continue;
2822 }
2823 /* check for duplicate scan results */
2824 if (!dup_bss) {
2825 status = csr_process_bss_desc_for_pmkid_list(mac_ctx,
2826 &bss_dscp->Result.BssDescriptor,
2827 local_ie, session_id);
2828 if (CDF_IS_STATUS_SUCCESS(status)) {
2829 /* Found a new BSS */
2830 csr_roam_call_callback(mac_ctx, session_id,
2831 NULL, 0, eCSR_ROAM_SCAN_FOUND_NEW_BSS,
2832 eCSR_ROAM_RESULT_NONE);
2833 }
2834 } else {
2835 /*
2836 * Check if the new one has SSID it it, if not, use
2837 * the older SSID if it exists.
2838 *
2839 * New BSS has a hidden SSID and old one has the SSID.
2840 * Keep the SSID only if diff of saved SSID time and
2841 * current time is less than 1 min to avoid side effect
2842 * of saving SSID with old one is that if AP changes
2843 * its SSID while remain hidden, we may never see it
2844 * and also to address the requirement of When we remove
2845 * hidden ssid from the profile i.e., forget the SSID
2846 * via GUI that SSID shouldn't see in the profile
2847 */
2848 v_TIME_t time_gap = cdf_mc_timer_get_system_time() -
2849 timer;
2850 if ((0 == bss_dscp->Result.ssId.length)
2851 && (time_gap <= HIDDEN_TIMER)
2852 && tmpSsid.length) {
2853 bss_dscp->Result.timer = timer;
2854 bss_dscp->Result.ssId = tmpSsid;
2855 }
2856 }
2857
2858 if (csr_is11d_supported(mac_ctx)
2859 && local_ie->Country.present) {
2860 csr_add_vote_for_country_info(mac_ctx,
2861 local_ie->Country.country);
2862 sms_log(mac_ctx, LOGW,
2863 FL("11d AP Bssid "MAC_ADDRESS_STR
2864 " chan= %d, rssi = -%d, countryCode %c%c"),
2865 MAC_ADDR_ARRAY(
2866 bss_dscp->Result.BssDescriptor.bssId),
2867 bss_dscp->Result.BssDescriptor.channelId,
2868 bss_dscp->Result.BssDescriptor.rssi * (-1),
2869 local_ie->Country.country[0],
2870 local_ie->Country.country[1]);
2871 }
2872 /* append to main list */
2873 csr_scan_add_result(mac_ctx, bss_dscp, local_ie, session_id);
2874 if ((bss_dscp->Result.pvIes == NULL) && local_ie)
2875 cdf_mem_free(local_ie);
2876 } /* end of loop */
2877}
2878
2879static void csr_move_temp_scan_results_to_main_list(tpAniSirGlobal pMac,
2880 uint8_t reason,
2881 uint8_t sessionId)
2882{
2883 tCsrRoamSession *pSession;
2884 uint32_t i;
2885
2886 /* remove the BSS descriptions from temporary list */
2887 csr_remove_from_tmp_list(pMac, reason, sessionId);
2888 /*
2889 * We don't need to update CC while connected to an AP which is
2890 * advertising CC already
2891 */
2892 if (!csr_is11d_supported(pMac))
2893 return;
2894
2895 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
2896 if (!CSR_IS_SESSION_VALID(pMac, i))
2897 continue;
2898 pSession = CSR_GET_SESSION(pMac, i);
2899 if (csr_is_conn_state_connected(pMac, i)) {
2900 sms_log(pMac, LOGW,
2901 FL("No need to update CC in connected state"));
2902 return;
2903 }
2904 }
2905 csr_elected_country_info(pMac);
2906 csr_learn_11dcountry_information(pMac, NULL, NULL, true);
2907}
2908
2909static tCsrScanResult *csr_scan_save_bss_description(tpAniSirGlobal pMac,
2910 tSirBssDescription *
2911 pBSSDescription,
2912 tDot11fBeaconIEs *pIes,
2913 uint8_t sessionId)
2914{
2915 tCsrScanResult *pCsrBssDescription = NULL;
2916 uint32_t cbBSSDesc;
2917 uint32_t cbAllocated;
2918
2919 /* figure out how big the BSS description is (the BSSDesc->length does NOT */
2920 /* include the size of the length field itself). */
2921 cbBSSDesc = pBSSDescription->length + sizeof(pBSSDescription->length);
2922
2923 cbAllocated = sizeof(tCsrScanResult) + cbBSSDesc;
2924
2925 pCsrBssDescription = cdf_mem_malloc(cbAllocated);
2926 if (NULL != pCsrBssDescription) {
2927 cdf_mem_set(pCsrBssDescription, cbAllocated, 0);
2928 pCsrBssDescription->AgingCount =
2929 (int32_t) pMac->roam.configParam.agingCount;
2930 sms_log(pMac, LOGW,
2931 FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "),
2932 pCsrBssDescription->AgingCount,
2933 MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.
2934 bssId));
2935 cdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor,
2936 pBSSDescription, cbBSSDesc);
2937#if defined(CDF_ENSBALED)
2938 if (NULL != pCsrBssDescription->Result.pvIes) {
2939 CDF_ASSERT(pCsrBssDescription->Result.pvIes == NULL);
2940 return NULL;
2941 }
2942#endif
2943 csr_scan_add_result(pMac, pCsrBssDescription, pIes, sessionId);
2944 }
2945
2946 return pCsrBssDescription;
2947}
2948
2949/* Append a Bss Description... */
2950tCsrScanResult *csr_scan_append_bss_description(tpAniSirGlobal pMac,
2951 tSirBssDescription *
2952 pSirBssDescription,
2953 tDot11fBeaconIEs *pIes,
2954 bool fForced, uint8_t sessionId)
2955{
2956 tCsrScanResult *pCsrBssDescription = NULL;
2957 tAniSSID tmpSsid;
2958 v_TIME_t timer = 0;
2959 int result;
2960
2961 tmpSsid.length = 0;
2962 result = csr_remove_dup_bss_description(pMac, pSirBssDescription,
2963 pIes, &tmpSsid, &timer,
2964 fForced);
2965 pCsrBssDescription = csr_scan_save_bss_description(pMac,
2966 pSirBssDescription, pIes, sessionId);
2967 if (result && (pCsrBssDescription != NULL)) {
2968 /*
2969 * Check if the new one has SSID it it, if not, use the older
2970 * SSID if it exists.
2971 */
2972 if ((0 == pCsrBssDescription->Result.ssId.length)
2973 && tmpSsid.length) {
2974 /*
2975 * New BSS has a hidden SSID and old one has the SSID.
2976 * Keep the SSID only if diff of saved SSID time and
2977 * current time is less than 1 min to avoid side effect
2978 * of saving SSID with old one is that if AP changes its
2979 * SSID while remain hidden, we may never see it and
2980 * also to address the requirement of. When we remove
2981 * hidden ssid from the profile i.e., forget the SSID
2982 * via GUI that SSID shouldn't see in the profile
2983 */
2984 if ((cdf_mc_timer_get_system_time() - timer) <=
2985 HIDDEN_TIMER) {
2986 pCsrBssDescription->Result.ssId = tmpSsid;
2987 pCsrBssDescription->Result.timer = timer;
2988 }
2989 }
2990 }
2991
2992 return pCsrBssDescription;
2993}
2994
2995void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList)
2996{
2997 tCsrChannelPowerInfo *pChannelSet;
2998 tListElem *pEntry;
2999
3000 csr_ll_lock(pChannelList);
3001 /*
3002 * Remove the channel sets from the learned list and put them
3003 * in the free list
3004 */
3005 while ((pEntry = csr_ll_remove_head(pChannelList,
3006 LL_ACCESS_NOLOCK)) != NULL) {
3007 pChannelSet = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link);
3008 if (pChannelSet)
3009 cdf_mem_free(pChannelSet);
3010 }
3011 csr_ll_unlock(pChannelList);
3012 return;
3013}
3014
3015/*
3016 * Save the channelList into the ultimate storage as the final stage of channel
3017 * Input: pCountryInfo -- the country code (e.g. "USI"), channel list, and power
3018 * limit are all stored inside this data structure
3019 */
3020CDF_STATUS csr_save_to_channel_power2_g_5_g(tpAniSirGlobal pMac,
3021 uint32_t tableSize,
3022 tSirMacChanInfo *channelTable)
3023{
3024 uint32_t i = tableSize / sizeof(tSirMacChanInfo);
3025 tSirMacChanInfo *pChannelInfo;
3026 tCsrChannelPowerInfo *pChannelSet;
3027 bool f2GHzInfoFound = false;
3028 bool f2GListPurged = false, f5GListPurged = false;
3029
3030 pChannelInfo = channelTable;
3031 /* atleast 3 bytes have to be remaining -- from "countryString" */
3032 while (i--) {
3033 pChannelSet = cdf_mem_malloc(sizeof(tCsrChannelPowerInfo));
3034 if (NULL == pChannelSet) {
3035 pChannelInfo++;
3036 continue;
3037 }
3038 cdf_mem_set(pChannelSet, sizeof(tCsrChannelPowerInfo), 0);
3039 pChannelSet->firstChannel = pChannelInfo->firstChanNum;
3040 pChannelSet->numChannels = pChannelInfo->numChannels;
3041 /*
3042 * Now set the inter-channel offset based on the frequency band
3043 * the channel set lies in
3044 */
3045 if ((CDS_IS_CHANNEL_24GHZ(pChannelSet->firstChannel)) &&
3046 ((pChannelSet->firstChannel +
3047 (pChannelSet->numChannels - 1)) <=
3048 CDS_MAX_24GHz_CHANNEL_NUMBER)) {
3049 pChannelSet->interChannelOffset = 1;
3050 f2GHzInfoFound = true;
3051 } else if ((CDS_IS_CHANNEL_5GHZ(pChannelSet->firstChannel))
3052 && ((pChannelSet->firstChannel +
3053 ((pChannelSet->numChannels - 1) * 4)) <=
3054 CDS_MAX_5GHz_CHANNEL_NUMBER)) {
3055 pChannelSet->interChannelOffset = 4;
3056 f2GHzInfoFound = false;
3057 } else {
3058 sms_log(pMac, LOGW,
3059 FL("Invalid Channel %d Present in Country IE"),
3060 pChannelSet->firstChannel);
3061 cdf_mem_free(pChannelSet);
3062 return CDF_STATUS_E_FAILURE;
3063 }
3064 pChannelSet->txPower = CDF_MIN(pChannelInfo->maxTxPower,
3065 pMac->roam.configParam.nTxPowerCap);
3066 if (f2GHzInfoFound) {
3067 if (!f2GListPurged) {
3068 /* purge previous results if found new */
3069 csr_purge_channel_power(pMac,
3070 &pMac->scan.
3071 channelPowerInfoList24);
3072 f2GListPurged = true;
3073 }
3074 if (CSR_IS_OPERATING_BG_BAND(pMac)) {
3075 /* add to the list of 2.4 GHz channel sets */
3076 csr_ll_insert_tail(&pMac->scan.
3077 channelPowerInfoList24,
3078 &pChannelSet->link,
3079 LL_ACCESS_LOCK);
3080 } else {
3081 sms_log(pMac, LOGW,
3082 FL("Adding 11B/G ch in 11A. 1st ch %d"),
3083 pChannelSet->firstChannel);
3084 cdf_mem_free(pChannelSet);
3085 }
3086 } else {
3087 /* 5GHz info found */
3088 if (!f5GListPurged) {
3089 /* purge previous results if found new */
3090 csr_purge_channel_power(pMac,
3091 &pMac->scan.
3092 channelPowerInfoList5G);
3093 f5GListPurged = true;
3094 }
3095 if (CSR_IS_OPERATING_A_BAND(pMac)) {
3096 /* add to the list of 5GHz channel sets */
3097 csr_ll_insert_tail(&pMac->scan.
3098 channelPowerInfoList5G,
3099 &pChannelSet->link,
3100 LL_ACCESS_LOCK);
3101 } else {
3102 sms_log(pMac, LOGW,
3103 FL("Adding 11A ch in B/G. 1st ch %d"),
3104 pChannelSet->firstChannel);
3105 cdf_mem_free(pChannelSet);
3106 }
3107 }
3108 pChannelInfo++; /* move to next entry */
3109 }
3110 return CDF_STATUS_SUCCESS;
3111}
3112
3113static void csr_clear_dfs_channel_list(tpAniSirGlobal pMac)
3114{
3115 tSirMbMsg *pMsg;
3116 uint16_t msgLen;
3117
3118 msgLen = (uint16_t) (sizeof(tSirMbMsg));
3119 pMsg = cdf_mem_malloc(msgLen);
3120 if (NULL != pMsg) {
3121 cdf_mem_set((void *)pMsg, msgLen, 0);
3122 pMsg->type = eWNI_SME_CLEAR_DFS_CHANNEL_LIST;
3123 pMsg->msgLen = msgLen;
3124 cds_send_mb_message_to_mac(pMsg);
3125 }
3126}
3127
3128void csr_apply_power2_current(tpAniSirGlobal pMac)
3129{
3130 sms_log(pMac, LOG3, FL(" Updating Cfg with power settings"));
3131 csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList24,
3132 WNI_CFG_MAX_TX_POWER_2_4);
3133 csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList5G,
3134 WNI_CFG_MAX_TX_POWER_5);
3135}
3136
3137void csr_apply_channel_power_info_to_fw(tpAniSirGlobal mac_ctx,
3138 tCsrChannel *ch_lst,
3139 uint8_t *countryCode)
3140{
3141 int i;
3142 uint8_t num_ch = 0;
3143 uint8_t tempNumChannels = 0;
3144 tCsrChannel tmp_ch_lst;
3145
3146 if (ch_lst->numChannels) {
3147 tempNumChannels = CSR_MIN(ch_lst->numChannels,
3148 WNI_CFG_VALID_CHANNEL_LIST_LEN);
3149 for (i = 0; i < tempNumChannels; i++) {
3150 tmp_ch_lst.channelList[num_ch] = ch_lst->channelList[i];
3151 num_ch++;
3152 }
3153 tmp_ch_lst.numChannels = num_ch;
3154 /* Store the channel+power info in the global place: Cfg */
3155 csr_apply_power2_current(mac_ctx);
3156 csr_set_cfg_valid_channel_list(mac_ctx, tmp_ch_lst.channelList,
3157 tmp_ch_lst.numChannels);
3158 /*
3159 * extend scan capability, build a scan list based on the
3160 * channel list : channel# + active/passive scan
3161 */
3162 csr_set_cfg_scan_control_list(mac_ctx, countryCode,
3163 &tmp_ch_lst);
3164 /* Send msg to Lim to clear DFS channel list */
3165 csr_clear_dfs_channel_list(mac_ctx);
3166 } else {
3167 sms_log(mac_ctx, LOGE, FL("11D channel list is empty"));
3168 }
3169 csr_set_cfg_country_code(mac_ctx, countryCode);
3170}
3171
3172#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3173static void csr_diag_reset_country_information(tpAniSirGlobal pMac)
3174{
3175
3176 host_log_802_11d_pkt_type *p11dLog;
3177 int Index;
3178 WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type,
3179 LOG_WLAN_80211D_C);
3180 if (!p11dLog)
3181 return;
3182
3183 p11dLog->eventId = WLAN_80211D_EVENT_RESET;
3184 cdf_mem_copy(p11dLog->countryCode, pMac->scan.countryCodeCurrent, 3);
3185 p11dLog->numChannel = pMac->scan.base_channels.numChannels;
3186 if (p11dLog->numChannel <= HOST_LOG_MAX_NUM_CHANNEL) {
3187 cdf_mem_copy(p11dLog->Channels,
3188 pMac->scan.base_channels.channelList,
3189 p11dLog->numChannel);
3190 for (Index = 0;
3191 Index < pMac->scan.base_channels.numChannels;
3192 Index++) {
3193 p11dLog->TxPwr[Index] = CDF_MIN(
3194 pMac->scan.defaultPowerTable[Index].pwr,
3195 pMac->roam.configParam.nTxPowerCap);
3196 }
3197 }
3198 if (!pMac->roam.configParam.Is11dSupportEnabled)
3199 p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
3200 else
3201 p11dLog->supportMultipleDomain =
3202 WLAN_80211D_SUPPORT_MULTI_DOMAIN;
3203 WLAN_HOST_DIAG_LOG_REPORT(p11dLog);
3204}
3205#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3206
3207/**
3208 * csr_apply_channel_power_info_wrapper() - sends channel info to fw
3209 * @pMac: main MAC data structure
3210 *
3211 * This function sends the channel power info to firmware
3212 *
3213 * Return: none
3214 */
3215void csr_apply_channel_power_info_wrapper(tpAniSirGlobal pMac)
3216{
3217
3218#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3219 csr_diag_reset_country_information(pMac);
3220#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3221 csr_prune_channel_list_for_mode(pMac, &pMac->scan.base_channels);
3222 csr_save_channel_power_for_band(pMac, false);
3223 csr_save_channel_power_for_band(pMac, true);
3224 /* apply the channel list, power settings, and the country code. */
3225 csr_apply_channel_power_info_to_fw(pMac,
3226 &pMac->scan.base_channels, pMac->scan.countryCodeCurrent);
3227 /* clear the 11d channel list */
3228 cdf_mem_set(&pMac->scan.channels11d, sizeof(pMac->scan.channels11d), 0);
3229}
3230
3231void csr_clear_votes_for_country_info(tpAniSirGlobal pMac)
3232{
3233 pMac->scan.countryCodeCount = 0;
3234 cdf_mem_set(pMac->scan.votes11d,
3235 sizeof(tCsrVotes11d) * CSR_MAX_NUM_COUNTRY_CODE, 0);
3236}
3237
3238void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode)
3239{
3240 bool match = false;
3241 uint8_t i;
3242
3243 /* convert to UPPER here so we are assured
3244 * the strings are always in upper case.
3245 */
3246 for (i = 0; i < 3; i++) {
3247 pCountryCode[i] = (uint8_t) csr_to_upper(pCountryCode[i]);
3248 }
3249
3250 /* Some of the 'old' Cisco 350 series AP's advertise NA as the
3251 * country code (for North America ??). NA is not a valid country code
3252 * or domain so let's allow this by changing it to the proper
3253 * country code (which is US). We've also seen some NETGEAR AP's
3254 * that have "XX " as the country code with valid 2.4 GHz US channel
3255 * information. If we cannot find the country code advertised in the
3256 * 11d information element, let's default to US.
3257 */
3258
3259 if (!CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(pMac,
3260 pCountryCode, NULL,
3261 COUNTRY_QUERY))) {
3262 pCountryCode[0] = '0';
3263 pCountryCode[1] = '0';
3264 }
3265
3266 /* We've seen some of the AP's improperly put a 0 for the
3267 * third character of the country code. spec says valid charcters are
3268 * 'O' (for outdoor), 'I' for Indoor, or ' ' (space; for either).
3269 * if we see a 0 in this third character, let's change it to a ' '.
3270 */
3271 if (0 == pCountryCode[2]) {
3272 pCountryCode[2] = ' ';
3273 }
3274
3275 for (i = 0; i < pMac->scan.countryCodeCount; i++) {
3276 match = (cdf_mem_compare(pMac->scan.votes11d[i].countryCode,
3277 pCountryCode, 2));
3278 if (match) {
3279 break;
3280 }
3281 }
3282
3283 if (match) {
3284 pMac->scan.votes11d[i].votes++;
3285 } else {
3286 cdf_mem_copy(pMac->scan.votes11d[pMac->scan.countryCodeCount].
3287 countryCode, pCountryCode, 3);
3288 pMac->scan.votes11d[pMac->scan.countryCodeCount].votes = 1;
3289 pMac->scan.countryCodeCount++;
3290 }
3291
3292 return;
3293}
3294
3295bool csr_elected_country_info(tpAniSirGlobal pMac)
3296{
3297 bool fRet = false;
3298 uint8_t maxVotes = 0;
3299 uint8_t i, j = 0;
3300
3301 if (!pMac->scan.countryCodeCount) {
3302 return fRet;
3303 }
3304 maxVotes = pMac->scan.votes11d[0].votes;
3305 fRet = true;
3306
3307 for (i = 1; i < pMac->scan.countryCodeCount; i++) {
3308 /* If we have a tie for max votes for 2 different country codes,
3309 * pick random.we can put some more intelligence - TBD
3310 */
3311 if (maxVotes < pMac->scan.votes11d[i].votes) {
3312 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
3313 " Votes for Country %c%c : %d\n",
3314 pMac->scan.votes11d[i].countryCode[0],
3315 pMac->scan.votes11d[i].countryCode[1],
3316 pMac->scan.votes11d[i].votes);
3317
3318 maxVotes = pMac->scan.votes11d[i].votes;
3319 j = i;
3320 fRet = true;
3321 }
3322
3323 }
3324 if (fRet) {
3325 cdf_mem_copy(pMac->scan.countryCodeElected,
3326 pMac->scan.votes11d[j].countryCode,
3327 WNI_CFG_COUNTRY_CODE_LEN);
3328 cdf_mem_copy(pMac->scan.countryCode11d,
3329 pMac->scan.votes11d[j].countryCode,
3330 WNI_CFG_COUNTRY_CODE_LEN);
3331 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
3332 "Selected Country is %c%c With count %d\n",
3333 pMac->scan.votes11d[j].countryCode[0],
3334 pMac->scan.votes11d[j].countryCode[1],
3335 pMac->scan.votes11d[j].votes);
3336 }
3337 return fRet;
3338}
3339
3340/**
3341 * csr_set_country_code() - Set country code
3342 * @pMac: main MAC data structure
3343 * @pCountry: ptr to Country Code
3344 *
3345 * This function sends the channel power info to firmware
3346 *
3347 * Return: none
3348 */
3349CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry)
3350{
3351 CDF_STATUS status = CDF_STATUS_E_INVAL;
3352 v_REGDOMAIN_t domainId;
3353
3354 if (pCountry) {
3355
3356 status = csr_get_regulatory_domain_for_country(pMac, pCountry,
3357 &domainId,
3358 COUNTRY_USER);
3359 if (CDF_IS_STATUS_SUCCESS(status)) {
3360 cdf_mem_copy(pMac->scan.countryCodeCurrent,
3361 pCountry,
3362 WNI_CFG_COUNTRY_CODE_LEN);
3363 csr_set_cfg_country_code(pMac, pCountry);
3364 }
3365 }
3366 return status;
3367}
3368
3369/* caller allocated memory for pNumChn and pChnPowerInfo */
3370/* As input, *pNumChn has the size of the array of pChnPowerInfo */
3371/* Upon return, *pNumChn has the number of channels assigned. */
3372void csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list,
3373 uint32_t *num_ch,
3374 tChannelListWithPower *chn_pwr_info)
3375{
3376 tListElem *entry;
3377 uint32_t chn_idx = 0, idx;
3378 tCsrChannelPowerInfo *ch_set;
3379
3380 /* Get 2.4Ghz first */
3381 entry = csr_ll_peek_head(list, LL_ACCESS_LOCK);
3382 while (entry && (chn_idx < *num_ch)) {
3383 ch_set = GET_BASE_ADDR(entry, tCsrChannelPowerInfo, link);
3384 for (idx = 0; (idx < ch_set->numChannels)
3385 && (chn_idx < *num_ch); idx++) {
3386 chn_pwr_info[chn_idx].chanId =
3387 (uint8_t) (ch_set->firstChannel
3388 + (idx * ch_set->interChannelOffset));
3389 chn_pwr_info[chn_idx++].pwr = ch_set->txPower;
3390 }
3391 entry = csr_ll_next(list, entry, LL_ACCESS_LOCK);
3392 }
3393 *num_ch = chn_idx;
3394
3395 return;
3396}
3397
3398#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3399void csr_diag_apply_country_info(tpAniSirGlobal mac_ctx)
3400{
3401 host_log_802_11d_pkt_type *p11dLog;
3402 tChannelListWithPower chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN];
3403 uint32_t nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp;
3404
3405 WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type,
3406 LOG_WLAN_80211D_C);
3407 if (!p11dLog)
3408 return;
3409
3410 p11dLog->eventId = WLAN_80211D_EVENT_COUNTRY_SET;
3411 cdf_mem_copy(p11dLog->countryCode, mac_ctx->scan.countryCode11d, 3);
3412 p11dLog->numChannel = mac_ctx->scan.channels11d.numChannels;
3413 if (p11dLog->numChannel > HOST_LOG_MAX_NUM_CHANNEL)
3414 goto diag_end;
3415
3416 cdf_mem_copy(p11dLog->Channels,
3417 mac_ctx->scan.channels11d.channelList,
3418 p11dLog->numChannel);
3419 csr_get_channel_power_info(mac_ctx,
3420 &mac_ctx->scan.channelPowerInfoList24,
3421 &nChnInfo, chnPwrInfo);
3422 nTmp = nChnInfo;
3423 nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN - nTmp;
3424 csr_get_channel_power_info(mac_ctx,
3425 &mac_ctx->scan.channelPowerInfoList5G,
3426 &nChnInfo, &chnPwrInfo[nTmp]);
3427 for (nTmp = 0; nTmp < p11dLog->numChannel; nTmp++) {
3428 for (nChnInfo = 0;
3429 nChnInfo < WNI_CFG_VALID_CHANNEL_LIST_LEN;
3430 nChnInfo++) {
3431 if (p11dLog->Channels[nTmp] ==
3432 chnPwrInfo[nChnInfo].chanId) {
3433 p11dLog->TxPwr[nTmp] =
3434 chnPwrInfo[nChnInfo].pwr;
3435 break;
3436 }
3437 }
3438 }
3439diag_end:
3440 if (!mac_ctx->roam.configParam.Is11dSupportEnabled)
3441 p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
3442 else
3443 p11dLog->supportMultipleDomain =
3444 WLAN_80211D_SUPPORT_MULTI_DOMAIN;
3445 WLAN_HOST_DIAG_LOG_REPORT(p11dLog);
3446}
3447#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3448
3449/**
3450 * csr_apply_country_information() - apply country code information
3451 * @pMac: core MAC data structure
3452 *
3453 * This function programs the new country code
3454 *
3455 * Return: none
3456 */
3457void csr_apply_country_information(tpAniSirGlobal pMac)
3458{
3459 v_REGDOMAIN_t domainId;
3460 CDF_STATUS status = CDF_STATUS_SUCCESS;
3461
3462 if (!csr_is11d_supported(pMac)
3463 || 0 == pMac->scan.channelOf11dInfo)
3464 return;
3465 status = csr_get_regulatory_domain_for_country(pMac,
3466 pMac->scan.countryCode11d, &domainId, COUNTRY_QUERY);
3467 if (!CDF_IS_STATUS_SUCCESS(status))
3468 return;
3469 /* Check whether we need to enforce default domain */
3470#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3471 csr_diag_apply_country_info(pMac);
3472#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3473
3474 if (pMac->scan.domainIdCurrent != domainId)
3475 return;
3476 if (pMac->scan.domainIdCurrent != domainId) {
3477 sms_log(pMac, LOGW, FL("Domain Changed Old %d, new %d"),
3478 pMac->scan.domainIdCurrent, domainId);
3479 status = wma_set_reg_domain(pMac, domainId);
3480 }
3481 if (status != CDF_STATUS_SUCCESS)
3482 sms_log(pMac, LOGE, FL("fail to set regId %d"), domainId);
3483 pMac->scan.domainIdCurrent = domainId;
3484 /* switch to active scans using this new channel list */
3485 pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
3486}
3487
3488void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fill_5f)
3489{
3490 uint32_t idx, count = 0;
3491 tSirMacChanInfo *chan_info;
3492 tSirMacChanInfo *ch_info_start;
3493 int32_t max_ch_idx;
3494 bool tmp_bool;
3495 uint8_t ch = 0;
3496
3497 max_ch_idx =
3498 (pMac->scan.base_channels.numChannels <
3499 WNI_CFG_VALID_CHANNEL_LIST_LEN) ?
3500 pMac->scan.base_channels.numChannels :
3501 WNI_CFG_VALID_CHANNEL_LIST_LEN;
3502
3503 chan_info = cdf_mem_malloc(sizeof(tSirMacChanInfo) *
3504 WNI_CFG_VALID_CHANNEL_LIST_LEN);
3505 if (NULL == chan_info)
3506 return;
3507
3508 cdf_mem_set(chan_info, sizeof(tSirMacChanInfo) *
3509 WNI_CFG_VALID_CHANNEL_LIST_LEN, 0);
3510 ch_info_start = chan_info;
3511 for (idx = 0; idx < max_ch_idx; idx++) {
3512 ch = pMac->scan.defaultPowerTable[idx].chanId;
3513 tmp_bool = (fill_5f && CDS_IS_CHANNEL_5GHZ(ch))
3514 || (!fill_5f && CDS_IS_CHANNEL_24GHZ(ch));
3515 if (!tmp_bool)
3516 continue;
3517
3518 if (count >= WNI_CFG_VALID_CHANNEL_LIST_LEN) {
3519 sms_log(pMac, LOGW, FL("count(%d) exceeded"), count);
3520 break;
3521 }
3522
3523 chan_info->firstChanNum =
3524 pMac->scan.defaultPowerTable[idx].chanId;
3525 chan_info->numChannels = 1;
3526 chan_info->maxTxPower =
3527 CDF_MIN(pMac->scan.defaultPowerTable[idx].pwr,
3528 pMac->roam.configParam.nTxPowerCap);
3529 chan_info++;
3530 count++;
3531 }
3532 if (count) {
3533 csr_save_to_channel_power2_g_5_g(pMac,
3534 count * sizeof(tSirMacChanInfo), ch_info_start);
3535 }
3536 cdf_mem_free(ch_info_start);
3537}
3538
3539bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId)
3540{
3541 bool fRet = false;
3542 uint32_t i;
3543
3544 for (i = 0; i < pMac->scan.base_channels.numChannels; i++) {
3545 if (channelId ==
3546 pMac->scan.base_channels.channelList[i]) {
3547 fRet = true;
3548 break;
3549 }
3550 }
3551
3552 return fRet;
3553}
3554
3555/*
3556 * 802.11D only: Gather 11d IE via beacon or Probe response and store them in pAdapter->channels11d
3557 */
3558bool csr_learn_11dcountry_information(tpAniSirGlobal pMac,
3559 tSirBssDescription *pSirBssDesc,
3560 tDot11fBeaconIEs *pIes, bool fForce)
3561{
3562 CDF_STATUS status;
3563 uint8_t *pCountryCodeSelected;
3564 bool fRet = false;
3565 v_REGDOMAIN_t domainId;
3566 tDot11fBeaconIEs *pIesLocal = pIes;
3567 bool useVoting = false;
3568
3569 if (CDF_SAP_MODE == cds_get_conparam())
3570 return CDF_STATUS_SUCCESS;
3571
3572 if ((NULL == pSirBssDesc) && (NULL == pIes))
3573 useVoting = true;
3574
3575 /* check if .11d support is enabled */
3576 if (!csr_is11d_supported(pMac))
3577 goto free_ie;
3578
3579 if (false == useVoting) {
3580 if (!pIesLocal &&
3581 (!CDF_IS_STATUS_SUCCESS(
3582 csr_get_parsed_bss_description_ies(
3583 pMac, pSirBssDesc, &pIesLocal))))
3584 goto free_ie;
3585 /* check if country information element is present */
3586 if (!pIesLocal->Country.present)
3587 /* No country info */
3588 goto free_ie;
3589 status = csr_get_regulatory_domain_for_country(pMac,
3590 pIesLocal->Country.country, &domainId,
3591 COUNTRY_QUERY);
3592 if (CDF_IS_STATUS_SUCCESS(status)
3593 && (domainId == REGDOMAIN_WORLD))
3594 goto free_ie;
3595 } /* useVoting == false */
3596
3597 if (false == useVoting)
3598 pCountryCodeSelected = pIesLocal->Country.country;
3599 else
3600 pCountryCodeSelected = pMac->scan.countryCodeElected;
3601
3602 status = csr_get_regulatory_domain_for_country(pMac,
3603 pCountryCodeSelected, &domainId, COUNTRY_IE);
3604 if (status != CDF_STATUS_SUCCESS) {
3605 sms_log(pMac, LOGE, FL("fail to get regId %d"), domainId);
3606 fRet = false;
3607 goto free_ie;
3608 }
3609
3610 /* updating 11d Country Code with Country code selected. */
3611 cdf_mem_copy(pMac->scan.countryCode11d, pCountryCodeSelected,
3612 WNI_CFG_COUNTRY_CODE_LEN);
3613 fRet = true;
3614free_ie:
3615 if (!pIes && pIesLocal) {
3616 /* locally allocated */
3617 cdf_mem_free(pIesLocal);
3618 }
3619 return fRet;
3620}
3621
3622void csr_save_scan_results(tpAniSirGlobal pMac, uint8_t reason,
3623 uint8_t sessionId)
3624{
3625 sms_log(pMac, LOG4, "%s: Saving scan results", __func__);
3626
3627 /* initialize this to false. profMoveInterimScanResultsToMainList() routine */
3628 /* will set this to the channel where an .11d beacon is seen */
3629 pMac->scan.channelOf11dInfo = 0;
3630 /* move the scan results from interim list to the main scan list */
3631 csr_move_temp_scan_results_to_main_list(pMac, reason, sessionId);
3632
3633 /* Now check if we gathered any domain/country specific information */
3634 /* If so, we should update channel list and apply Tx power settings */
3635 if (csr_is11d_supported(pMac)) {
3636 csr_apply_country_information(pMac);
3637 }
3638}
3639
3640void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
3641{
3642 switch (pCommand->u.scanCmd.reason) {
3643 case eCsrScanAbortNormalScan:
3644 default:
3645 csr_scan_free_request(pMac, &pCommand->u.scanCmd.u.scanRequest);
3646 break;
3647 }
3648 if (pCommand->u.scanCmd.pToRoamProfile) {
3649 csr_release_profile(pMac, pCommand->u.scanCmd.pToRoamProfile);
3650 cdf_mem_free(pCommand->u.scanCmd.pToRoamProfile);
3651 }
3652 cdf_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0);
3653}
3654
3655eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac,
3656 tSmeCmd *pCommand,
3657 bool fSuccess)
3658{
3659 eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
3660
3661 switch (pCommand->u.scanCmd.reason) {
3662 case eCsrScan11d1:
3663 NextCommand =
3664 (fSuccess) ? eCsrNext11dScan1Success :
3665 eCsrNext11dScan1Failure;
3666 break;
3667 case eCsrScan11d2:
3668 NextCommand =
3669 (fSuccess) ? eCsrNext11dScan2Success :
3670 eCsrNext11dScan2Failure;
3671 break;
3672 case eCsrScan11dDone:
3673 NextCommand = eCsrNext11dScanComplete;
3674 break;
3675 case eCsrScanLostLink1:
3676 NextCommand =
3677 (fSuccess) ? eCsrNextLostLinkScan1Success :
3678 eCsrNextLostLinkScan1Failed;
3679 break;
3680 case eCsrScanLostLink2:
3681 NextCommand =
3682 (fSuccess) ? eCsrNextLostLinkScan2Success :
3683 eCsrNextLostLinkScan2Failed;
3684 break;
3685 case eCsrScanLostLink3:
3686 NextCommand =
3687 (fSuccess) ? eCsrNextLostLinkScan3Success :
3688 eCsrNextLostLinkScan3Failed;
3689 break;
3690 case eCsrScanForSsid:
3691 NextCommand =
3692 (fSuccess) ? eCsrNexteScanForSsidSuccess :
3693 eCsrNexteScanForSsidFailure;
3694 break;
3695 default:
3696 NextCommand = eCsrNextScanNothing;
3697 break;
3698 }
3699 return NextCommand;
3700}
3701
3702/* Return whether the pCommand is finished. */
3703bool csr_handle_scan11d1_failure(tpAniSirGlobal pMac, tSmeCmd *pCommand)
3704{
3705 bool fRet = true;
3706
3707 /* Apply back the default setting and passively scan one more time. */
3708 csr_apply_channel_power_info_wrapper(pMac);
3709 pCommand->u.scanCmd.reason = eCsrScan11d2;
3710 if (CDF_IS_STATUS_SUCCESS(csr_scan_channels(pMac, pCommand))) {
3711 fRet = false;
3712 }
3713
3714 return fRet;
3715}
3716
3717#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3718static void
3719csr_diag_scan_complete(tpAniSirGlobal pMac,
3720 tSmeCmd *pCommand,
3721 tSirSmeScanRsp *pScanRsp)
3722{
3723 host_log_scan_pkt_type *pScanLog = NULL;
3724 tScanResultHandle hScanResult;
3725 tCsrScanResultInfo *pScanResult;
3726 tDot11fBeaconIEs *pIes;
3727 int n = 0, c = 0;
3728 CDF_STATUS status;
3729
3730 WLAN_HOST_DIAG_LOG_ALLOC(pScanLog,
3731 host_log_scan_pkt_type,
3732 LOG_WLAN_SCAN_C);
3733 if (!pScanLog)
3734 return;
3735
3736 if (eCsrScanProbeBss == pCommand->u.scanCmd.reason) {
3737 pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_RSP;
3738 } else {
3739 if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)
3740 pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP;
3741 else
3742 pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP;
3743 }
3744 if (eSIR_SME_SUCCESS != pScanRsp->statusCode) {
3745 pScanLog->status = WLAN_SCAN_STATUS_FAILURE;
3746 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
3747 return;
3748 }
3749
3750 status = csr_scan_get_result(pMac, NULL, &hScanResult);
3751 if (!CDF_IS_STATUS_SUCCESS(status)) {
3752 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
3753 return;
3754 }
3755
3756 pScanResult = csr_scan_result_get_next(pMac, hScanResult);
3757 while (pScanResult != NULL) {
3758 if (n < HOST_LOG_MAX_NUM_BSSID) {
3759 status = csr_get_parsed_bss_description_ies(pMac,
3760 &pScanResult->BssDescriptor, &pIes);
3761 if (!CDF_IS_STATUS_SUCCESS(status)) {
3762 sms_log(pMac, LOGE, FL("fail to parse IEs"));
3763 break;
3764 }
3765 cdf_mem_copy(pScanLog->bssid[n],
3766 pScanResult->BssDescriptor.bssId, 6);
3767 if (pIes && pIes->SSID.present &&
3768 HOST_LOG_MAX_SSID_SIZE >= pIes->SSID.num_ssid) {
3769 cdf_mem_copy(pScanLog->ssid[n],
3770 pIes->SSID.ssid,
3771 pIes->SSID.num_ssid);
3772 }
3773 cdf_mem_free(pIes);
3774 n++;
3775 }
3776 c++;
3777 pScanResult = csr_scan_result_get_next(pMac, hScanResult);
3778 }
3779 pScanLog->numSsid = (uint8_t) n;
3780 pScanLog->totalSsid = (uint8_t) c;
3781 csr_scan_result_purge(pMac, hScanResult);
3782 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
3783
3784 csr_diag_event_report(pMac, eCSR_EVENT_SCAN_COMPLETE, eSIR_SUCCESS,
3785 eSIR_SUCCESS);
3786 if (c > 0)
3787 csr_diag_event_report(pMac, eCSR_EVENT_SCAN_RES_FOUND,
3788 eSIR_SUCCESS, eSIR_SUCCESS);
3789}
3790#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3791
3792static void
3793csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand,
3794 eCsrScanCompleteNextCommand *nxt_cmd,
3795 bool *remove_cmd, uint32_t session_id)
3796{
3797 CDF_STATUS status;
3798 switch (*nxt_cmd) {
3799 case eCsrNext11dScan1Success:
3800 case eCsrNext11dScan2Success:
3801 sms_log(mac_ctx, LOG2,
3802 FL("11dScan1/3 produced results. Reissue Active scan"));
3803 /*
3804 * if we found country information, no need to continue scanning
3805 * further, bail out
3806 */
3807 *remove_cmd = true;
3808 *nxt_cmd = eCsrNext11dScanComplete;
3809 break;
3810 case eCsrNext11dScan1Failure:
3811 /*
3812 * We are not done yet. 11d scan fail once. We will try to reset
3813 * anything and do it over again. The only meaningful thing for
3814 * this retry is that we cannot find 11d information after a
3815 * reset so we clear the "old" 11d info and give it once more
3816 * chance
3817 */
3818 *remove_cmd = csr_handle_scan11d1_failure(mac_ctx, pCommand);
3819 if (*remove_cmd)
3820 *nxt_cmd = eCsrNext11dScanComplete;
3821 break;
3822 case eCsrNextLostLinkScan1Success:
3823 status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
3824 eCsrLostLink1);
3825 if (!CDF_IS_STATUS_SUCCESS(status))
3826 csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
3827 break;
3828 case eCsrNextLostLinkScan2Success:
3829 status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
3830 eCsrLostLink2);
3831 if (!CDF_IS_STATUS_SUCCESS(status))
3832 csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
3833 break;
3834 case eCsrNextLostLinkScan3Success:
3835 status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
3836 eCsrLostLink3);
3837 if (!CDF_IS_STATUS_SUCCESS(status))
3838 csr_scan_handle_failed_lostlink3(mac_ctx, session_id);
3839 break;
3840 case eCsrNextLostLinkScan1Failed:
3841 csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
3842 break;
3843 case eCsrNextLostLinkScan2Failed:
3844 csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
3845 break;
3846 case eCsrNextLostLinkScan3Failed:
3847 csr_scan_handle_failed_lostlink3(mac_ctx, session_id);
3848 break;
3849 case eCsrNexteScanForSsidSuccess:
3850 csr_scan_handle_search_for_ssid(mac_ctx, pCommand);
3851 break;
3852 case eCsrNexteScanForSsidFailure:
3853 csr_scan_handle_search_for_ssid_failure(mac_ctx, pCommand);
3854 break;
3855 default:
3856 break;
3857 }
3858}
3859
3860/**
3861 * csr_get_active_scan_entry() - To get scan entry from active command list
3862 *
3863 * @mac_ctx - MAC context
3864 * @scan_id - Scan identifier of the scan request
3865 * @entry - scan entry returned.
3866 *
3867 * Scan entry in the active scan list mapping to the sent scan id
3868 * is returned to the caller.
3869 *
3870 * Return: CDF_STATUS.
3871 */
3872CDF_STATUS csr_get_active_scan_entry(tpAniSirGlobal mac_ctx,
3873 uint32_t scan_id, tListElem **entry)
3874{
3875 CDF_STATUS status = CDF_STATUS_E_FAILURE;
3876 tListElem *localentry;
3877 tSmeCmd *cmd;
3878 uint32_t cmd_scan_id = 0;
3879
3880 csr_ll_lock(&mac_ctx->sme.smeScanCmdActiveList);
3881
3882 if (csr_ll_is_list_empty(&mac_ctx->sme.smeScanCmdActiveList,
3883 LL_ACCESS_NOLOCK)) {
3884 sms_log(mac_ctx, LOGE,
3885 FL(" Active list Empty scanId: %d"), scan_id);
3886 return CDF_STATUS_SUCCESS;
3887 }
3888 localentry = csr_ll_peek_head(&mac_ctx->sme.smeScanCmdActiveList,
3889 LL_ACCESS_NOLOCK);
3890 do {
3891 cmd = GET_BASE_ADDR(localentry, tSmeCmd, Link);
3892 if (cmd->command == eSmeCommandScan)
3893 cmd_scan_id = cmd->u.scanCmd.u.scanRequest.scan_id;
3894 else if (cmd->command == eSmeCommandRemainOnChannel)
3895 cmd_scan_id = cmd->u.remainChlCmd.scan_id;
3896 if (cmd_scan_id == scan_id) {
3897 sms_log(mac_ctx, LOG1, FL(" scanId Matched %d"),
3898 scan_id);
3899 *entry = localentry;
3900 csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
3901 return CDF_STATUS_SUCCESS;
3902 }
3903 localentry = csr_ll_next(&mac_ctx->sme.smeScanCmdActiveList,
3904 localentry, LL_ACCESS_NOLOCK);
3905 } while (localentry);
3906 csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
3907 return status;
3908}
3909
3910/* Return whether the command should be removed */
3911bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp)
3912{
3913 eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
3914 tListElem *pEntry = NULL;
3915 tSmeCmd *pCommand;
3916 bool fRemoveCommand = true;
3917 bool fSuccess;
3918 uint32_t sessionId = 0;
3919
3920 csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry);
3921 if (!pEntry) {
3922 sms_log(pMac, LOGE,
3923 FL("Scan Completion called but NO cmd ACTIVE ..."));
3924 return false;
3925 }
3926
3927 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
3928 /*
3929 * If the head of the queue is Active and it is a SCAN command, remove
3930 * and put this on the Free queue.
3931 */
3932 if (eSmeCommandScan != pCommand->command) {
3933 sms_log(pMac, LOGW,
3934 FL("Scan Completion called, but active SCAN cmd"));
3935 return false;
3936 }
3937
3938 sessionId = pCommand->sessionId;
3939 if (eSIR_SME_SUCCESS != pScanRsp->statusCode) {
3940 fSuccess = false;
3941 } else {
3942 /*
3943 * pMac->scan.tempScanResults is not empty meaning the scan
3944 * found something. This check only valid here because
3945 * csrSaveScanresults is not yet called
3946 */
3947 fSuccess = (!csr_ll_is_list_empty(&pMac->scan.tempScanResults,
3948 LL_ACCESS_LOCK));
3949 }
3950 if (pCommand->u.scanCmd.abortScanDueToBandChange) {
3951 /*
3952 * Scan aborted due to band change
3953 * The scan results need to be flushed
3954 */
3955 if (pCommand->u.scanCmd.callback
3956 != pMac->scan.callback11dScanDone) {
3957 sms_log(pMac, LOG1, FL("Filtering the scan results"));
3958 csr_scan_filter_results(pMac);
3959 } else {
3960 sms_log(pMac, LOG1,
3961 FL("11d_scan_done, flushing the scan results"));
3962 }
3963 pCommand->u.scanCmd.abortScanDueToBandChange = false;
3964 }
3965 csr_save_scan_results(pMac, pCommand->u.scanCmd.reason, sessionId);
3966#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3967 csr_diag_scan_complete(pMac, pCommand, pScanRsp);
3968#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3969 NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess);
3970 /* We reuse the command here instead reissue a new command */
3971 csr_handle_nxt_cmd(pMac, pCommand, &NextCommand,
3972 &fRemoveCommand, sessionId);
3973 return fRemoveCommand;
3974}
3975
3976static void
3977csr_scan_remove_dup_bss_description_from_interim_list(tpAniSirGlobal mac_ctx,
3978 tSirBssDescription *bss_dscp,
3979 tDot11fBeaconIEs *pIes)
3980{
3981 tListElem *pEntry;
3982 tCsrScanResult *scan_bss_dscp;
3983 int8_t scan_entry_rssi = 0;
3984 /*
3985 * Walk through all the chained BssDescriptions. If we find a chained
3986 * BssDescription that matches the BssID of the BssDescription passed
3987 * in, then these must be duplicate scan results for this Bss. In that
3988 * case, remove the 'old' Bss description from the linked list.
3989 */
3990 sms_log(mac_ctx, LOG4, FL(" for BSS " MAC_ADDRESS_STR " "),
3991 MAC_ADDR_ARRAY(bss_dscp->bssId));
3992 csr_ll_lock(&mac_ctx->scan.tempScanResults);
3993 pEntry = csr_ll_peek_head(&mac_ctx->scan.tempScanResults,
3994 LL_ACCESS_NOLOCK);
3995 while (pEntry) {
3996 scan_bss_dscp = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
3997 /*
3998 * we have a duplicate scan results only when BSSID, SSID,
3999 * Channel and NetworkType matches
4000 */
4001 scan_entry_rssi = scan_bss_dscp->Result.BssDescriptor.rssi;
4002 if (csr_is_duplicate_bss_description(mac_ctx,
4003 &scan_bss_dscp->Result.BssDescriptor, bss_dscp,
4004 pIes, false)) {
4005 /*
4006 * Following is mathematically a = (aX + b(100-X))/100
4007 * where:
4008 * a = bss_dscp->rssi, b = scan_entry_rssi
4009 * and X = CSR_SCAN_RESULT_RSSI_WEIGHT
4010 */
4011 bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi *
4012 CSR_SCAN_RESULT_RSSI_WEIGHT) +
4013 ((int32_t) scan_entry_rssi *
4014 (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100);
4015 /* Remove the 'old' entry from the list */
4016 if (csr_ll_remove_entry(&mac_ctx->scan.tempScanResults,
4017 pEntry, LL_ACCESS_NOLOCK)) {
4018 csr_check_n_save_wsc_ie(mac_ctx, bss_dscp,
4019 &scan_bss_dscp->Result.
4020 BssDescriptor);
4021 /*
4022 * we need to free the memory associated with
4023 * this node
4024 */
4025 csr_free_scan_result_entry(mac_ctx,
4026 scan_bss_dscp);
4027 }
4028 /*
4029 * If we found a match, we can stop looking through
4030 * the list.
4031 */
4032 break;
4033 }
4034 pEntry = csr_ll_next(&mac_ctx->scan.tempScanResults, pEntry,
4035 LL_ACCESS_NOLOCK);
4036 }
4037
4038 csr_ll_unlock(&mac_ctx->scan.tempScanResults);
4039}
4040
4041/* Caller allocated memory pfNewBssForConn to return whether new candidate for */
4042/* current connection is found. Cannot be NULL */
4043tCsrScanResult *csr_scan_save_bss_description_to_interim_list(tpAniSirGlobal pMac,
4044 tSirBssDescription *
4045 pBSSDescription,
4046 tDot11fBeaconIEs *pIes)
4047{
4048 tCsrScanResult *pCsrBssDescription = NULL;
4049 uint32_t cbBSSDesc;
4050 uint32_t cbAllocated;
4051
4052 /* figure out how big the BSS description is (the BSSDesc->length does NOT */
4053 /* include the size of the length field itself). */
4054 cbBSSDesc = pBSSDescription->length + sizeof(pBSSDescription->length);
4055
4056 cbAllocated = sizeof(tCsrScanResult) + cbBSSDesc;
4057
4058 sms_log(pMac, LOG4, FL("new BSS description, length %d, cbBSSDesc %d"),
4059 cbAllocated, cbBSSDesc);
4060 pCsrBssDescription = cdf_mem_malloc(cbAllocated);
4061 if (NULL != pCsrBssDescription) {
4062 cdf_mem_set(pCsrBssDescription, cbAllocated, 0);
4063 cdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor,
4064 pBSSDescription, cbBSSDesc);
4065 pCsrBssDescription->AgingCount =
4066 (int32_t) pMac->roam.configParam.agingCount;
4067 sms_log(pMac, LOG4,
4068 FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "),
4069 pCsrBssDescription->AgingCount,
4070 MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.
4071 bssId));
4072 /* Save SSID separately for later use */
4073 if (pIes->SSID.present
4074 && !csr_is_nullssid(pIes->SSID.ssid, pIes->SSID.num_ssid)) {
4075 /* SSID not hidden */
4076 uint32_t len = pIes->SSID.num_ssid;
4077 if (len > SIR_MAC_MAX_SSID_LENGTH) {
4078 /* truncate to fit in our struct */
4079 len = SIR_MAC_MAX_SSID_LENGTH;
4080 }
4081 pCsrBssDescription->Result.ssId.length = len;
4082 pCsrBssDescription->Result.timer =
4083 cdf_mc_timer_get_system_time();
4084 cdf_mem_copy(pCsrBssDescription->Result.ssId.ssId,
4085 pIes->SSID.ssid, len);
4086 }
4087 csr_ll_insert_tail(&pMac->scan.tempScanResults,
4088 &pCsrBssDescription->Link, LL_ACCESS_LOCK);
4089 }
4090
4091 return pCsrBssDescription;
4092}
4093
4094bool csr_is_duplicate_bss_description(tpAniSirGlobal pMac,
4095 tSirBssDescription *pSirBssDesc1,
4096 tSirBssDescription *pSirBssDesc2,
4097 tDot11fBeaconIEs *pIes2, bool fForced)
4098{
4099 bool fMatch = false;
4100 tSirMacCapabilityInfo *pCap1, *pCap2;
4101 tDot11fBeaconIEs *pIes1 = NULL;
4102 tDot11fBeaconIEs *pIesTemp = pIes2;
4103 CDF_STATUS status;
4104
4105 pCap1 = (tSirMacCapabilityInfo *) &pSirBssDesc1->capabilityInfo;
4106 pCap2 = (tSirMacCapabilityInfo *) &pSirBssDesc2->capabilityInfo;
4107
4108 if (pCap1->ess != pCap2->ess)
4109 goto free_ies;
4110
4111 if (pCap1->ess &&
4112 cdf_is_macaddr_equal((struct cdf_mac_addr *) pSirBssDesc1->bssId,
4113 (struct cdf_mac_addr *) pSirBssDesc2->bssId)
4114 && (fForced
4115 || (cds_chan_to_band(pSirBssDesc1->channelId) ==
4116 cds_chan_to_band((pSirBssDesc2->channelId))))) {
4117 fMatch = true;
4118 /* Check for SSID match, if exists */
4119 status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1,
4120 &pIes1);
4121 if (!CDF_IS_STATUS_SUCCESS(status))
4122 goto free_ies;
4123
4124 if (NULL == pIesTemp) {
4125 status = csr_get_parsed_bss_description_ies(pMac,
4126 pSirBssDesc2, &pIesTemp);
4127 if (!CDF_IS_STATUS_SUCCESS(status))
4128 goto free_ies;
4129 }
4130 if (pIes1->SSID.present && pIesTemp->SSID.present) {
4131 fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid,
4132 pIes1->SSID.num_ssid,
4133 pIesTemp->SSID.ssid,
4134 pIesTemp->SSID.num_ssid,
4135 true);
4136 }
4137 } else if (pCap1->ibss && (pSirBssDesc1->channelId ==
4138 pSirBssDesc2->channelId)) {
4139 status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1,
4140 &pIes1);
4141 if (!CDF_IS_STATUS_SUCCESS(status))
4142 goto free_ies;
4143
4144 if (NULL == pIesTemp) {
4145 status = csr_get_parsed_bss_description_ies(pMac,
4146 pSirBssDesc2, &pIesTemp);
4147 if (!CDF_IS_STATUS_SUCCESS(status))
4148 goto free_ies;
4149 }
4150
4151 /* Same channel cannot have same SSID for different IBSS */
4152 if (pIes1->SSID.present && pIesTemp->SSID.present) {
4153 fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid,
4154 pIes1->SSID.num_ssid,
4155 pIesTemp->SSID.ssid,
4156 pIesTemp->SSID.num_ssid,
4157 true);
4158 }
4159 }
4160 /* In case of P2P devices, ess and ibss will be set to zero */
4161 else if (!pCap1->ess &&
4162 cdf_is_macaddr_equal(
4163 (struct cdf_mac_addr *) pSirBssDesc1->bssId,
4164 (struct cdf_mac_addr *) pSirBssDesc2->bssId)) {
4165 fMatch = true;
4166 }
4167
4168free_ies:
4169 if (pIes1)
4170 cdf_mem_free(pIes1);
4171 if ((NULL == pIes2) && pIesTemp)
4172 /* locally allocated */
4173 cdf_mem_free(pIesTemp);
4174 return fMatch;
4175}
4176
4177bool csr_is_network_type_equal(tSirBssDescription *pSirBssDesc1,
4178 tSirBssDescription *pSirBssDesc2)
4179{
4180 return pSirBssDesc1->nwType == pSirBssDesc2->nwType;
4181}
4182
4183/* to check whether the BSS matches the dot11Mode */
4184static bool csr_scan_is_bss_allowed(tpAniSirGlobal pMac,
4185 tSirBssDescription *pBssDesc,
4186 tDot11fBeaconIEs *pIes)
4187{
4188 bool fAllowed = false;
4189 eCsrPhyMode phyMode;
4190
4191 if (CDF_IS_STATUS_SUCCESS
4192 (csr_get_phy_mode_from_bss(pMac, pBssDesc, &phyMode, pIes))) {
4193 switch (pMac->roam.configParam.phyMode) {
4194 case eCSR_DOT11_MODE_11b:
4195 fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode);
4196 break;
4197 case eCSR_DOT11_MODE_11g:
4198 fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode);
4199 break;
4200 case eCSR_DOT11_MODE_11g_ONLY:
4201 fAllowed = (bool) (eCSR_DOT11_MODE_11g == phyMode);
4202 break;
4203 case eCSR_DOT11_MODE_11a:
4204 fAllowed = (bool) ((eCSR_DOT11_MODE_11b != phyMode)
4205 && (eCSR_DOT11_MODE_11g != phyMode));
4206 break;
4207 case eCSR_DOT11_MODE_11n_ONLY:
4208 fAllowed = (bool) ((eCSR_DOT11_MODE_11n == phyMode));
4209 break;
4210
4211#ifdef WLAN_FEATURE_11AC
4212 case eCSR_DOT11_MODE_11ac_ONLY:
4213 fAllowed = (bool) ((eCSR_DOT11_MODE_11ac == phyMode));
4214 break;
4215#endif
4216 case eCSR_DOT11_MODE_11b_ONLY:
4217 fAllowed = (bool) (eCSR_DOT11_MODE_11b == phyMode);
4218 break;
4219 case eCSR_DOT11_MODE_11n:
4220#ifdef WLAN_FEATURE_11AC
4221 case eCSR_DOT11_MODE_11ac:
4222#endif
4223 default:
4224 fAllowed = true;
4225 break;
4226 }
4227 }
4228
4229 return fAllowed;
4230}
4231
4232/* Return pIes to caller for future use when returning true. */
4233static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac,
4234 uint8_t *pChannels,
4235 uint8_t numChn,
4236 tSirBssDescription *pBssDesc,
4237 tDot11fBeaconIEs **ppIes)
4238{
4239 bool valid = false;
4240 tDot11fBeaconIEs *pIes = NULL;
4241 uint8_t index;
4242 CDF_STATUS status;
4243
4244 for (index = 0; index < numChn; index++) {
4245 /*
4246 * This check relies on the fact that a single BSS description
4247 * is returned in each ScanRsp call, which is the way LIM
4248 * implemented the scan req/rsp funtions. We changed to this
4249 * model when we ran with a large number of APs. If this were to
4250 * change, then this check would have to mess with removing the
4251 * bssDescription from somewhere in an arbitrary index in the
4252 * bssDescription array.
4253 */
4254 if (pChannels[index] == pBssDesc->channelId) {
4255 valid = true;
4256 break;
4257 }
4258 }
4259 *ppIes = NULL;
4260 if (valid) {
4261 status = csr_get_parsed_bss_description_ies(pMac, pBssDesc,
4262 &pIes);
4263 if (!CDF_IS_STATUS_SUCCESS(status))
4264 return false;
4265
4266 valid = csr_scan_is_bss_allowed(pMac, pBssDesc, pIes);
4267 if (valid)
4268 *ppIes = pIes;
4269 else
4270 cdf_mem_free(pIes);
4271 }
4272 return valid;
4273}
4274
4275static void csr_update_scantype(tpAniSirGlobal pMac, tDot11fBeaconIEs *pIes,
4276 uint8_t channelId)
4277{
4278 if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)
4279 return;
4280
4281 if (csr_is11d_supported(pMac)) {
4282 /* Check whether the BSS is acceptable based on
4283 * 11d info and our config.
4284 */
4285 if (!csr_match_country_code(pMac, NULL, pIes))
4286 return;
4287
4288 /* check if channel is acceptable by config */
4289 if (csr_is_supported_channel(pMac, channelId))
4290 pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
4291
4292 } else
4293 pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
4294
4295}
4296
4297/* Return whether last scan result is received */
4298static bool csr_scan_process_scan_results(tpAniSirGlobal pMac, tSmeCmd *pCommand,
4299 tSirSmeScanRsp *pScanRsp,
4300 bool *pfRemoveCommand)
4301{
4302 bool fRet = false, fRemoveCommand = false;
4303
4304 sms_log(pMac, LOG1, FL("scan reason = %d, response status code = %d"),
4305 pCommand->u.scanCmd.reason, pScanRsp->statusCode);
4306 fRemoveCommand = csr_scan_complete(pMac, pScanRsp);
4307 fRet = true;
4308 if (pfRemoveCommand) {
4309 *pfRemoveCommand = fRemoveCommand;
4310 }
4311 return fRet;
4312}
4313
4314/* csr_scan_process_single_bssdescr() - Add a bssdescriptor to scan table
4315 *
4316 * @mac_ctx - MAC context
4317 * @bssdescr - Pointer to BSS description structure that contains
4318 * everything from beacon/probe response frame and additional
4319 * information.
4320 * @scan_id - Scan identifier of the scan request that was running
4321 * when this beacon was received. Reserved for future when
4322 * firmware provides that information.
4323 * @flags - Reserved for future use.
4324 *
4325 * Callback routine called by LIM when it receives a beacon or probe response
4326 * from the device. 802.11 frame is already converted to internal
4327 * tSirBssDescription data structure.
4328 *
4329 * Return: 0 or other error codes.
4330 */
4331
4332CDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal mac_ctx,
4333 tSirBssDescription *bssdescr,
4334 uint32_t scan_id, uint32_t flags)
4335{
4336 tDot11fBeaconIEs *ies = NULL;
4337 uint8_t *chanlist = NULL;
4338 uint8_t cnt_channels = 0;
4339 uint32_t len = sizeof(mac_ctx->roam.validChannelList);
4340
4341 sms_log(mac_ctx, LOG4, "CSR: Processing single bssdescr");
4342 if (CDF_IS_STATUS_SUCCESS(
4343 csr_get_cfg_valid_channels(mac_ctx,
4344 (uint8_t *) mac_ctx->roam.validChannelList,
4345 &len))) {
4346 chanlist = mac_ctx->roam.validChannelList;
4347 cnt_channels = (uint8_t) len;
4348 } else {
4349 /* Cannot continue */
4350 sms_log(mac_ctx, LOGW,
4351 FL("Received results on invalid channel"));
4352 return CDF_STATUS_E_INVAL;
4353 }
4354
4355 if (csr_scan_validate_scan_result(mac_ctx, chanlist,
4356 cnt_channels, bssdescr, &ies)) {
4357 csr_scan_remove_dup_bss_description_from_interim_list
4358 (mac_ctx, bssdescr, ies);
4359 csr_scan_save_bss_description_to_interim_list
4360 (mac_ctx, bssdescr, ies);
4361 csr_update_scantype(mac_ctx, ies, bssdescr->channelId);
4362 /* Free the resource */
4363 if (ies != NULL)
4364 cdf_mem_free(ies);
4365 }
4366 return CDF_STATUS_SUCCESS;
4367}
4368
4369
4370bool csr_scan_is_wild_card_scan(tpAniSirGlobal pMac, tSmeCmd *pCommand)
4371{
4372 uint8_t bssid[CDF_MAC_ADDR_SIZE] = {0};
4373 bool f = cdf_mem_compare(pCommand->u.scanCmd.u.scanRequest.bssid.bytes,
4374 bssid, sizeof(struct cdf_mac_addr));
4375 /*
4376 * It is not a wild card scan if the bssid is not broadcast and
4377 * the number of SSID is 1.
4378 */
4379 return (f || (0xff == pCommand->u.scanCmd.u.scanRequest.bssid.bytes[0]))
4380 && (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs != 1);
4381}
4382
4383CDF_STATUS csr_scan_sme_scan_response(tpAniSirGlobal pMac,
4384 void *pMsgBuf)
4385{
4386 CDF_STATUS status = CDF_STATUS_SUCCESS;
4387 tListElem *pEntry = NULL;
4388 tSmeCmd *pCommand;
4389 eCsrScanStatus scanStatus;
4390 tSirSmeScanRsp *pScanRsp = (tSirSmeScanRsp *)pMsgBuf;
4391 bool fRemoveCommand = true;
4392 eCsrScanReason reason = eCsrScanOther;
4393
4394 csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry);
4395 if (!pEntry)
4396 goto error_handling;
4397
4398 sms_log(pMac, LOG1, FL("Scan completion called:scan_id %d, entry = %p"),
4399 pScanRsp->scan_id, pEntry);
4400
4401 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
4402 if (eSmeCommandScan != pCommand->command)
4403 goto error_handling;
4404
4405 scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ?
4406 eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE;
4407 reason = pCommand->u.scanCmd.reason;
4408 switch (pCommand->u.scanCmd.reason) {
4409 case eCsrScanAbortNormalScan:
4410 break;
4411 case eCsrScanP2PFindPeer:
4412 scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ?
4413 eCSR_SCAN_FOUND_PEER : eCSR_SCAN_FAILURE;
4414 csr_scan_process_scan_results(pMac, pCommand, pScanRsp, NULL);
4415 break;
4416 default:
4417 if (csr_scan_process_scan_results(pMac, pCommand, pScanRsp,
4418 &fRemoveCommand)
4419 && csr_scan_is_wild_card_scan(pMac, pCommand)
4420 && !pCommand->u.scanCmd.u.scanRequest.p2pSearch) {
4421
4422 /* Age out logic will be taken care by the age out timer */
4423 }
4424 break;
4425 }
4426 if (fRemoveCommand)
4427 csr_release_scan_command(pMac, pCommand, scanStatus);
4428 sme_process_pending_queue(pMac);
4429 return status;
4430
4431error_handling:
4432#ifdef FEATURE_WLAN_SCAN_PNO
4433 if (pMac->pnoOffload && pScanRsp->statusCode == eSIR_PNO_SCAN_SUCCESS) {
4434 sms_log(pMac, LOGE, FL("PNO Scan completion called."));
4435 csr_save_scan_results(pMac, eCsrScanCandidateFound,
4436 pScanRsp->sessionId);
4437 return CDF_STATUS_SUCCESS;
4438 } else {
4439 /*
4440 * Scan completion was called, PNO is active, but scan
4441 * response was not PNO
4442 */
4443 sms_log(pMac, LOGE,
4444 FL("Scan completion called, scan rsp was not PNO."));
4445 return CDF_STATUS_E_FAILURE;
4446 }
4447#endif
4448 sms_log(pMac, LOGE, FL("Scan completion called, but no active SCAN command."));
4449 return CDF_STATUS_E_FAILURE;
4450}
4451
4452tCsrScanResultInfo *csr_scan_result_get_first(tpAniSirGlobal pMac,
4453 tScanResultHandle hScanResult)
4454{
4455 tListElem *pEntry;
4456 tCsrScanResult *pResult;
4457 tCsrScanResultInfo *pRet = NULL;
4458 tScanResultList *pResultList = (tScanResultList *) hScanResult;
4459
4460 if (pResultList) {
4461 csr_ll_lock(&pResultList->List);
4462 pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
4463 if (pEntry) {
4464 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4465 pRet = &pResult->Result;
4466 }
4467 pResultList->pCurEntry = pEntry;
4468 csr_ll_unlock(&pResultList->List);
4469 }
4470
4471 return pRet;
4472}
4473
4474tCsrScanResultInfo *csr_scan_result_get_next(tpAniSirGlobal pMac,
4475 tScanResultHandle hScanResult)
4476{
4477 tListElem *pEntry = NULL;
4478 tCsrScanResult *pResult = NULL;
4479 tCsrScanResultInfo *pRet = NULL;
4480 tScanResultList *pResultList = (tScanResultList *) hScanResult;
4481
4482 if (!pResultList)
4483 return NULL;
4484
4485 csr_ll_lock(&pResultList->List);
4486 if (NULL == pResultList->pCurEntry) {
4487 pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
4488 } else {
4489 pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry,
4490 LL_ACCESS_NOLOCK);
4491 }
4492 if (pEntry) {
4493 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4494 pRet = &pResult->Result;
4495 }
4496 pResultList->pCurEntry = pEntry;
4497 csr_ll_unlock(&pResultList->List);
4498 return pRet;
4499}
4500
4501/*
4502 * This function moves the first BSS that matches the bssid to the
4503 * head of the result
4504 */
4505CDF_STATUS csr_move_bss_to_head_from_bssid(tpAniSirGlobal pMac,
4506 struct cdf_mac_addr *bssid,
4507 tScanResultHandle hScanResult)
4508{
4509 CDF_STATUS status = CDF_STATUS_E_FAILURE;
4510 tScanResultList *pResultList = (tScanResultList *) hScanResult;
4511 tCsrScanResult *pResult = NULL;
4512 tListElem *pEntry = NULL;
4513
4514 if (!(pResultList && bssid))
4515 return status;
4516
4517 csr_ll_lock(&pResultList->List);
4518 pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
4519 while (pEntry) {
4520 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4521 if (cdf_mem_compare(bssid, pResult->Result.BssDescriptor.bssId,
4522 sizeof(struct cdf_mac_addr))) {
4523 status = CDF_STATUS_SUCCESS;
4524 csr_ll_remove_entry(&pResultList->List, pEntry,
4525 LL_ACCESS_NOLOCK);
4526 csr_ll_insert_head(&pResultList->List, pEntry,
4527 LL_ACCESS_NOLOCK);
4528 break;
4529 }
4530 pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry,
4531 LL_ACCESS_NOLOCK);
4532 }
4533 csr_ll_unlock(&pResultList->List);
4534 return status;
4535}
4536
4537/* Remove the BSS if possible. */
4538/* Return -- true == the BSS is remove. False == Fail to remove it */
4539/* This function is called when list lock is held. Be caution what functions it can call. */
4540bool csr_scan_age_out_bss(tpAniSirGlobal pMac, tCsrScanResult *pResult)
4541{
4542 bool fRet = false;
4543 uint32_t i;
4544 tCsrRoamSession *pSession;
4545 bool isConnBssfound = false;
4546
4547 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4548 if (!CSR_IS_SESSION_VALID(pMac, i))
4549 continue;
4550 pSession = CSR_GET_SESSION(pMac, i);
4551 /* Not to remove the BSS we are connected to. */
4552 if (csr_is_conn_state_connected_infra(pMac, i)
4553 && (NULL != pSession->pConnectBssDesc)
4554 && (csr_is_duplicate_bss_description(pMac,
4555 &pResult->Result.BssDescriptor,
4556 pSession->pConnectBssDesc, NULL, false))) {
4557 isConnBssfound = true;
4558 break;
4559 }
4560 }
4561 if (isConnBssfound) {
4562 /*
4563 * Reset the counter so that aging out of connected BSS won't
4564 * hapeen too soon
4565 */
4566 pResult->AgingCount =
4567 (int32_t) pMac->roam.configParam.agingCount;
4568 sms_log(pMac, LOGW,
4569 FL("Connected BSS, Set Aging Count=%d for BSS "
4570 MAC_ADDRESS_STR), pResult->AgingCount,
4571 MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId));
4572 pResult->Result.BssDescriptor.nReceivedTime =
4573 (uint32_t) cdf_mc_timer_get_system_ticks();
4574 return fRet;
4575 }
4576 sms_log(pMac, LOGW,
4577 "Aging out BSS " MAC_ADDRESS_STR " Channel %d",
4578 MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId),
4579 pResult->Result.BssDescriptor.channelId);
4580 /*
4581 * No need to hold the spin lock because caller should hold the lock for
4582 * pMac->scan.scanResultList
4583 */
4584 if (csr_ll_remove_entry(&pMac->scan.scanResultList, &pResult->Link,
4585 LL_ACCESS_NOLOCK)) {
4586 if (cdf_is_macaddr_equal(
4587 (struct cdf_mac_addr *) &pResult->Result.BssDescriptor.bssId,
4588 (struct cdf_mac_addr *) &pMac->scan.currentCountryBssid)) {
4589 sms_log(pMac, LOGW,
4590 FL("Aging out 11d BSS " MAC_ADDRESS_STR),
4591 MAC_ADDR_ARRAY(
4592 pResult->Result.BssDescriptor.bssId));
4593 pMac->scan.currentCountryRSSI = -128;
4594 }
4595 csr_free_scan_result_entry(pMac, pResult);
4596 fRet = true;
4597 }
4598 return fRet;
4599}
4600
4601CDF_STATUS csr_scan_age_results(tpAniSirGlobal pMac,
4602 tSmeGetScanChnRsp *pScanChnInfo)
4603{
4604 CDF_STATUS status = CDF_STATUS_SUCCESS;
4605 tListElem *pEntry, *tmpEntry;
4606 tCsrScanResult *pResult;
4607 tLimScanChn *pChnInfo;
4608 uint8_t i;
4609
4610 csr_ll_lock(&pMac->scan.scanResultList);
4611 for (i = 0; i < pScanChnInfo->numChn; i++) {
4612 pChnInfo = &pScanChnInfo->scanChn[i];
4613 pEntry =
4614 csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
4615 while (pEntry) {
4616 tmpEntry =
4617 csr_ll_next(&pMac->scan.scanResultList, pEntry,
4618 LL_ACCESS_NOLOCK);
4619 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4620 if (pResult->Result.BssDescriptor.channelId ==
4621 pChnInfo->channelId) {
4622 if (pResult->AgingCount <= 0) {
4623 sms_log(pMac, LOGW,
4624 " age out due to ref count");
4625 csr_scan_age_out_bss(pMac, pResult);
4626 } else {
4627 pResult->AgingCount--;
4628 sms_log(pMac, LOGW,
4629 FL
4630 ("Decremented AgingCount=%d for BSS "
4631 MAC_ADDRESS_STR ""),
4632 pResult->AgingCount,
4633 MAC_ADDR_ARRAY(pResult->Result.
4634 BssDescriptor.
4635 bssId));
4636 }
4637 }
4638 pEntry = tmpEntry;
4639 }
4640 }
4641 csr_ll_unlock(&pMac->scan.scanResultList);
4642
4643 return status;
4644}
4645
4646CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId,
4647 tCsrScanRequest *pScanReq,
4648 tScanReqParam *pScanReqParam)
4649{
4650 CDF_STATUS status = CDF_STATUS_SUCCESS;
4651 tSirSmeScanReq *pMsg;
4652 uint16_t msgLen;
4653 tSirScanType scanType = pScanReq->scanType;
4654 uint32_t minChnTime; /* in units of milliseconds */
4655 uint32_t maxChnTime; /* in units of milliseconds */
4656 uint32_t i;
4657 uint8_t selfMacAddr[CDF_MAC_ADDR_SIZE];
4658 uint8_t *pSelfMac = NULL;
4659
4660 msgLen = (uint16_t) (sizeof(tSirSmeScanReq) -
4661 sizeof(pMsg->channelList.channelNumber) +
4662 (sizeof(pMsg->channelList.channelNumber) *
4663 pScanReq->ChannelInfo.numOfChannels)) +
4664 (pScanReq->uIEFieldLen);
4665
4666 pMsg = cdf_mem_malloc(msgLen);
4667 if (NULL == pMsg) {
4668 sms_log(pMac, LOGE, FL("memory allocation failed"));
4669 sms_log(pMac, LOG1, FL("Failed: SId: %d FirstMatch = %d"
4670 " UniqueResult = %d freshScan = %d hiddenSsid = %d"),
4671 sessionId, pScanReqParam->bReturnAfter1stMatch,
4672 pScanReqParam->fUniqueResult, pScanReqParam->freshScan,
4673 pScanReqParam->hiddenSsid);
4674 sms_log(pMac, LOG1,
4675 FL("scanType = %u BSSType = %u numOfSSIDs = %d"
4676 " numOfChannels = %d requestType = %d p2pSearch = %d\n"),
4677 pScanReq->scanType, pScanReq->BSSType,
4678 pScanReq->SSIDs.numOfSSIDs,
4679 pScanReq->ChannelInfo.numOfChannels,
4680 pScanReq->requestType, pScanReq->p2pSearch);
4681 return CDF_STATUS_E_NOMEM;
4682 }
4683
4684 cdf_mem_set(pMsg, msgLen, 0);
4685 pMsg->messageType = eWNI_SME_SCAN_REQ;
4686 pMsg->length = msgLen;
4687 /* ToDO: Fill in session info when we need to do scan base on session */
4688 if ((sessionId != CSR_SESSION_ID_INVALID)) {
4689 pMsg->sessionId = sessionId;
4690 } else {
4691 /* if sessionId == CSR_SESSION_ID_INVALID, then send the scan
4692 request on first available session */
4693 pMsg->sessionId = 0;
4694 }
4695 if (pMsg->sessionId >= CSR_ROAM_SESSION_MAX)
4696 sms_log(pMac, LOGE, FL(" Invalid Sme Session ID = %d"),
4697 pMsg->sessionId);
4698 pMsg->transactionId = 0;
4699 pMsg->dot11mode = (uint8_t) csr_translate_to_wni_cfg_dot11_mode(pMac,
4700 csr_find_best_phy_mode(pMac,
4701 pMac->roam.configParam.phyMode));
4702 pMsg->bssType = csr_translate_bsstype_to_mac_type(pScanReq->BSSType);
4703
4704 if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
4705 pSelfMac = (uint8_t *)
4706 &pMac->roam.roamSession[sessionId].selfMacAddr;
4707 } else {
4708 /*
4709 * Since we don't have session for the scanning, we find a valid
4710 * session. In case we fail to do so, get the WNI_CFG_STA_ID
4711 */
4712 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4713 if (CSR_IS_SESSION_VALID(pMac, i)) {
4714 pSelfMac = (uint8_t *)
4715 &pMac->roam.roamSession[i].selfMacAddr;
4716 break;
4717 }
4718 }
4719 if (CSR_ROAM_SESSION_MAX == i) {
4720 uint32_t len = CDF_MAC_ADDR_SIZE;
4721 pSelfMac = selfMacAddr;
4722 status = wlan_cfg_get_str(pMac, WNI_CFG_STA_ID,
4723 pSelfMac, &len);
4724 if (!CDF_IS_STATUS_SUCCESS(status)
4725 || (len < CDF_MAC_ADDR_SIZE)) {
4726 sms_log(pMac, LOGE,
4727 FL("Can't get self MAC address = %d"),
4728 status);
4729 /* Force failed status */
4730 status = CDF_STATUS_E_FAILURE;
4731 goto send_scan_req;
4732 }
4733 }
4734 }
4735 cdf_mem_copy((uint8_t *) pMsg->selfMacAddr,
4736 pSelfMac, sizeof(tSirMacAddr));
4737
4738 /* sir_copy_mac_addr */
4739 cdf_mem_copy(pMsg->bssId, &pScanReq->bssid, sizeof(tSirMacAddr));
4740 if (cdf_is_macaddr_zero(&pScanReq->bssid))
4741 cdf_mem_set(pMsg->bssId, sizeof(tSirMacAddr), 0xff);
4742 else
4743 cdf_mem_copy(pMsg->bssId, pScanReq->bssid.bytes,
4744 CDF_MAC_ADDR_SIZE);
4745 minChnTime = pScanReq->minChnTime;
4746 maxChnTime = pScanReq->maxChnTime;
4747
4748 /*
4749 * Verify the scan type first, if the scan is active scan, we need to
4750 * make sure we are allowed to do so. if 11d is enabled & we don't see
4751 * any beacon around, scan type falls back to passive. But in BT AMP STA
4752 * mode we need to send out a directed probe
4753 */
4754 if ((eSIR_PASSIVE_SCAN != scanType)
4755 && (eCSR_SCAN_P2P_DISCOVERY !=
4756 pScanReq->requestType)
4757 && (eCSR_BSS_TYPE_WDS_STA != pScanReq->BSSType)
4758 && (false == pMac->scan.fEnableBypass11d)) {
4759 scanType = pMac->scan.curScanType;
4760 if (eSIR_PASSIVE_SCAN == pMac->scan.curScanType) {
4761 if (minChnTime <
4762 pMac->roam.configParam.nPassiveMinChnTime) {
4763 minChnTime =
4764 pMac->roam.configParam.nPassiveMinChnTime;
4765 }
4766 if (maxChnTime <
4767 pMac->roam.configParam.nPassiveMaxChnTime) {
4768 maxChnTime =
4769 pMac->roam.configParam.nPassiveMaxChnTime;
4770 }
4771 }
4772 }
4773 pMsg->scanType = scanType;
4774
4775 pMsg->numSsid = (pScanReq->SSIDs.numOfSSIDs < SIR_SCAN_MAX_NUM_SSID) ?
4776 pScanReq->SSIDs.numOfSSIDs : SIR_SCAN_MAX_NUM_SSID;
4777 if ((pScanReq->SSIDs.numOfSSIDs != 0)
4778 && (eSIR_PASSIVE_SCAN != scanType)) {
4779 for (i = 0; i < pMsg->numSsid; i++) {
4780 cdf_mem_copy(&pMsg->ssId[i],
4781 &pScanReq->SSIDs.SSIDList[i].SSID,
4782 sizeof(tSirMacSSid));
4783 }
4784 } else {
4785 /* Otherwise we scan all SSID and let the result filter later */
4786 for (i = 0; i < SIR_SCAN_MAX_NUM_SSID; i++)
4787 pMsg->ssId[i].length = 0;
4788 }
4789
4790 pMsg->minChannelTime = minChnTime;
4791 pMsg->maxChannelTime = maxChnTime;
4792 /* hidden SSID option */
4793 pMsg->hiddenSsid = pScanReqParam->hiddenSsid;
4794 /* rest time */
4795 pMsg->restTime = pScanReq->restTime;
4796 pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch;
4797 /* All the scan results caching will be done by Roaming */
4798 /* We do not want LIM to do any caching of scan results, */
4799 /* so delete the LIM cache on all scan requests */
4800 pMsg->returnFreshResults = pScanReqParam->freshScan;
4801 /* Always ask for unique result */
4802 pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
4803 pMsg->channelList.numChannels =
4804 (uint8_t) pScanReq->ChannelInfo.numOfChannels;
4805 if (pScanReq->ChannelInfo.numOfChannels) {
4806 /* Assuming the channelNumber is uint8_t (1 byte) */
4807 cdf_mem_copy(pMsg->channelList.channelNumber,
4808 pScanReq->ChannelInfo.ChannelList,
4809 pScanReq->ChannelInfo.numOfChannels);
4810 }
4811
4812 pMsg->uIEFieldLen = (uint16_t) pScanReq->uIEFieldLen;
4813 pMsg->uIEFieldOffset = (uint16_t) (sizeof(tSirSmeScanReq) -
4814 sizeof(pMsg->channelList.channelNumber) +
4815 (sizeof(pMsg->channelList.channelNumber) *
4816 pScanReq->ChannelInfo.numOfChannels));
4817 if (pScanReq->uIEFieldLen != 0) {
4818 cdf_mem_copy((uint8_t *) pMsg + pMsg->uIEFieldOffset,
4819 pScanReq->pIEField, pScanReq->uIEFieldLen);
4820 }
4821 pMsg->p2pSearch = pScanReq->p2pSearch;
4822 pMsg->scan_id = pScanReq->scan_id;
4823
4824send_scan_req:
4825 sms_log(pMac, LOG1,
4826 FL("scanId %d domainIdCurrent %d scanType %d bssType %d requestType %d numChannels %d"),
4827 pMsg->scan_id, pMac->scan.domainIdCurrent, pMsg->scanType,
4828 pMsg->bssType, pScanReq->requestType,
4829 pMsg->channelList.numChannels);
4830
4831 for (i = 0; i < pMsg->channelList.numChannels; i++) {
4832 sms_log(pMac, LOG1, FL("channelNumber[%d]= %d"), i,
4833 pMsg->channelList.channelNumber[i]);
4834 }
4835
4836 if (CDF_IS_STATUS_SUCCESS(status)) {
4837 status = cds_send_mb_message_to_mac(pMsg);
4838 } else {
4839 sms_log(pMac, LOGE,
4840 FL("failed to send down scan req with status = %d"),
4841 status);
4842 cdf_mem_free(pMsg);
4843 }
4844 return status;
4845}
4846
4847CDF_STATUS csr_send_mb_scan_result_req(tpAniSirGlobal pMac,
4848 uint32_t sessionId,
4849 tScanReqParam *pScanReqParam)
4850{
4851 CDF_STATUS status = CDF_STATUS_SUCCESS;
4852 tSirSmeScanReq *pMsg;
4853 uint16_t msgLen;
4854
4855 msgLen = (uint16_t) (sizeof(tSirSmeScanReq));
4856 pMsg = cdf_mem_malloc(msgLen);
4857 if (NULL == pMsg)
4858 return CDF_STATUS_E_NOMEM;
4859
4860 cdf_mem_set(pMsg, msgLen, 0);
4861 pMsg->messageType = eWNI_SME_SCAN_REQ;
4862 pMsg->length = msgLen;
4863 pMsg->sessionId = sessionId;
4864 pMsg->transactionId = 0;
4865 pMsg->returnFreshResults = pScanReqParam->freshScan;
4866 /* Always ask for unique result */
4867 pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
4868 pMsg->returnAfterFirstMatch =
4869 pScanReqParam->bReturnAfter1stMatch;
4870 status = cds_send_mb_message_to_mac(pMsg);
4871 if (!CDF_IS_STATUS_SUCCESS(status)) {
4872 sms_log(pMac, LOGE,
4873 FL("Failed to send down scan req with status = %d\n"),
4874 status);
4875 }
4876 return status;
4877}
4878
4879#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
4880static void csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand)
4881{
4882 host_log_scan_pkt_type *pScanLog = NULL;
4883
4884 WLAN_HOST_DIAG_LOG_ALLOC(pScanLog,
4885 host_log_scan_pkt_type,
4886 LOG_WLAN_SCAN_C);
4887 if (!pScanLog)
4888 return;
4889
4890 if (eCsrScanProbeBss == pCommand->u.scanCmd.reason) {
4891 pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ;
4892 } else {
4893 if ((eSIR_PASSIVE_SCAN !=
4894 pCommand->u.scanCmd.u.scanRequest.scanType)
4895 && (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)) {
4896 pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ;
4897 } else {
4898 pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ;
4899 }
4900 }
4901 pScanLog->minChnTime =
4902 (uint8_t) pCommand->u.scanCmd.u.scanRequest.minChnTime;
4903 pScanLog->maxChnTime =
4904 (uint8_t) pCommand->u.scanCmd.u.scanRequest.maxChnTime;
4905 pScanLog->numChannel =
4906 (uint8_t) pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
4907 if (pScanLog->numChannel &&
4908 (pScanLog->numChannel < HOST_LOG_MAX_NUM_CHANNEL)) {
4909 cdf_mem_copy(pScanLog->channels,
4910 pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
4911 pScanLog->numChannel);
4912 }
4913 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
4914}
4915#else
4916#define csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand) (void)0;
4917#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
4918
4919CDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand)
4920{
4921 CDF_STATUS status = CDF_STATUS_E_FAILURE;
4922 tScanReqParam scanReq;
4923
4924 /*
4925 * Don't delete cached results. Rome rssi based scan candidates may land
4926 * up in scan cache instead of LFR cache. They will be deleted upon
4927 * query
4928 */
4929 scanReq.freshScan = SIR_BG_SCAN_RETURN_FRESH_RESULTS;
4930 scanReq.fUniqueResult = true;
4931 scanReq.hiddenSsid = SIR_SCAN_NO_HIDDEN_SSID;
4932 if (eCsrScanForSsid == pCommand->u.scanCmd.reason) {
4933 scanReq.bReturnAfter1stMatch =
4934 CSR_SCAN_RETURN_AFTER_FIRST_MATCH;
4935 } else {
4936 /*
4937 * Basically do scan on all channels even for 11D 1st scan case
4938 */
4939 scanReq.bReturnAfter1stMatch =
4940 CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
4941 }
4942 if (eCsrScanProbeBss == pCommand->u.scanCmd.reason)
4943 scanReq.hiddenSsid = SIR_SCAN_HIDDEN_SSID_PE_DECISION;
4944 csr_diag_scan_channels(pMac, pCommand);
4945 csr_clear_votes_for_country_info(pMac);
4946 status = csr_send_mb_scan_req(pMac, pCommand->sessionId,
4947 &pCommand->u.scanCmd.u.scanRequest,
4948 &scanReq);
4949 return status;
4950}
4951
4952static CDF_STATUS
4953csr_issue_user_scan(tpAniSirGlobal mac_ctx, tSmeCmd *cmd)
4954{
4955 int i, j;
4956 CDF_STATUS status;
4957 uint32_t len = 0;
4958 uint8_t *ch_lst = NULL;
4959 tCsrChannelInfo new_ch_info = { 0, NULL };
4960
4961 if (!mac_ctx->roam.configParam.fScanTwice)
4962 return csr_scan_channels(mac_ctx, cmd);
4963
4964 /* We scan 2.4 channel twice */
4965 if (cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels
4966 && (NULL != cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)) {
4967 len = cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
4968 /* allocate twice the channel */
4969 new_ch_info.ChannelList = (uint8_t *) cdf_mem_malloc(len * 2);
4970 ch_lst = cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList;
4971 } else {
4972 /* get the valid channel list to scan all. */
4973 len = sizeof(mac_ctx->roam.validChannelList);
4974 status = csr_get_cfg_valid_channels(mac_ctx,
4975 (uint8_t *) mac_ctx->roam.validChannelList, &len);
4976 if (CDF_IS_STATUS_SUCCESS(status)) {
4977 /* allocate twice the channel */
4978 new_ch_info.ChannelList =
4979 (uint8_t *) cdf_mem_malloc(len * 2);
4980 ch_lst = mac_ctx->roam.validChannelList;
4981 }
4982 }
4983 if (NULL == new_ch_info.ChannelList) {
4984 new_ch_info.numOfChannels = 0;
4985 } else {
4986 j = 0;
4987 for (i = 0; i < len; i++) {
4988 new_ch_info.ChannelList[j++] = ch_lst[i];
4989 if (CDS_MAX_24GHz_CHANNEL_NUMBER >= ch_lst[i])
4990 new_ch_info.ChannelList[j++] = ch_lst[i];
4991 }
4992 if (NULL !=
4993 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) {
4994 /*
4995 * ch_lst points to the channellist from the command,
4996 * free it.
4997 */
4998 cdf_mem_free(
4999 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList);
5000 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList =
5001 NULL;
5002 }
5003 cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = j;
5004 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList =
5005 new_ch_info.ChannelList;
5006 }
5007
5008 return csr_scan_channels(mac_ctx, cmd);
5009}
5010
5011CDF_STATUS csr_process_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
5012{
5013 CDF_STATUS status = CDF_STATUS_SUCCESS;
5014
5015 sms_log(pMac, LOG3,
5016 FL("starting SCAN cmd in %d state. reason %d"),
5017 pCommand->u.scanCmd.lastRoamState[pCommand->sessionId],
5018 pCommand->u.scanCmd.reason);
5019
5020 switch (pCommand->u.scanCmd.reason) {
5021 case eCsrScanUserRequest:
5022 status = csr_issue_user_scan(pMac, pCommand);
5023 break;
5024 default:
5025 status = csr_scan_channels(pMac, pCommand);
5026 break;
5027 }
5028
5029 if (!CDF_IS_STATUS_SUCCESS(status)) {
5030 csr_release_scan_command(pMac, pCommand, eCSR_SCAN_FAILURE);
5031 }
5032
5033 return status;
5034}
5035
5036/**
5037 * csr_scan_copy_request_valid_channels_only() - scan request of valid channels
5038 * @mac_ctx : pointer to Global Mac Structure
5039 * @dst_req: pointer to tCsrScanRequest
5040 * @skip_dfs_chnl: 1 - skip dfs channel, 0 - don't skip dfs channel
5041 * @src_req: pointer to tCsrScanRequest
5042 *
5043 * This function makes a copy of scan request with valid channels
5044 *
5045 * Return: none
5046 */
5047static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx,
5048 tCsrScanRequest *dst_req, uint8_t skip_dfs_chnl,
5049 tCsrScanRequest *src_req)
5050{
5051 uint32_t index = 0;
5052 uint32_t new_index = 0;
5053
5054 for (index = 0; index < src_req->ChannelInfo.numOfChannels; index++) {
5055 /* Allow scan on valid channels only.
5056 * If it is p2p scan and valid channel list doesnt contain
5057 * social channels, enforce scan on social channels because
5058 * that is the only way to find p2p peers.
5059 * This can happen only if band is set to 5Ghz mode.
5060 */
5061 if (src_req->ChannelInfo.ChannelList[index] < MIN_11P_CHANNEL &&
5062 ((csr_roam_is_valid_channel(mac_ctx,
5063 src_req->ChannelInfo.ChannelList[index])) ||
5064 ((eCSR_SCAN_P2P_DISCOVERY == src_req->requestType) &&
5065 CSR_IS_SOCIAL_CHANNEL(
5066 src_req->ChannelInfo.ChannelList[index])))) {
5067 if (((src_req->skipDfsChnlInP2pSearch || skip_dfs_chnl)
5068 && (CHANNEL_STATE_DFS ==
5069 cds_get_channel_state(src_req->
5070 ChannelInfo.
5071 ChannelList
5072 [index])))
5073 ) {
5074#ifdef FEATURE_WLAN_LFR
5075 sms_log(mac_ctx, LOG2,
5076 FL(" reqType=%d, numOfChannels=%d, ignoring DFS channel %d"),
5077 src_req->requestType,
5078 src_req->ChannelInfo.numOfChannels,
5079 src_req->ChannelInfo.ChannelList
5080 [index]);
5081#endif
5082 continue;
5083 }
5084
5085 dst_req->ChannelInfo.ChannelList[new_index] =
5086 src_req->ChannelInfo.ChannelList[index];
5087 new_index++;
5088 }
5089 }
5090 dst_req->ChannelInfo.numOfChannels = new_index;
5091}
5092
5093/**
5094 * csr_scan_copy_request() - Function to copy scan request
5095 * @mac_ctx : pointer to Global Mac Structure
5096 * @dst_req: pointer to tCsrScanRequest
5097 * @src_req: pointer to tCsrScanRequest
5098 *
5099 * This function makes a copy of scan request
5100 *
5101 * Return: 0 - Success, Error number - Failure
5102 */
5103CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx,
5104 tCsrScanRequest *dst_req,
5105 tCsrScanRequest *src_req)
5106{
5107 CDF_STATUS status = CDF_STATUS_SUCCESS;
5108 uint32_t len = sizeof(mac_ctx->roam.validChannelList);
5109 uint32_t index = 0;
5110 uint32_t new_index = 0;
5111 CHANNEL_STATE channel_state;
5112 bool skip_dfs_chnl =
5113 mac_ctx->roam.configParam.initial_scan_no_dfs_chnl ||
5114 !mac_ctx->scan.fEnableDFSChnlScan;
5115
5116 status = csr_scan_free_request(mac_ctx, dst_req);
5117 if (!CDF_IS_STATUS_SUCCESS(status))
5118 goto complete;
5119 cdf_mem_copy(dst_req, src_req, sizeof(tCsrScanRequest));
5120 /* Re-initialize the pointers to NULL since we did a copy */
5121 dst_req->pIEField = NULL;
5122 dst_req->ChannelInfo.ChannelList = NULL;
5123 dst_req->SSIDs.SSIDList = NULL;
5124
5125 if (src_req->uIEFieldLen) {
5126 dst_req->pIEField =
5127 cdf_mem_malloc(src_req->uIEFieldLen);
5128 if (NULL == dst_req->pIEField) {
5129 status = CDF_STATUS_E_NOMEM;
5130 sms_log(mac_ctx, LOGE,
5131 FL("No memory for scanning IE fields"));
5132 goto complete;
5133 } else {
5134 status = CDF_STATUS_SUCCESS;
5135 cdf_mem_copy(dst_req->pIEField, src_req->pIEField,
5136 src_req->uIEFieldLen);
5137 dst_req->uIEFieldLen = src_req->uIEFieldLen;
5138 }
5139 }
5140
5141 /* Allocate memory for IE field */
5142 if (src_req->ChannelInfo.numOfChannels == 0) {
5143 dst_req->ChannelInfo.ChannelList = NULL;
5144 dst_req->ChannelInfo.numOfChannels = 0;
5145 } else {
5146 dst_req->ChannelInfo.ChannelList =
5147 cdf_mem_malloc(src_req->ChannelInfo.numOfChannels *
5148 sizeof(*dst_req->ChannelInfo.ChannelList));
5149 if (NULL == dst_req->ChannelInfo.ChannelList) {
5150 status = CDF_STATUS_E_NOMEM;
5151 dst_req->ChannelInfo.numOfChannels = 0;
5152 sms_log(mac_ctx, LOGE,
5153 FL("No memory for scanning Channel List"));
5154 goto complete;
5155 }
5156
5157 if ((src_req->scanType == eSIR_PASSIVE_SCAN) &&
5158 (src_req->requestType == eCSR_SCAN_REQUEST_11D_SCAN)) {
5159 for (index = 0; index < src_req->ChannelInfo.
5160 numOfChannels; index++) {
5161 channel_state =
5162 cds_get_channel_state(src_req->
5163 ChannelInfo.
5164 ChannelList[index]);
5165 if (src_req->ChannelInfo.ChannelList[index] <
5166 MIN_11P_CHANNEL &&
5167 ((CHANNEL_STATE_ENABLE ==
5168 channel_state) ||
5169 ((CHANNEL_STATE_DFS == channel_state) &&
5170 !skip_dfs_chnl))) {
5171 dst_req->ChannelInfo.ChannelList
5172 [new_index] =
5173 src_req->
5174 ChannelInfo.
5175 ChannelList
5176 [index];
5177 new_index++;
5178 }
5179 }
5180 dst_req->ChannelInfo.numOfChannels = new_index;
5181 } else if (CDF_IS_STATUS_SUCCESS(
5182 csr_get_cfg_valid_channels(mac_ctx,
5183 mac_ctx->roam.validChannelList,
5184 &len))) {
5185 new_index = 0;
5186 mac_ctx->roam.numValidChannels = len;
5187 csr_scan_copy_request_valid_channels_only(mac_ctx,
5188 dst_req, skip_dfs_chnl,
5189 src_req);
5190 } else {
5191 sms_log(mac_ctx, LOGE,
5192 FL("Couldn't get the valid Channel List, keeping requester's list"));
5193 new_index = 0;
5194 for (index = 0; index < src_req->ChannelInfo.
5195 numOfChannels; index++) {
5196 if (src_req->ChannelInfo.ChannelList[index] <
5197 MIN_11P_CHANNEL) {
5198 dst_req->ChannelInfo.
5199 ChannelList[new_index] =
5200 src_req->ChannelInfo.
5201 ChannelList[index];
5202 new_index++;
5203 }
5204 }
5205 dst_req->ChannelInfo.numOfChannels =
5206 new_index;
5207 }
5208 } /* Allocate memory for Channel List */
5209 if (src_req->SSIDs.numOfSSIDs == 0) {
5210 dst_req->SSIDs.numOfSSIDs = 0;
5211 dst_req->SSIDs.SSIDList = NULL;
5212 } else {
5213 dst_req->SSIDs.SSIDList =
5214 cdf_mem_malloc(src_req->SSIDs.numOfSSIDs *
5215 sizeof(*dst_req->SSIDs.SSIDList));
5216 if (NULL == dst_req->SSIDs.SSIDList)
5217 status = CDF_STATUS_E_NOMEM;
5218 else
5219 status = CDF_STATUS_SUCCESS;
5220 if (CDF_IS_STATUS_SUCCESS(status)) {
5221 dst_req->SSIDs.numOfSSIDs =
5222 src_req->SSIDs.numOfSSIDs;
5223 cdf_mem_copy(dst_req->SSIDs.SSIDList,
5224 src_req->SSIDs.SSIDList,
5225 src_req->SSIDs.numOfSSIDs *
5226 sizeof(*dst_req->SSIDs.SSIDList));
5227 } else {
5228 dst_req->SSIDs.numOfSSIDs = 0;
5229 sms_log(mac_ctx, LOGE,
5230 FL("No memory for scanning SSID List"));
5231 goto complete;
5232 }
5233 } /* Allocate memory for SSID List */
5234 dst_req->p2pSearch = src_req->p2pSearch;
5235 dst_req->skipDfsChnlInP2pSearch =
5236 src_req->skipDfsChnlInP2pSearch;
5237 dst_req->scan_id = src_req->scan_id;
5238 dst_req->timestamp = src_req->timestamp;
5239
5240complete:
5241 if (!CDF_IS_STATUS_SUCCESS(status)) {
5242 csr_scan_free_request(mac_ctx, dst_req);
5243 }
5244
5245 return status;
5246}
5247
5248CDF_STATUS csr_scan_free_request(tpAniSirGlobal pMac, tCsrScanRequest *pReq)
5249{
5250
5251 if (pReq->ChannelInfo.ChannelList) {
5252 cdf_mem_free(pReq->ChannelInfo.ChannelList);
5253 pReq->ChannelInfo.ChannelList = NULL;
5254 }
5255 pReq->ChannelInfo.numOfChannels = 0;
5256 if (pReq->pIEField) {
5257 cdf_mem_free(pReq->pIEField);
5258 pReq->pIEField = NULL;
5259 }
5260 pReq->uIEFieldLen = 0;
5261 if (pReq->SSIDs.SSIDList) {
5262 cdf_mem_free(pReq->SSIDs.SSIDList);
5263 pReq->SSIDs.SSIDList = NULL;
5264 }
5265 pReq->SSIDs.numOfSSIDs = 0;
5266
5267 return CDF_STATUS_SUCCESS;
5268}
5269
5270void csr_scan_call_callback(tpAniSirGlobal pMac, tSmeCmd *pCommand,
5271 eCsrScanStatus scanStatus)
5272{
5273 if (pCommand->u.scanCmd.callback) {
5274 pCommand->u.scanCmd.callback(pMac, pCommand->u.scanCmd.pContext,
5275 pCommand->sessionId,
5276 pCommand->u.scanCmd.scanID,
5277 scanStatus);
5278 } else {
5279 sms_log(pMac, LOG2, "%s:%d - Callback NULL!!!", __func__,
5280 __LINE__);
5281 }
5282}
5283
5284void csr_scan_stop_timers(tpAniSirGlobal pMac)
5285{
5286 if (0 != pMac->scan.scanResultCfgAgingTime) {
5287 csr_scan_stop_result_cfg_aging_timer(pMac);
5288 }
5289
5290}
5291
5292#ifdef WLAN_AP_STA_CONCURRENCY
5293/**
5294 * csr_sta_ap_conc_timer_handler - Function to handle STA,AP concurrency timer
5295 * @pv: pointer variable
5296 *
5297 * Function handles STA,AP concurrency timer
5298 *
5299 * Return: none
5300 */
5301static void csr_sta_ap_conc_timer_handler(void *pv)
5302{
5303 tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv);
5304 tListElem *entry;
5305 tSmeCmd *scan_cmd;
5306 uint32_t session_id = CSR_SESSION_ID_INVALID;
5307 tCsrScanRequest scan_req;
5308 tSmeCmd *send_scancmd = NULL;
5309 uint8_t num_chn = 0;
5310 uint8_t numchan_combinedconc = 0;
5311 uint8_t i, j;
5312 tCsrChannelInfo *chn_info = NULL;
5313 uint8_t channel_to_scan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5314 CDF_STATUS status;
5315
5316 csr_ll_lock(&mac_ctx->scan.scanCmdPendingList);
5317
5318 entry = csr_ll_peek_head(&mac_ctx->scan.scanCmdPendingList,
5319 LL_ACCESS_NOLOCK);
5320
5321 if (NULL == entry) {
5322 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5323 return;
5324 }
5325
5326
5327 chn_info = &scan_req.ChannelInfo;
5328 scan_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
5329 num_chn =
5330 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
5331 session_id = scan_cmd->sessionId;
5332
5333 /*
5334 * if any session is connected and the number of channels to scan is
5335 * greater than 1 then split the scan into multiple scan operations
5336 * on each individual channel else continue to perform scan on all
5337 * specified channels */
5338
5339 /*
5340 * split scan if number of channels to scan is greater than 1 and
5341 * any one of the following:
5342 * - STA session is connected and the scan is not a P2P search
5343 * - any P2P session is connected
5344 * Do not split scans if no concurrent infra connections are
5345 * active and if the scan is a BG scan triggered by LFR (OR)
5346 * any scan if LFR is in the middle of a BG scan. Splitting
5347 * the scan is delaying the time it takes for LFR to find
5348 * candidates and resulting in disconnects.
5349 */
5350
5351 if ((csr_is_sta_session_connected(mac_ctx) &&
5352 !csr_is_p2p_session_connected(mac_ctx)))
5353 numchan_combinedconc =
5354 mac_ctx->roam.configParam.nNumStaChanCombinedConc;
5355 else if (csr_is_p2p_session_connected(mac_ctx))
5356 numchan_combinedconc =
5357 mac_ctx->roam.configParam.nNumP2PChanCombinedConc;
5358
5359 if ((num_chn > numchan_combinedconc) &&
5360 ((csr_is_sta_session_connected(mac_ctx) &&
5361#ifdef FEATURE_WLAN_LFR
5362 (csr_is_concurrent_infra_connected(mac_ctx)) &&
5363#endif
5364 (scan_cmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) ||
5365 (csr_is_p2p_session_connected(mac_ctx)))) {
5366 cdf_mem_set(&scan_req, sizeof(tCsrScanRequest), 0);
5367
5368 /* optimize this to use 2 command buffer only */
5369 send_scancmd = csr_get_command_buffer(mac_ctx);
5370 if (!send_scancmd) {
5371 sms_log(mac_ctx, LOGE,
5372 FL(" Failed to get Queue command buffer"));
5373 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5374 return;
5375 }
5376 send_scancmd->command = scan_cmd->command;
5377 send_scancmd->sessionId = scan_cmd->sessionId;
5378 send_scancmd->u.scanCmd.callback = NULL;
5379 send_scancmd->u.scanCmd.pContext =
5380 scan_cmd->u.scanCmd.pContext;
5381 send_scancmd->u.scanCmd.reason =
5382 scan_cmd->u.scanCmd.reason;
5383 /* let it wrap around */
5384 wma_get_scan_id(&send_scancmd->u.scanCmd.scanID);
5385
5386 /*
5387 * First copy all the parameters to local variable of scan
5388 * request
5389 */
5390 csr_scan_copy_request(mac_ctx, &scan_req,
5391 &scan_cmd->u.scanCmd.u.scanRequest);
5392
5393 /*
5394 * Now modify the elements of local var scan request required
5395 * to be modified for split scan
5396 */
5397 if (scan_req.ChannelInfo.ChannelList != NULL) {
5398 cdf_mem_free(scan_req.ChannelInfo.ChannelList);
5399 scan_req.ChannelInfo.ChannelList = NULL;
5400 }
5401
5402 chn_info->numOfChannels = numchan_combinedconc;
5403 cdf_mem_copy(&channel_to_scan[0],
5404 &scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.
5405 ChannelList[0], chn_info->numOfChannels
5406 * sizeof(uint8_t));
5407 chn_info->ChannelList = &channel_to_scan[0];
5408
5409 for (i = 0, j = numchan_combinedconc;
5410 i < (num_chn - numchan_combinedconc);
5411 i++, j++) {
5412 /* Move all the channels one step */
5413 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.
5414 ChannelList[i] =
5415 scan_cmd->u.scanCmd.u.scanRequest.
5416 ChannelInfo.ChannelList[j];
5417 }
5418
5419 /* reduce outstanding # of channels to be scanned */
5420 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels =
5421 num_chn - numchan_combinedconc;
5422
5423 scan_req.BSSType = eCSR_BSS_TYPE_ANY;
5424 /* Modify callers parameters in case of concurrency */
5425 scan_req.scanType = eSIR_ACTIVE_SCAN;
5426 /* Use concurrency values for min/maxChnTime. */
5427 csr_set_default_scan_timing(mac_ctx, scan_req.scanType,
5428 &scan_req);
5429
5430 status = csr_scan_copy_request(mac_ctx,
5431 &send_scancmd->u.scanCmd.u.
5432 scanRequest, &scan_req);
5433 if (!CDF_IS_STATUS_SUCCESS(status)) {
5434 sms_log(mac_ctx, LOGE,
5435 FL(" Failed to get copy csr_scan_request = %d"),
5436 status);
5437 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5438 return;
5439 }
5440 /* Clean the local scan variable */
5441 scan_req.ChannelInfo.ChannelList = NULL;
5442 scan_req.ChannelInfo.numOfChannels = 0;
5443 csr_scan_free_request(mac_ctx, &scan_req);
5444 } else {
5445 /*
5446 * no active connected session present or numChn == 1
5447 * scan all remaining channels
5448 */
5449 send_scancmd = scan_cmd;
5450 /* remove this command from pending list */
5451 if (csr_ll_remove_head(&mac_ctx->scan.scanCmdPendingList,
5452 /*
5453 * In case between PeekHead and here, the entry
5454 * got removed by another thread.
5455 */
5456 LL_ACCESS_NOLOCK) == NULL) {
5457 sms_log(mac_ctx, LOGE,
5458 FL(" Failed to remove entry from scanCmdPendingList"));
5459 }
5460
5461 }
5462 csr_queue_sme_command(mac_ctx, send_scancmd, false);
5463
5464
5465 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5466
5467}
5468#endif
5469
5470CDF_STATUS csr_scan_start_result_cfg_aging_timer(tpAniSirGlobal pMac)
5471{
5472 CDF_STATUS status = CDF_STATUS_E_FAILURE;
5473
5474 if (pMac->scan.fScanEnable) {
5475 status =
5476 cdf_mc_timer_start(&pMac->scan.hTimerResultCfgAging,
5477 CSR_SCAN_RESULT_CFG_AGING_INTERVAL /
5478 CDF_MC_TIMER_TO_MS_UNIT);
5479 }
5480 return status;
5481}
5482
5483CDF_STATUS csr_scan_stop_result_cfg_aging_timer(tpAniSirGlobal pMac)
5484{
5485 return cdf_mc_timer_stop(&pMac->scan.hTimerResultCfgAging);
5486}
5487
5488/**
5489 * csr_scan_result_cfg_aging_timer_handler() - Time based scan aging handler
5490 * @pv: Global context
5491 *
5492 * This routine is to handle scan aging based on user configured timer value.
5493 *
5494 * Return: None
5495 */
5496static void csr_scan_result_cfg_aging_timer_handler(void *pv)
5497{
5498 tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv);
5499 tListElem *entry, *tmp_entry;
5500 tCsrScanResult *result;
5501 uint32_t ageout_time =
5502 mac_ctx->scan.scanResultCfgAgingTime * CDF_TICKS_PER_SECOND/10;
5503 uint32_t cur_time = (uint32_t) cdf_mc_timer_get_system_ticks();
5504 uint8_t *bssId;
5505
5506 csr_ll_lock(&mac_ctx->scan.scanResultList);
5507 entry = csr_ll_peek_head(&mac_ctx->scan.scanResultList, LL_ACCESS_NOLOCK);
5508 while (entry) {
5509 tmp_entry = csr_ll_next(&mac_ctx->scan.scanResultList, entry,
5510 LL_ACCESS_NOLOCK);
5511 result = GET_BASE_ADDR(entry, tCsrScanResult, Link);
5512 /*
5513 * cdf_mc_timer_get_system_ticks() returns in 10ms interval.
5514 * so ageout time value also updated to 10ms interval value.
5515 */
5516 if ((cur_time - result->Result.BssDescriptor.nReceivedTime) >
5517 ageout_time) {
5518 bssId = result->Result.BssDescriptor.bssId;
5519 sms_log(mac_ctx, LOGW,
5520 FL("age out due to time out"MAC_ADDRESS_STR),
5521 MAC_ADDR_ARRAY(bssId));
5522 csr_scan_age_out_bss(mac_ctx, result);
5523 }
5524 entry = tmp_entry;
5525 }
5526 csr_ll_unlock(&mac_ctx->scan.scanResultList);
5527 cdf_mc_timer_start(&mac_ctx->scan.hTimerResultCfgAging,
5528 CSR_SCAN_RESULT_CFG_AGING_INTERVAL /
5529 CDF_MC_TIMER_TO_MS_UNIT);
5530}
5531
5532bool csr_scan_remove_fresh_scan_command(tpAniSirGlobal pMac, uint8_t sessionId)
5533{
5534 bool fRet = false;
5535 tListElem *pEntry, *pEntryTmp;
5536 tSmeCmd *pCommand;
5537 tDblLinkList localList;
5538 tDblLinkList *pCmdList;
5539
5540 cdf_mem_zero(&localList, sizeof(tDblLinkList));
5541 if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
5542 sms_log(pMac, LOGE, FL(" failed to open list"));
5543 return fRet;
5544 }
5545
5546 pCmdList = &pMac->sme.smeScanCmdPendingList;
5547
5548 csr_ll_lock(pCmdList);
5549 pEntry = csr_ll_peek_head(pCmdList, LL_ACCESS_NOLOCK);
5550 while (pEntry) {
5551 pEntryTmp = csr_ll_next(pCmdList, pEntry, LL_ACCESS_NOLOCK);
5552 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
5553 if (!((eSmeCommandScan == pCommand->command)
5554 && (sessionId == pCommand->sessionId))) {
5555 pEntry = pEntryTmp;
5556 continue;
5557 }
5558 sms_log(pMac, LOGW,
5559 FL("-------- abort scan command reason = %d"),
5560 pCommand->u.scanCmd.reason);
5561 /* The rest are fresh scan requests */
5562 if (csr_ll_remove_entry(pCmdList, pEntry,
5563 LL_ACCESS_NOLOCK)) {
5564 csr_ll_insert_tail(&localList, pEntry,
5565 LL_ACCESS_NOLOCK);
5566 }
5567 fRet = true;
5568 pEntry = pEntryTmp;
5569 }
5570
5571 csr_ll_unlock(pCmdList);
5572
5573 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
5574 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
5575 if (pCommand->u.scanCmd.callback) {
5576 /*
5577 * User scan request is pending, send response with
5578 * status eCSR_SCAN_ABORT
5579 */
5580 pCommand->u.scanCmd.callback(pMac,
5581 pCommand->u.scanCmd.pContext, sessionId,
5582 pCommand->u.scanCmd.scanID, eCSR_SCAN_ABORT);
5583 }
5584 csr_release_command_scan(pMac, pCommand);
5585 }
5586 csr_ll_close(&localList);
5587
5588 return fRet;
5589}
5590
5591void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
5592 eCsrScanStatus scanStatus)
5593{
5594 eCsrScanReason reason = pCommand->u.scanCmd.reason;
5595 bool status;
5596 tDblLinkList *cmd_list = NULL;
5597
5598 csr_scan_call_callback(pMac, pCommand, scanStatus);
5599 sms_log(pMac, LOG1, FL("Remove Scan command reason = %d, scan_id %d"),
5600 reason, pCommand->u.scanCmd.scanID);
5601 cmd_list = &pMac->sme.smeScanCmdActiveList;
5602 status = csr_ll_remove_entry(cmd_list, &pCommand->Link, LL_ACCESS_LOCK);
5603 if (!status) {
5604 sms_log(pMac, LOGE,
5605 FL("cannot release command reason %d scan_id %d"),
5606 pCommand->u.scanCmd.reason,
5607 pCommand->u.scanCmd.scanID);
5608 return;
5609 }
5610 csr_release_command_scan(pMac, pCommand);
5611}
5612
5613CDF_STATUS csr_scan_get_pmkid_candidate_list(tpAniSirGlobal pMac,
5614 uint32_t sessionId,
5615 tPmkidCandidateInfo *pPmkidList,
5616 uint32_t *pNumItems)
5617{
5618 CDF_STATUS status = CDF_STATUS_SUCCESS;
5619 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
5620 tCsrScanResultFilter *pScanFilter;
5621 tCsrScanResultInfo *pScanResult;
5622 tScanResultHandle hBSSList;
5623 uint32_t nItems = *pNumItems;
5624
5625 if (!pSession) {
5626 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
5627 return CDF_STATUS_E_FAILURE;
5628 }
5629
5630 sms_log(pMac, LOGW, FL("pMac->scan.NumPmkidCandidate = %d"),
5631 pSession->NumPmkidCandidate);
5632 csr_reset_pmkid_candidate_list(pMac, sessionId);
5633 if (!(csr_is_conn_state_connected(pMac, sessionId)
5634 && pSession->pCurRoamProfile))
5635 return status;
5636
5637 *pNumItems = 0;
5638 pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
5639 if (NULL == pScanFilter)
5640 return CDF_STATUS_E_NOMEM;
5641
5642 cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
5643 /* Here is the profile we need to connect to */
5644 status = csr_roam_prepare_filter_from_profile(pMac,
5645 pSession->pCurRoamProfile, pScanFilter);
5646 if (!CDF_IS_STATUS_SUCCESS(status)) {
5647 cdf_mem_free(pScanFilter);
5648 return status;
5649 }
5650
5651 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
5652 if (!CDF_IS_STATUS_SUCCESS(status)) {
5653 csr_free_scan_filter(pMac, pScanFilter);
5654 cdf_mem_free(pScanFilter);
5655 return status;
5656 }
5657
5658 if (pSession->NumPmkidCandidate < nItems) {
5659 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
5660 while (pScanResult != NULL) {
5661 /* NumPmkidCandidate adds up here */
5662 csr_process_bss_desc_for_pmkid_list(pMac,
5663 &pScanResult->BssDescriptor,
5664 (tDot11fBeaconIEs *)(pScanResult->pvIes),
5665 sessionId);
5666 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
5667 }
5668 }
5669
5670 if (pSession->NumPmkidCandidate) {
5671 *pNumItems = pSession->NumPmkidCandidate;
5672 cdf_mem_copy(pPmkidList, pSession->PmkidCandidateInfo,
5673 pSession->NumPmkidCandidate *
5674 sizeof(tPmkidCandidateInfo));
5675 }
5676
5677 csr_scan_result_purge(pMac, hBSSList);
5678 csr_free_scan_filter(pMac, pScanFilter);
5679 cdf_mem_free(pScanFilter);
5680 return status;
5681}
5682
5683#ifdef FEATURE_WLAN_WAPI
5684CDF_STATUS csr_scan_get_bkid_candidate_list(tpAniSirGlobal pMac,
5685 uint32_t sessionId,
5686 tBkidCandidateInfo *pBkidList,
5687 uint32_t *pNumItems)
5688{
5689 CDF_STATUS status = CDF_STATUS_SUCCESS;
5690 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
5691 tCsrScanResultFilter *pScanFilter;
5692 tCsrScanResultInfo *pScanResult;
5693 tScanResultHandle hBSSList;
5694 uint32_t nItems = *pNumItems;
5695
5696 if (!pSession) {
5697 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
5698 return CDF_STATUS_E_FAILURE;
5699 }
5700
5701 sms_log(pMac, LOGW, FL("pMac->scan.NumBkidCandidate = %d"),
5702 pSession->NumBkidCandidate);
5703 csr_reset_bkid_candidate_list(pMac, sessionId);
5704 if (!(csr_is_conn_state_connected(pMac, sessionId)
5705 && pSession->pCurRoamProfile))
5706 return status;
5707
5708 *pNumItems = 0;
5709 pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
5710 if (NULL == pScanFilter)
5711 return CDF_STATUS_E_NOMEM;
5712
5713 cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
5714 /* Here is the profile we need to connect to */
5715 status = csr_roam_prepare_filter_from_profile(pMac,
5716 pSession->pCurRoamProfile, pScanFilter);
5717 if (!CDF_IS_STATUS_SUCCESS(status)) {
5718 cdf_mem_free(pScanFilter);
5719 return status;
5720 }
5721
5722 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
5723 if (!CDF_IS_STATUS_SUCCESS(status)) {
5724 csr_free_scan_filter(pMac, pScanFilter);
5725 cdf_mem_free(pScanFilter);
5726 return status;
5727 }
5728
5729 if (pSession->NumBkidCandidate < nItems) {
5730 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
5731 while (pScanResult != NULL) {
5732 /* pMac->scan.NumBkidCandidate adds up here */
5733 csr_process_bss_desc_for_bkid_list(pMac,
5734 &pScanResult->BssDescriptor,
5735 (tDot11fBeaconIEs *)(pScanResult->pvIes));
5736 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
5737 }
5738 }
5739
5740 if (pSession->NumBkidCandidate) {
5741 *pNumItems = pSession->NumBkidCandidate;
5742 cdf_mem_copy(pBkidList, pSession->BkidCandidateInfo,
5743 pSession->NumBkidCandidate *
5744 sizeof(tBkidCandidateInfo));
5745 }
5746
5747 csr_scan_result_purge(pMac, hBSSList);
5748 csr_free_scan_filter(pMac, pScanFilter);
5749 cdf_mem_free(pScanFilter);
5750 return status;
5751}
5752#endif /* FEATURE_WLAN_WAPI */
5753
5754/**
5755 * csr_roam_copy_channellist() - Function to copy channel list
5756 * @mac_ctx: pointer to Global Mac structure
5757 * @profile: pointer to tCsrRoamProfile
5758 * @scan_cmd: pointer to tSmeCmd
5759 * @index: index for channellist
5760 *
5761 * Function copies channel list
5762 *
5763 * Return: none
5764 */
5765static void csr_roam_copy_channellist(tpAniSirGlobal mac_ctx,
5766 tCsrRoamProfile *profile,
5767 tSmeCmd *scan_cmd, uint8_t index)
5768{
5769 tCsrChannelInfo *channel_info =
5770 &scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo;
5771
5772 for (index = 0; index < profile->ChannelInfo.numOfChannels;
5773 index++) {
5774 if (!csr_roam_is_valid_channel(mac_ctx,
5775 profile->ChannelInfo.ChannelList[index])) {
5776 sms_log(mac_ctx, LOGW,
5777 FL("process a channel (%d) that is invalid"),
5778 profile->ChannelInfo.ChannelList[index]);
5779 continue;
5780 }
5781 channel_info->ChannelList[channel_info->numOfChannels] =
5782 profile->ChannelInfo.ChannelList[index];
5783 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels++;
5784 }
5785}
5786
5787/**
5788 * csr_scan_for_ssid() - Function usually used for BSSs that suppresses SSID
5789 * @mac_ctx: Pointer to Global Mac structure
5790 * @profile: pointer to tCsrRoamProfile
5791 * @roam_id: variable representing roam id
5792 * @notify: boolean variable
5793 *
5794 * Function is usually used for BSSs that suppresses SSID so the profile
5795 * shall have one and only one SSID.
5796 *
5797 * Return: Success - CDF_STATUS_SUCCESS, Failure - error number
5798 */
5799CDF_STATUS csr_scan_for_ssid(tpAniSirGlobal mac_ctx, uint32_t session_id,
5800 tCsrRoamProfile *profile, uint32_t roam_id,
5801 bool notify)
5802{
5803 CDF_STATUS status = CDF_STATUS_E_INVAL;
5804 tSmeCmd *scan_cmd = NULL;
5805 tCsrScanRequest *scan_req = NULL;
5806 uint8_t index = 0;
5807 uint32_t num_ssid = profile->SSIDs.numOfSSIDs;
5808 tpCsrNeighborRoamControlInfo neighbor_roaminfo =
5809 &mac_ctx->roam.neighborRoamInfo[session_id];
5810 tCsrSSIDs *ssids = NULL;
5811
5812 sms_log(mac_ctx, LOG2, FL("called"));
5813
5814 /* For WDS, we use the index 0. There must be at least one in there */
5815 if (CSR_IS_WDS_STA(profile) && num_ssid)
5816 num_ssid = 1;
5817
5818 if (!(mac_ctx->scan.fScanEnable) && (num_ssid != 1)) {
5819 sms_log(mac_ctx, LOGE,
5820 FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid"),
5821 mac_ctx->scan.fScanEnable, profile->SSIDs.numOfSSIDs);
5822 return status;
5823 }
5824
5825 scan_cmd = csr_get_command_buffer(mac_ctx);
5826
5827 if (!scan_cmd) {
5828 sms_log(mac_ctx, LOGE,
5829 FL("failed to allocate command buffer"));
5830 goto error;
5831 }
5832
5833 cdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0);
5834 scan_cmd->u.scanCmd.pToRoamProfile =
5835 cdf_mem_malloc(sizeof(tCsrRoamProfile));
5836
5837 if (NULL == scan_cmd->u.scanCmd.pToRoamProfile)
5838 status = CDF_STATUS_E_NOMEM;
5839 else
5840 status = csr_roam_copy_profile(mac_ctx,
5841 scan_cmd->u.scanCmd.pToRoamProfile,
5842 profile);
5843
5844 if (!CDF_IS_STATUS_SUCCESS(status))
5845 goto error;
5846
5847 scan_cmd->u.scanCmd.roamId = roam_id;
5848 scan_cmd->command = eSmeCommandScan;
5849 scan_cmd->sessionId = (uint8_t) session_id;
5850 scan_cmd->u.scanCmd.callback = NULL;
5851 scan_cmd->u.scanCmd.pContext = NULL;
5852 scan_cmd->u.scanCmd.reason = eCsrScanForSsid;
5853
5854 /* let it wrap around */
5855 wma_get_scan_id(&scan_cmd->u.scanCmd.scanID);
5856 cdf_mem_set(&scan_cmd->u.scanCmd.u.scanRequest,
5857 sizeof(tCsrScanRequest), 0);
5858 status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
5859 CDF_TIMER_TYPE_SW,
5860 csr_scan_active_list_timeout_handle, &scan_cmd);
5861 scan_req = &scan_cmd->u.scanCmd.u.scanRequest;
5862 scan_req->scanType = eSIR_ACTIVE_SCAN;
5863 scan_req->BSSType = profile->BSSType;
5864 scan_req->scan_id = scan_cmd->u.scanCmd.scanID;
5865 /*
5866 * To avoid 11b rate in probe request Set p2pSearch
5867 * flag as 1 for P2P Client Mode
5868 */
5869 if (CDF_P2P_CLIENT_MODE == profile->csrPersona)
5870 scan_req->p2pSearch = 1;
5871
5872 /* Allocate memory for IE field */
5873 if (profile->pAddIEScan) {
5874 scan_req->pIEField =
5875 cdf_mem_malloc(profile->nAddIEScanLength);
5876
5877 if (NULL == scan_req->pIEField)
5878 status = CDF_STATUS_E_NOMEM;
5879 else
5880 status = CDF_STATUS_SUCCESS;
5881
5882 cdf_mem_set(scan_req->pIEField,
5883 profile->nAddIEScanLength, 0);
5884
5885 if (CDF_IS_STATUS_SUCCESS(status)) {
5886 cdf_mem_copy(scan_req->pIEField,
5887 profile->pAddIEScan,
5888 profile->nAddIEScanLength);
5889 scan_req->uIEFieldLen = profile->nAddIEScanLength;
5890 } else {
5891 sms_log(mac_ctx, LOGE,
5892 "No memory for scanning IE fields");
5893 }
5894 } else
5895 scan_req->uIEFieldLen = 0;
5896
5897 /*
5898 * For one channel be good enpugh time to receive beacon
5899 * atleast
5900 */
5901 if (1 == profile->ChannelInfo.numOfChannels) {
5902 if (neighbor_roaminfo->handoffReqInfo.src ==
5903 FASTREASSOC) {
5904 scan_req->maxChnTime =
5905 MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC;
5906 scan_req->minChnTime =
5907 MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC;
5908 /* Reset this value */
5909 neighbor_roaminfo->handoffReqInfo.src = 0;
5910 } else {
5911 scan_req->maxChnTime =
5912 MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL;
5913 scan_req->minChnTime =
5914 MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL;
5915 }
5916 } else {
5917 scan_req->maxChnTime =
5918 mac_ctx->roam.configParam.nActiveMaxChnTime;
5919 scan_req->minChnTime =
5920 mac_ctx->roam.configParam.nActiveMinChnTime;
5921 }
5922
5923 if (profile->BSSIDs.numOfBSSIDs == 1)
5924 cdf_copy_macaddr(&scan_req->bssid,
5925 profile->BSSIDs.bssid);
5926 else
5927 cdf_set_macaddr_broadcast(&scan_req->bssid);
5928
5929 if (profile->ChannelInfo.numOfChannels) {
5930 scan_req->ChannelInfo.ChannelList =
5931 cdf_mem_malloc(sizeof(*scan_req->ChannelInfo.ChannelList) *
5932 profile->ChannelInfo.numOfChannels);
5933
5934 if (NULL == scan_req->ChannelInfo.ChannelList)
5935 status = CDF_STATUS_E_NOMEM;
5936 else
5937 status = CDF_STATUS_SUCCESS;
5938
5939 scan_req->ChannelInfo.numOfChannels = 0;
5940
5941 if (CDF_IS_STATUS_SUCCESS(status)) {
5942 csr_roam_is_channel_valid(mac_ctx,
5943 profile->ChannelInfo.ChannelList[0]);
5944 csr_roam_copy_channellist(mac_ctx,
5945 profile, scan_cmd, index);
5946 } else {
5947 goto error;
5948 }
5949 } else {
5950 scan_req->ChannelInfo.numOfChannels = 0;
5951 }
5952
5953 if (profile->SSIDs.numOfSSIDs) {
5954 scan_req->SSIDs.SSIDList =
5955 cdf_mem_malloc(profile->SSIDs.numOfSSIDs *
5956 sizeof(tCsrSSIDInfo));
5957
5958 if (NULL == scan_req->SSIDs.SSIDList)
5959 status = CDF_STATUS_E_NOMEM;
5960 else
5961 status = CDF_STATUS_SUCCESS;
5962
5963 if (!CDF_IS_STATUS_SUCCESS(status))
5964 goto error;
5965
5966 ssids = &scan_req->SSIDs;
5967 ssids->numOfSSIDs = 1;
5968
5969 cdf_mem_copy(scan_req->SSIDs.SSIDList,
5970 profile->SSIDs.SSIDList,
5971 sizeof(tCsrSSIDInfo));
5972 }
5973
5974 /* Start process the command */
5975 status = csr_queue_sme_command(mac_ctx, scan_cmd, false);
5976error:
5977 if (!CDF_IS_STATUS_SUCCESS(status)) {
5978 sms_log(mac_ctx, LOGE,
5979 FL(" failed to iniate scan with status = %d"), status);
5980 if (scan_cmd)
5981 csr_release_command_scan(mac_ctx, scan_cmd);
5982 if (notify)
5983 csr_roam_call_callback(mac_ctx, session_id, NULL,
5984 roam_id, eCSR_ROAM_FAILED,
5985 eCSR_ROAM_RESULT_FAILURE);
5986 }
5987 return status;
5988}
5989
5990void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList,
5991 uint8_t NumChannels)
5992{
5993 uint32_t dataLen = sizeof(uint8_t) * NumChannels;
5994 CDF_STATUS status;
5995
5996 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
5997 "%s: dump valid channel list(NumChannels(%d))",
5998 __func__, NumChannels);
5999 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
6000 pChannelList, NumChannels);
6001 cfg_set_str(pMac, WNI_CFG_VALID_CHANNEL_LIST, pChannelList,
6002 dataLen);
6003
6004 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
6005 "Scan offload is enabled, update default chan list");
6006 /*
6007 * disable fcc constraint since new country code
6008 * is being set
6009 */
6010 pMac->scan.fcc_constraint = false;
6011 status = csr_update_channel_list(pMac);
6012 if (CDF_STATUS_SUCCESS != status) {
6013 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6014 "failed to update the supported channel list");
6015 }
6016 return;
6017}
6018
6019/*
6020 * The Tx power limits are saved in the cfg for future usage.
6021 */
6022void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList,
6023 uint32_t cfgId)
6024{
6025 tListElem *pEntry;
6026 uint32_t cbLen = 0, dataLen, tmp_len;
6027 tCsrChannelPowerInfo *ch_set;
6028 uint32_t idx;
6029 tSirMacChanInfo *ch_pwr_set;
6030 uint8_t *pBuf = NULL;
6031
6032 /* allocate maximum space for all channels */
6033 dataLen = WNI_CFG_VALID_CHANNEL_LIST_LEN * sizeof(tSirMacChanInfo);
6034 pBuf = cdf_mem_malloc(dataLen);
6035 if (pBuf == NULL)
6036 return;
6037
6038 cdf_mem_set(pBuf, dataLen, 0);
6039 ch_pwr_set = (tSirMacChanInfo *) (pBuf);
6040 pEntry = csr_ll_peek_head(pList, LL_ACCESS_LOCK);
6041 /*
6042 * write the tuples (startChan, numChan, txPower) for each channel found
6043 * in the channel power list.
6044 */
6045 while (pEntry) {
6046 ch_set = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link);
6047 if (1 != ch_set->interChannelOffset) {
6048 /*
6049 * we keep the 5G channel sets internally with an
6050 * interchannel offset of 4. Expand these to the right
6051 * format. (inter channel offset of 1 is the only option
6052 * for the triplets that 11d advertises.
6053 */
6054 tmp_len = cbLen + (ch_set->numChannels *
6055 sizeof(tSirMacChanInfo));
6056 if (tmp_len >= dataLen) {
6057 /*
6058 * expanding this entry will overflow our
6059 * allocation
6060 */
6061 sms_log(pMac, LOGE,
6062 FL("Buffer overflow, start %d, num %d, offset %d"),
6063 ch_set->firstChannel,
6064 ch_set->numChannels,
6065 ch_set->interChannelOffset);
6066 break;
6067 }
6068
6069 for (idx = 0; idx < ch_set->numChannels; idx++) {
6070 ch_pwr_set->firstChanNum = (tSirMacChanNum)
6071 (ch_set->firstChannel + (idx *
6072 ch_set->interChannelOffset));
6073 sms_log(pMac, LOG3,
6074 FL("Setting Channel Number %d"),
6075 ch_pwr_set->firstChanNum);
6076 ch_pwr_set->numChannels = 1;
6077 ch_pwr_set->maxTxPower =
6078 CDF_MIN(ch_set->txPower,
6079 pMac->roam.configParam.nTxPowerCap);
6080 sms_log(pMac, LOG3,
6081 FL("Setting Max Transmit Power %d"),
6082 ch_pwr_set->maxTxPower);
6083 cbLen += sizeof(tSirMacChanInfo);
6084 ch_pwr_set++;
6085 }
6086 } else {
6087 if (cbLen >= dataLen) {
6088 /* this entry will overflow our allocation */
6089 sms_log(pMac, LOGE,
6090 FL("Buffer overflow, start %d, num %d, offset %d"),
6091 ch_set->firstChannel,
6092 ch_set->numChannels,
6093 ch_set->interChannelOffset);
6094 break;
6095 }
6096 ch_pwr_set->firstChanNum = ch_set->firstChannel;
6097 sms_log(pMac, LOG3, FL("Setting Channel Number %d"),
6098 ch_pwr_set->firstChanNum);
6099 ch_pwr_set->numChannels = ch_set->numChannels;
6100 ch_pwr_set->maxTxPower = CDF_MIN(ch_set->txPower,
6101 pMac->roam.configParam.nTxPowerCap);
6102 sms_log(pMac, LOG3,
6103 FL("Setting Max Tx Power %d, nTxPower %d"),
6104 ch_pwr_set->maxTxPower,
6105 pMac->roam.configParam.nTxPowerCap);
6106 cbLen += sizeof(tSirMacChanInfo);
6107 ch_pwr_set++;
6108 }
6109 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_LOCK);
6110 }
6111 if (cbLen)
6112 cfg_set_str(pMac, cfgId, (uint8_t *) pBuf, cbLen);
6113
6114 cdf_mem_free(pBuf);
6115}
6116
6117void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode)
6118{
6119 uint8_t cc[WNI_CFG_COUNTRY_CODE_LEN];
6120 /* v_REGDOMAIN_t DomainId */
6121
6122 sms_log(pMac, LOG3, FL("Setting Country Code in Cfg %s"), countryCode);
6123 cdf_mem_copy(cc, countryCode, WNI_CFG_COUNTRY_CODE_LEN);
6124
6125 /*
6126 * don't program the bogus country codes that we created for Korea in the
6127 * MAC. if we see the bogus country codes, program the MAC with the right
6128 * country code.
6129 */
6130 if (('K' == countryCode[0] && '1' == countryCode[1]) ||
6131 ('K' == countryCode[0] && '2' == countryCode[1]) ||
6132 ('K' == countryCode[0] && '3' == countryCode[1]) ||
6133 ('K' == countryCode[0] && '4' == countryCode[1])) {
6134 /*
6135 * replace the alternate Korea country codes, 'K1', 'K2', ..
6136 * with 'KR' for Korea
6137 */
6138 cc[1] = 'R';
6139 }
6140 cfg_set_str(pMac, WNI_CFG_COUNTRY_CODE, cc, WNI_CFG_COUNTRY_CODE_LEN);
6141
6142 /*
6143 * Need to let HALPHY know about the current domain so it can apply some
6144 * domain-specific settings (TX filter...)
6145 */
6146 /*
6147 if(CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(
6148 pMac, cc, &DomainId))) {
6149 halPhySetRegDomain(pMac, DomainId);
6150 } */
6151}
6152
6153CDF_STATUS csr_get_country_code(tpAniSirGlobal pMac, uint8_t *pBuf,
6154 uint8_t *pbLen)
6155{
6156 CDF_STATUS status = CDF_STATUS_E_INVAL;
6157 uint32_t len;
6158
6159 if (pBuf && pbLen && (*pbLen >= WNI_CFG_COUNTRY_CODE_LEN)) {
6160 len = *pbLen;
6161 status = wlan_cfg_get_str(pMac, WNI_CFG_COUNTRY_CODE, pBuf, &len);
6162 if (CDF_IS_STATUS_SUCCESS(status)) {
6163 *pbLen = (uint8_t) len;
6164 }
6165 }
6166
6167 return status;
6168}
6169
6170void csr_set_cfg_scan_control_list(tpAniSirGlobal pMac, uint8_t *countryCode,
6171 tCsrChannel *pChannelList)
6172{
6173 uint8_t i, j;
6174 bool found = false;
6175 uint8_t *pControlList = NULL;
6176 uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
6177
6178 pControlList = cdf_mem_malloc(WNI_CFG_SCAN_CONTROL_LIST_LEN);
6179 if (pControlList != NULL) {
6180 cdf_mem_set((void *)pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN,
6181 0);
6182 if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_str(pMac,
6183 WNI_CFG_SCAN_CONTROL_LIST,
6184 pControlList, &len))) {
6185 for (i = 0; i < pChannelList->numChannels; i++) {
6186 for (j = 0; j < len; j += 2) {
6187 if (pControlList[j] ==
6188 pChannelList->channelList[i]) {
6189 found = true;
6190 break;
6191 }
6192 }
6193
6194 if (found) {
6195 /* insert a pair(channel#, flag) */
6196 pControlList[j + 1] =
6197 csr_get_scan_type(pMac,
6198 pControlList[j]);
6199 found = false; /* reset the flag */
6200 }
6201
6202 }
6203 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
6204 "%s: dump scan control list", __func__);
6205 CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME,
6206 CDF_TRACE_LEVEL_INFO, pControlList,
6207 len);
6208
6209 cfg_set_str(pMac, WNI_CFG_SCAN_CONTROL_LIST,
6210 pControlList, len);
6211 } /* Successfully getting scan control list */
6212 cdf_mem_free(pControlList);
6213 } /* AllocateMemory */
6214}
6215
6216CDF_STATUS csr_scan_abort_mac_scan(tpAniSirGlobal pMac, uint8_t sessionId,
6217 eCsrAbortReason reason)
6218{
6219 CDF_STATUS status = CDF_STATUS_SUCCESS;
6220
6221 pMac->scan.fDropScanCmd = true;
6222 csr_remove_cmd_with_session_id_from_pending_list(pMac,
6223 sessionId, &pMac->sme.smeScanCmdPendingList,
6224 eSmeCommandScan);
6225 pMac->scan.fDropScanCmd = false;
6226 csr_abort_scan_from_active_list(pMac,
6227 &pMac->sme.smeScanCmdActiveList, sessionId,
6228 eSmeCommandScan, reason);
6229
6230 return status;
6231}
6232
6233void csr_remove_cmd_with_session_id_from_pending_list(tpAniSirGlobal pMac,
6234 uint8_t sessionId,
6235 tDblLinkList *pList,
6236 eSmeCommandType commandType)
6237{
6238 tDblLinkList localList;
6239 tListElem *pEntry;
6240 tSmeCmd *pCommand;
6241 tListElem *pEntryToRemove;
6242
6243 cdf_mem_zero(&localList, sizeof(tDblLinkList));
6244 if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
6245 sms_log(pMac, LOGE, FL("failed to open list"));
6246 return;
6247 }
6248
6249 csr_ll_lock(pList);
6250 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
6251 if (pEntry) {
6252 /*
6253 * Have to make sure we don't loop back to the head of the list,
6254 * which will happen if the entry is NOT on the list
6255 */
6256 while (pEntry) {
6257 pEntryToRemove = pEntry;
6258 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
6259 pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
6260
6261 if (!((pCommand->command == commandType) &&
6262 (pCommand->sessionId == sessionId)))
6263 continue;
6264 /* Remove that entry only */
6265 if (csr_ll_remove_entry(pList, pEntryToRemove,
6266 LL_ACCESS_NOLOCK)) {
6267 csr_ll_insert_tail(&localList, pEntryToRemove,
6268 LL_ACCESS_NOLOCK);
6269 }
6270 }
6271 }
6272 csr_ll_unlock(pList);
6273
6274 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
6275 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
6276 sms_log(pMac, LOG1, FL("Sending abort for scan command ID %d"),
6277 pCommand->u.scanCmd.scanID);
6278 csr_abort_command(pMac, pCommand, false);
6279 }
6280
6281 csr_ll_close(&localList);
6282}
6283
6284void csr_remove_cmd_from_pending_list(tpAniSirGlobal pMac,
6285 tDblLinkList *pList,
6286 eSmeCommandType commandType)
6287{
6288 tDblLinkList localList;
6289 tListElem *pEntry;
6290 tSmeCmd *pCommand;
6291 tListElem *pEntryToRemove;
6292
6293 cdf_mem_zero(&localList, sizeof(tDblLinkList));
6294 if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
6295 sms_log(pMac, LOGE, FL(" failed to open list"));
6296 return;
6297 }
6298
6299 csr_ll_lock(pList);
6300 if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) {
6301 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
6302 /*
6303 * Have to make sure we don't loop back to the head of the list,
6304 * which will happen if the entry is NOT on the list...
6305 */
6306 while (pEntry) {
6307 pEntryToRemove = pEntry;
6308 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
6309 pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
6310 /* Remove that entry only that matches cmd type */
6311 if (pCommand->command == commandType &&
6312 csr_ll_remove_entry(pList, pEntryToRemove,
6313 LL_ACCESS_NOLOCK)) {
6314 csr_ll_insert_tail(&localList, pEntryToRemove,
6315 LL_ACCESS_NOLOCK);
6316 }
6317 }
6318 }
6319 csr_ll_unlock(pList);
6320
6321 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
6322 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
6323 csr_abort_command(pMac, pCommand, false);
6324 }
6325 csr_ll_close(&localList);
6326
6327}
6328
6329CDF_STATUS csr_scan_abort_scan_for_ssid(tpAniSirGlobal pMac, uint32_t sessionId)
6330{
6331 CDF_STATUS status = CDF_STATUS_SUCCESS;
6332
6333 pMac->scan.fDropScanCmd = true;
6334 csr_remove_scan_for_ssid_from_pending_list(pMac,
6335 &pMac->sme.smeScanCmdPendingList, sessionId);
6336 pMac->scan.fDropScanCmd = false;
6337 csr_abort_scan_from_active_list(pMac, &pMac->sme.smeScanCmdActiveList,
6338 sessionId, eSmeCommandScan, eCSR_SCAN_ABORT_SSID_ONLY);
6339 return status;
6340}
6341
6342void csr_remove_scan_for_ssid_from_pending_list(tpAniSirGlobal pMac,
6343 tDblLinkList *pList,
6344 uint32_t sessionId)
6345{
6346 tDblLinkList localList;
6347 tListElem *pEntry;
6348 tSmeCmd *pCommand;
6349 tListElem *pEntryToRemove;
6350
6351 cdf_mem_zero(&localList, sizeof(tDblLinkList));
6352 if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
6353 sms_log(pMac, LOGE, FL(" failed to open list"));
6354 return;
6355 }
6356 csr_ll_lock(pList);
6357 if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) {
6358 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
6359 /*
6360 * Have to make sure we don't loop back to the head of the list,
6361 * which will happen if the entry is NOT on the list...
6362 */
6363 while (pEntry) {
6364 pEntryToRemove = pEntry;
6365 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
6366 pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
6367
6368 if (!((eSmeCommandScan == pCommand->command) &&
6369 (sessionId == pCommand->sessionId)))
6370 continue;
6371 if (eCsrScanForSsid != pCommand->u.scanCmd.reason)
6372 continue;
6373 /* Remove that entry only */
6374 if (csr_ll_remove_entry(pList, pEntryToRemove,
6375 LL_ACCESS_NOLOCK)) {
6376 csr_ll_insert_tail(&localList, pEntryToRemove,
6377 LL_ACCESS_NOLOCK);
6378 }
6379 }
6380 }
6381 csr_ll_unlock(pList);
6382 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
6383 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
6384 csr_abort_command(pMac, pCommand, false);
6385 }
6386 csr_ll_close(&localList);
6387}
6388
6389
6390/**
6391 * csr_send_scan_abort() - Sends scan abort command to firmware
6392 * @mac_ctx: Pointer to Global Mac structure
6393 * @session_id: CSR session identification
6394 * @scan_id: scan identifier
6395 *
6396 * .Sends scan abort command to firmware
6397 *
6398 * Return: None
6399 */
6400static void csr_send_scan_abort(tpAniSirGlobal mac_ctx,
6401 uint32_t session_id, uint32_t scan_id)
6402{
6403 tSirSmeScanAbortReq *msg;
6404 uint16_t msg_len;
6405 CDF_STATUS status = CDF_STATUS_SUCCESS;
6406
6407 msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq));
6408 msg = cdf_mem_malloc(msg_len);
6409 if (NULL == msg) {
6410 sms_log(mac_ctx, LOGE,
6411 FL("Failed to alloc memory for SmeScanAbortReq"));
6412 return;
6413 }
6414 cdf_mem_zero((void *)msg, msg_len);
6415 msg->type = eWNI_SME_SCAN_ABORT_IND;
6416 msg->msgLen = msg_len;
6417 msg->sessionId = session_id;
6418 msg->scan_id = scan_id;
6419 sms_log(mac_ctx, LOG2,
6420 FL("Abort scan sent to Firmware scan_id %d session %d"),
6421 scan_id, session_id);
6422 status = cds_send_mb_message_to_mac(msg);
6423 if (!CDF_IS_STATUS_SUCCESS(status)) {
6424 cdf_mem_free(msg);
6425 sms_log(mac_ctx, LOGE,
6426 FL("Failed to send abort scan.scan_id %d session %d"),
6427 scan_id, session_id);
6428 }
6429 return;
6430}
6431
6432/**
6433 * csr_abort_scan_from_active_list() - Remove Scan command from active list
6434 * @mac_ctx: Pointer to Global Mac structure
6435 * @list: pointer to scan active list
6436 * @session_id: CSR session identification
6437 * @scan_cmd_type: scan command type
6438 * @abort_reason: abort reason
6439 *
6440 * .Remove Scan command from active scan list
6441 *
6442 * Return: Success - CDF_STATUS_SUCCESS, Failure - error number
6443 */
6444CDF_STATUS csr_abort_scan_from_active_list(tpAniSirGlobal mac_ctx,
6445 tDblLinkList *list, uint32_t session_id,
6446 eSmeCommandType scan_cmd_type, eCsrAbortReason abort_reason)
6447{
6448 tListElem *entry;
6449 tSmeCmd *cmd;
6450 tListElem *entry_remove;
6451 CDF_STATUS status = CDF_STATUS_SUCCESS;
6452
6453 csr_ll_lock(list);
6454 if (!csr_ll_is_list_empty(list, LL_ACCESS_NOLOCK)) {
6455 entry = csr_ll_peek_head(list, LL_ACCESS_NOLOCK);
6456 while (entry) {
6457 entry_remove = entry;
6458 entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
6459 cmd = GET_BASE_ADDR(entry_remove, tSmeCmd, Link);
6460
6461 /* Skip if command and session id not matched */
6462 if (!((scan_cmd_type == cmd->command) &&
6463 (session_id == cmd->sessionId)))
6464 continue;
6465 /*skip if abort reason is for SSID*/
6466 if ((abort_reason == eCSR_SCAN_ABORT_SSID_ONLY) &&
6467 (eCsrScanForSsid != cmd->u.scanCmd.reason))
6468 continue;
6469 if (abort_reason == eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE)
6470 cmd->u.scanCmd.abortScanDueToBandChange =
6471 true;
6472 csr_send_scan_abort(mac_ctx, cmd->sessionId,
6473 cmd->u.scanCmd.scanID);
6474 }
6475 }
6476 csr_ll_unlock(list);
6477
6478 return status;
6479}
6480
6481
6482CDF_STATUS csr_scan_abort_mac_scan_not_for_connect(tpAniSirGlobal pMac,
6483 uint8_t sessionId)
6484{
6485 CDF_STATUS status = CDF_STATUS_SUCCESS;
6486 if (!csr_is_scan_for_roam_command_active(pMac)) {
6487 /*
6488 * Only abort the scan if it is not used for other roam/connect
6489 * purpose
6490 */
6491 status = csr_scan_abort_mac_scan(pMac, sessionId,
6492 eCSR_SCAN_ABORT_DEFAULT);
6493 }
6494 return status;
6495}
6496bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel)
6497{
6498 bool fValid = false;
6499 uint32_t idx_valid_ch;
6500 uint32_t len = pMac->roam.numValidChannels;
6501
6502 for (idx_valid_ch = 0; (idx_valid_ch < len); idx_valid_ch++) {
6503 if (channel == pMac->roam.validChannelList[idx_valid_ch]) {
6504 fValid = true;
6505 break;
6506 }
6507 }
6508 return fValid;
6509}
6510
6511#ifdef FEATURE_WLAN_SCAN_PNO
6512CDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac,
6513 tSirPrefNetworkFoundInd *
6514 pPrefNetworkFoundInd)
6515{
6516 uint32_t uLen = 0;
6517 tpSirProbeRespBeacon parsed_frm;
6518 tCsrScanResult *pScanResult = NULL;
6519 tSirBssDescription *pBssDescr = NULL;
6520 bool fDupBss;
6521 tDot11fBeaconIEs *local_ie = NULL;
6522 tAniSSID tmpSsid;
6523 v_TIME_t timer = 0;
6524 CDF_STATUS status;
6525
6526 tpSirMacMgmtHdr macHeader =
6527 (tpSirMacMgmtHdr) pPrefNetworkFoundInd->data;
6528 parsed_frm =
6529 (tpSirProbeRespBeacon) cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
6530
6531 if (NULL == parsed_frm) {
6532 sms_log(pMac, LOGE, FL("fail to allocate memory for frame"));
6533 return CDF_STATUS_E_NOMEM;
6534 }
6535 if (pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A) {
6536 sms_log(pMac, LOGE,
6537 FL("Incorrect len(%d)"),
6538 pPrefNetworkFoundInd->frameLength);
6539 cdf_mem_free(parsed_frm);
6540 return CDF_STATUS_E_FAILURE;
6541 }
6542 if (sir_convert_probe_frame2_struct(pMac,
6543 &pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A],
6544 pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A,
6545 parsed_frm) != eSIR_SUCCESS
6546 || !parsed_frm->ssidPresent) {
6547 sms_log(pMac, LOGE, FL("Parse error ProbeResponse, length=%d"),
6548 pPrefNetworkFoundInd->frameLength);
6549 cdf_mem_free(parsed_frm);
6550 return CDF_STATUS_E_FAILURE;
6551 }
6552 /* 24 byte MAC header and 12 byte to ssid IE */
6553 if (pPrefNetworkFoundInd->frameLength >
6554 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) {
6555 uLen = pPrefNetworkFoundInd->frameLength -
6556 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
6557 }
6558 pScanResult = cdf_mem_malloc(sizeof(tCsrScanResult) + uLen);
6559 if (NULL == pScanResult) {
6560 sms_log(pMac, LOGE, FL("fail to allocate memory for frame"));
6561 cdf_mem_free(parsed_frm);
6562 return CDF_STATUS_E_NOMEM;
6563 }
6564 cdf_mem_set(pScanResult, sizeof(tCsrScanResult) + uLen, 0);
6565 pBssDescr = &pScanResult->Result.BssDescriptor;
6566 /*
6567 * Length of BSS desription is without length of length itself and
6568 * length of pointer that holds the next BSS description
6569 */
6570 pBssDescr->length = (uint16_t) (sizeof(tSirBssDescription) -
6571 sizeof(uint16_t) - sizeof(uint32_t) + uLen);
6572 if (parsed_frm->dsParamsPresent)
6573 pBssDescr->channelId = parsed_frm->channelNumber;
6574 else if (parsed_frm->HTInfo.present)
6575 pBssDescr->channelId = parsed_frm->HTInfo.primaryChannel;
6576 else
6577 pBssDescr->channelId = parsed_frm->channelNumber;
6578
6579 if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) {
6580 int i;
6581 /* 11b or 11g packet */
6582 /* 11g iff extended Rate IE is present or */
6583 /* if there is an A rate in suppRate IE */
6584 for (i = 0; i < parsed_frm->supportedRates.numRates; i++) {
6585 if (sirIsArate(parsed_frm->supportedRates.rate[i]
6586 & 0x7f)) {
6587 pBssDescr->nwType = eSIR_11G_NW_TYPE;
6588 break;
6589 }
6590 }
6591 if (parsed_frm->extendedRatesPresent)
6592 pBssDescr->nwType = eSIR_11G_NW_TYPE;
6593 } else {
6594 /* 11a packet */
6595 pBssDescr->nwType = eSIR_11A_NW_TYPE;
6596 }
6597 pBssDescr->sinr = 0;
6598 pBssDescr->rssi = -1 * pPrefNetworkFoundInd->rssi;
6599 pBssDescr->beaconInterval = parsed_frm->beaconInterval;
6600 if (!pBssDescr->beaconInterval) {
6601 sms_log(pMac, LOGW, FL("Bcn Interval is Zero , default to 100"
6602 MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pBssDescr->bssId));
6603 pBssDescr->beaconInterval = 100;
6604 }
6605 pBssDescr->timeStamp[0] = parsed_frm->timeStamp[0];
6606 pBssDescr->timeStamp[1] = parsed_frm->timeStamp[1];
6607 pBssDescr->capabilityInfo = *((uint16_t *)&parsed_frm->capabilityInfo);
6608 cdf_mem_copy((uint8_t *) &pBssDescr->bssId,
6609 (uint8_t *) macHeader->bssId, sizeof(tSirMacAddr));
6610 pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks();
6611 sms_log(pMac, LOG2, FL("Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = %d"),
6612 MAC_ADDR_ARRAY(pBssDescr->bssId), pBssDescr->channelId,
6613 pBssDescr->rssi);
6614 /* IEs */
6615 if (uLen) {
6616 cdf_mem_copy(&pBssDescr->ieFields,
6617 pPrefNetworkFoundInd->data + (SIR_MAC_HDR_LEN_3A +
6618 SIR_MAC_B_PR_SSID_OFFSET), uLen);
6619 }
6620 local_ie = (tDot11fBeaconIEs *) (pScanResult->Result.pvIes);
6621 status = csr_get_parsed_bss_description_ies(pMac,
6622 &pScanResult->Result.BssDescriptor, &local_ie);
6623 if (!(local_ie || CDF_IS_STATUS_SUCCESS(status))) {
6624 sms_log(pMac, LOGE, FL("Cannot parse IEs"));
6625 csr_free_scan_result_entry(pMac, pScanResult);
6626 cdf_mem_free(parsed_frm);
6627 return CDF_STATUS_E_RESOURCES;
6628 }
6629
6630 fDupBss = csr_remove_dup_bss_description(pMac,
6631 &pScanResult->Result.BssDescriptor,
6632 local_ie, &tmpSsid, &timer, false);
6633 /* Check whether we have reach out limit */
6634 if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) {
6635 /* Limit reach */
6636 sms_log(pMac, LOGE, FL("BSS limit reached"));
6637 /* Free the resources */
6638 if ((pScanResult->Result.pvIes == NULL) && local_ie)
6639 cdf_mem_free(local_ie);
6640 csr_free_scan_result_entry(pMac, pScanResult);
6641 cdf_mem_free(parsed_frm);
6642 return CDF_STATUS_E_RESOURCES;
6643 }
6644 /* Add to scan cache */
6645 csr_scan_add_result(pMac, pScanResult, local_ie,
6646 pPrefNetworkFoundInd->sessionId);
6647
6648 if ((pScanResult->Result.pvIes == NULL) && local_ie)
6649 cdf_mem_free(local_ie);
6650 cdf_mem_free(parsed_frm);
6651 return CDF_STATUS_SUCCESS;
6652}
6653#endif /* FEATURE_WLAN_SCAN_PNO */
6654
6655#ifdef FEATURE_WLAN_LFR
6656void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId)
6657{
6658 tListElem *pEntry = NULL;
6659 tCsrScanResult *pBssDesc = NULL;
6660 tDot11fBeaconIEs *pIes = NULL;
6661 tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
6662 &pMac->roam.neighborRoamInfo[sessionId];
6663
6664 if (0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) {
6665 /*
6666 * Ini file contains neighbor scan channel list, hence NO need
6667 * to build occupied channel list"
6668 */
6669 sms_log(pMac, LOG1, FL("Ini contains neighbor scan ch list"));
6670 return;
6671 }
6672
6673 if (!csr_neighbor_roam_is_new_connected_profile(pMac, sessionId)) {
6674 /*
6675 * Do not flush occupied list since current roam profile matches
6676 * previous
6677 */
6678 sms_log(pMac, LOG2, FL("Current roam profile matches prev"));
6679 return;
6680 }
6681
6682 /* Empty occupied channels here */
6683 pMac->scan.occupiedChannels[sessionId].numChannels = 0;
6684
6685 csr_ll_lock(&pMac->scan.scanResultList);
6686 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
6687 while (pEntry) {
6688 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
6689 pIes = (tDot11fBeaconIEs *) (pBssDesc->Result.pvIes);
6690 /* At this time, pBssDescription->Result.pvIes may be NULL */
6691 if (!pIes && !CDF_IS_STATUS_SUCCESS(
6692 csr_get_parsed_bss_description_ies(pMac,
6693 &pBssDesc->Result.BssDescriptor, &pIes)))
6694 continue;
6695 csr_scan_add_to_occupied_channels(pMac, pBssDesc, sessionId,
6696 &pMac->scan.occupiedChannels[sessionId], pIes);
6697 /*
6698 * Free the memory allocated for pIes in
6699 * csr_get_parsed_bss_description_ies
6700 */
6701 if ((pBssDesc->Result.pvIes == NULL) && pIes)
6702 cdf_mem_free(pIes);
6703 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
6704 LL_ACCESS_NOLOCK);
6705 } /* while */
6706 csr_ll_unlock(&pMac->scan.scanResultList);
6707}
6708#endif
6709
6710CDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac,
6711 uint32_t sessionId,
6712 struct cdf_mac_addr bssid,
6713 uint8_t channel)
6714{
6715 CDF_STATUS status = CDF_STATUS_SUCCESS;
6716 tDot11fBeaconIEs *pNewIes = NULL;
6717 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
6718 tSirBssDescription *pNewBssDescriptor = NULL;
6719 uint32_t size = 0;
6720
6721 if (NULL == pSession) {
6722 status = CDF_STATUS_E_FAILURE;
6723 return status;
6724 }
6725 sms_log(pMac, LOG2, FL("Current bssid::"MAC_ADDRESS_STR),
6726 MAC_ADDR_ARRAY(pSession->pConnectBssDesc->bssId));
6727 sms_log(pMac, LOG2, FL("My bssid::"MAC_ADDRESS_STR" channel %d"),
6728 MAC_ADDR_ARRAY(bssid.bytes), channel);
6729
6730 if (!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(
6731 pMac, pSession->pConnectBssDesc,
6732 &pNewIes))) {
6733 sms_log(pMac, LOGE, FL("Failed to parse IEs"));
6734 status = CDF_STATUS_E_FAILURE;
6735 goto free_mem;
6736 }
6737 size = pSession->pConnectBssDesc->length +
6738 sizeof(pSession->pConnectBssDesc->length);
6739 if (!size) {
6740 sms_log(pMac, LOGE, FL("length of bss descriptor is 0"));
6741 status = CDF_STATUS_E_FAILURE;
6742 goto free_mem;
6743 }
6744 pNewBssDescriptor = cdf_mem_malloc(size);
6745 if (NULL == pNewBssDescriptor) {
6746 sms_log(pMac, LOGE, FL("memory allocation failed"));
6747 status = CDF_STATUS_E_FAILURE;
6748 goto free_mem;
6749 }
6750 cdf_mem_copy(pNewBssDescriptor, pSession->pConnectBssDesc, size);
6751 /* change the BSSID & channel as passed */
6752 cdf_mem_copy(pNewBssDescriptor->bssId, bssid.bytes,
6753 sizeof(tSirMacAddr));
6754 pNewBssDescriptor->channelId = channel;
6755 if (NULL == csr_scan_append_bss_description(pMac, pNewBssDescriptor,
6756 pNewIes, true, sessionId)) {
6757 sms_log(pMac, LOGE,
6758 FL("csr_scan_append_bss_description failed"));
6759 status = CDF_STATUS_E_FAILURE;
6760 goto free_mem;
6761 }
6762 sms_log(pMac, LOGE, FL("entry successfully added in scan cache"));
6763
6764free_mem:
6765 if (pNewIes) {
6766 cdf_mem_free(pNewIes);
6767 }
6768 if (pNewBssDescriptor) {
6769 cdf_mem_free(pNewBssDescriptor);
6770 }
6771 return status;
6772}
6773
6774#ifdef FEATURE_WLAN_ESE
6775/* Update the TSF with the difference in system time */
6776void update_cckmtsf(uint32_t *timeStamp0, uint32_t *timeStamp1,
6777 uint32_t *incr)
6778{
6779 uint64_t timeStamp64 = ((uint64_t) *timeStamp1 << 32) | (*timeStamp0);
6780 timeStamp64 = (uint64_t) (timeStamp64 + (uint64_t) *incr);
6781 *timeStamp0 = (uint32_t) (timeStamp64 & 0xffffffff);
6782 *timeStamp1 = (uint32_t) ((timeStamp64 >> 32) & 0xffffffff);
6783}
6784#endif
6785
6786/**
6787 * csr_scan_save_roam_offload_ap_to_scan_cache
6788 * This function parses the received beacon/probe response
6789 * from the firmware as part of the roam synch indication.
6790 * The beacon or the probe response is parsed and is also
6791 * saved into the scan cache
6792 *
6793 * @param pMac Pointer to Global Mac
6794 * @param roam_sync_ind_ptr Roam Synch Indication from
6795 * firmware which also contains the beacon/probe
6796 * response
6797 * @return Status
6798 */
6799#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6800CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac,
6801 roam_offload_synch_ind *roam_sync_ind_ptr)
6802{
6803 uint32_t length = 0;
6804 bool dup_bss;
6805 tDot11fBeaconIEs *ies_local_ptr = NULL;
6806 tAniSSID tmpSsid;
6807 v_TIME_t timer = 0;
6808 tCsrScanResult *scan_res_ptr = NULL;
6809 uint8_t session_id = roam_sync_ind_ptr->roamedVdevId;
6810
6811 length = roam_sync_ind_ptr->beaconProbeRespLength -
6812 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
6813 scan_res_ptr = cdf_mem_malloc(sizeof(tCsrScanResult) + length);
6814 if (scan_res_ptr == NULL) {
6815 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6816 " fail to allocate memory for frame");
6817 return CDF_STATUS_E_NOMEM;
6818 }
6819
6820 cdf_mem_zero(scan_res_ptr, sizeof(tCsrScanResult) + length);
6821 cdf_mem_copy(&scan_res_ptr->Result.BssDescriptor,
6822 roam_sync_ind_ptr->bss_desc_ptr,
6823 (sizeof(tSirBssDescription) + length));
6824 ies_local_ptr = (tDot11fBeaconIEs *)(scan_res_ptr->Result.pvIes);
6825 if (!ies_local_ptr &&
6826 (!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(
6827 pMac, &scan_res_ptr->Result.
6828 BssDescriptor,
6829 &ies_local_ptr)))) {
6830 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6831 "%s:Cannot Parse IEs", __func__);
6832 csr_free_scan_result_entry(pMac, scan_res_ptr);
6833 return CDF_STATUS_E_RESOURCES;
6834 }
6835
6836 dup_bss = csr_remove_dup_bss_description(pMac,
6837 &scan_res_ptr->Result.BssDescriptor,
6838 ies_local_ptr, &tmpSsid, &timer, true);
6839 if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) {
6840 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6841 "%s:BSS Limit Exceed", __func__);
6842 if ((scan_res_ptr->Result.pvIes == NULL) && ies_local_ptr)
6843 cdf_mem_free(ies_local_ptr);
6844
6845 csr_free_scan_result_entry(pMac, scan_res_ptr);
6846 return CDF_STATUS_E_RESOURCES;
6847 }
6848 csr_scan_add_result(pMac, scan_res_ptr, ies_local_ptr, session_id);
6849 return CDF_STATUS_SUCCESS;
6850}
6851#endif
6852
6853/**
6854 * csr_get_bssdescr_from_scan_handle() - This function to extract
6855 * first bss description from scan handle
6856 * @result_handle: an object for the result.
6857 *
6858 * This function is written to extract first bss from scan handle.
6859 *
6860 * Return: first bss descriptor from the scan handle.
6861 */
6862tSirBssDescription*
6863csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle,
6864 tSirBssDescription *bss_descr)
6865{
6866 tListElem *first_element = NULL;
6867 tCsrScanResult *scan_result = NULL;
6868 tScanResultList *bss_list = (tScanResultList *)result_handle;
6869
6870 if (NULL == bss_list) {
6871 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6872 FL("Empty bss_list"));
6873 return NULL;
6874 }
6875 if (csr_ll_is_list_empty(&bss_list->List, LL_ACCESS_NOLOCK)) {
6876 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6877 FL("bss_list->List is empty"));
6878 cdf_mem_free(bss_list);
6879 return NULL;
6880 }
6881 first_element = csr_ll_peek_head(&bss_list->List, LL_ACCESS_NOLOCK);
6882 if (first_element) {
6883 scan_result = GET_BASE_ADDR(first_element,
6884 tCsrScanResult,
6885 Link);
6886 cdf_mem_copy(bss_descr,
6887 &scan_result->Result.BssDescriptor,
6888 sizeof(tSirBssDescription));
6889 }
6890 return bss_descr;
6891}
6892
6893/**
6894 * scan_active_list_cmd_timeout_handle() - To handle scan active command timeout
6895 * @userData: scan context
6896 *
6897 * This routine is to handle scan active command timeout
6898 *
6899 * Return: None
6900 */
6901void csr_scan_active_list_timeout_handle(void *userData)
6902{
6903 tSmeCmd *scan_cmd = (tSmeCmd *) userData;
6904 tHalHandle *hal_ctx = cds_get_context(CDF_MODULE_ID_PE);
6905 tpAniSirGlobal mac_ctx;
6906 uint16_t scan_id;
6907 tSirSmeScanAbortReq *msg;
6908 uint16_t msg_len;
6909 CDF_STATUS status = CDF_STATUS_SUCCESS;
6910
6911 if (scan_cmd == NULL) {
6912 CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
6913 FL("Scan Timeout: Scan command is NULL"));
6914 return;
6915 }
6916 mac_ctx = PMAC_STRUCT(hal_ctx);
6917 scan_id = scan_cmd->u.scanCmd.scanID;
6918 sms_log(mac_ctx, LOGE,
6919 FL("Scan Timeout:Sending abort to Firmware ID %d session %d "),
6920 scan_id, scan_cmd->sessionId);
6921 msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq));
6922 msg = cdf_mem_malloc(msg_len);
6923 if (NULL == msg) {
6924 sms_log(mac_ctx, LOGE,
6925 FL("Failed to alloc memory for SmeScanAbortReq"));
6926 return;
6927 }
6928 cdf_mem_zero((void *)msg, msg_len);
6929 msg->type = eWNI_SME_SCAN_ABORT_IND;
6930 msg->msgLen = msg_len;
6931 msg->sessionId = scan_cmd->sessionId;
6932 msg->scan_id = scan_id;
6933 status = cds_send_mb_message_to_mac(msg);
6934 if (!CDF_IS_STATUS_SUCCESS(status)) {
6935 sms_log(mac_ctx, LOGE,
6936 FL(" Failed to post message to LIM"));
6937 cdf_mem_free(msg);
6938 }
6939 csr_release_scan_command(mac_ctx, scan_cmd, eCSR_SCAN_FAILURE);
6940 return;
6941}