blob: ecf7939f93f26362c4146f63d32b7a345c928644 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080052#include "wma.h"
53
54#include "cds_concurrency.h"
55#include "wlan_hdd_main.h"
56
57#define MIN_CHN_TIME_TO_FIND_GO 100
58#define MAX_CHN_TIME_TO_FIND_GO 100
59#define DIRECT_SSID_LEN 7
60
61/* Purpose of HIDDEN_TIMER
62** When we remove hidden ssid from the profile i.e., forget the SSID via GUI that SSID shouldn't see in the profile
63** For above requirement we used timer limit, logic is explained below
64** Timer value is initialsed to current time when it receives corresponding probe response of hidden SSID (The probe request is
65** received regularly till SSID in the profile. Once it is removed from profile probe request is not sent.) when we receive probe response
66** 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
67** then we are not updating with old one
68*/
69
70#define HIDDEN_TIMER (1*60*1000)
71#define CSR_SCAN_RESULT_RSSI_WEIGHT 80 /* must be less than 100, represent the persentage of new RSSI */
72
73#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL 140
74#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL 120
75
76#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 30
77#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 20
78
79#define PCL_ADVANTAGE 30
80#define PCL_RSSI_THRESHOLD -75
81
82#define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \
83 ((pMac)->scan.nBssLimit <= (csr_ll_count(&(pMac)->scan.scanResultList)))
84
85void csr_scan_get_result_timer_handler(void *);
86static void csr_scan_result_cfg_aging_timer_handler(void *pv);
87static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType,
88 tCsrScanRequest *pScanRequest);
89#ifdef WLAN_AP_STA_CONCURRENCY
90static void csr_sta_ap_conc_timer_handler(void *);
91#endif
92bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053093QDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList,
95 uint8_t NumChannels);
96void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList,
97 uint32_t cfgId);
98void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode);
99void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList);
100void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
101 eCsrScanStatus scanStatus);
102static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac, uint8_t *pChannels,
103 uint8_t numChn,
104 tSirBssDescription *pBssDesc,
105 tDot11fBeaconIEs **ppIes);
106bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel);
107void csr_prune_channel_list_for_mode(tpAniSirGlobal pMac,
108 tCsrChannel *pChannelList);
109
110#define CSR_IS_SOCIAL_CHANNEL(channel) \
111 (((channel) == 1) || ((channel) == 6) || ((channel) == 11))
112
113static void csr_release_scan_cmd_pending_list(tpAniSirGlobal pMac)
114{
115 tListElem *pEntry;
116 tSmeCmd *pCommand;
117
118 while ((pEntry =
119 csr_ll_remove_head(&pMac->scan.scanCmdPendingList,
120 LL_ACCESS_LOCK)) != NULL) {
121 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
122 if (eSmeCsrCommandMask & pCommand->command) {
123 csr_abort_command(pMac, pCommand, true);
124 } else {
125 sms_log(pMac, LOGE, FL("Error: Received command : %d"),
126 pCommand->command);
127 }
128 }
129}
130
131/* pResult is invalid calling this function. */
132void csr_free_scan_result_entry(tpAniSirGlobal pMac, tCsrScanResult *pResult)
133{
134 if (NULL != pResult->Result.pvIes) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530135 qdf_mem_free(pResult->Result.pvIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530137 qdf_mem_free(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800138}
139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530140static QDF_STATUS csr_ll_scan_purge_result(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141 tDblLinkList *pList)
142{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530143 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144 tListElem *pEntry;
145 tCsrScanResult *pBssDesc;
146
147 csr_ll_lock(pList);
148
149 while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) {
150 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
151 csr_free_scan_result_entry(pMac, pBssDesc);
152 }
153
154 csr_ll_unlock(pList);
155
156 return status;
157}
158
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530159QDF_STATUS csr_scan_open(tpAniSirGlobal mac_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530161 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800162
163 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanResultList);
164 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.tempScanResults);
165 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList24);
166 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList5G);
167#ifdef WLAN_AP_STA_CONCURRENCY
168 csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanCmdPendingList);
169#endif
170 mac_ctx->scan.fFullScanIssued = false;
171 mac_ctx->scan.nBssLimit = CSR_MAX_BSS_SUPPORT;
172#ifdef WLAN_AP_STA_CONCURRENCY
Anurag Chouhan210db072016-02-22 18:42:15 +0530173 status = qdf_mc_timer_init(&mac_ctx->scan.hTimerStaApConcTimer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530174 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175 csr_sta_ap_conc_timer_handler,
176 mac_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530177 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 sms_log(mac_ctx, LOGE,
179 FL("Mem Alloc failed for hTimerStaApConcTimer timer"));
180 return status;
181 }
182#endif
Anurag Chouhan210db072016-02-22 18:42:15 +0530183 status = qdf_mc_timer_init(&mac_ctx->scan.hTimerResultCfgAging,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530184 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 csr_scan_result_cfg_aging_timer_handler,
186 mac_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530187 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188 sms_log(mac_ctx, LOGE,
189 FL("Mem Alloc failed for CFG ResultAging timer"));
190
191 return status;
192}
193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530194QDF_STATUS csr_scan_close(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195{
196 csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults);
197 csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList);
198#ifdef WLAN_AP_STA_CONCURRENCY
199 csr_release_scan_cmd_pending_list(pMac);
200#endif
201 csr_ll_close(&pMac->scan.scanResultList);
202 csr_ll_close(&pMac->scan.tempScanResults);
203#ifdef WLAN_AP_STA_CONCURRENCY
204 csr_ll_close(&pMac->scan.scanCmdPendingList);
205#endif
206 csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList24);
207 csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList5G);
208 csr_ll_close(&pMac->scan.channelPowerInfoList24);
209 csr_ll_close(&pMac->scan.channelPowerInfoList5G);
210 csr_scan_disable(pMac);
Anurag Chouhan210db072016-02-22 18:42:15 +0530211 qdf_mc_timer_destroy(&pMac->scan.hTimerResultCfgAging);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212#ifdef WLAN_AP_STA_CONCURRENCY
Anurag Chouhan210db072016-02-22 18:42:15 +0530213 qdf_mc_timer_destroy(&pMac->scan.hTimerStaApConcTimer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530215 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216}
217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530218QDF_STATUS csr_scan_enable(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219{
220
221 pMac->scan.fScanEnable = true;
222
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530223 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224}
225
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530226QDF_STATUS csr_scan_disable(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227{
228
229 csr_scan_stop_timers(pMac);
230 pMac->scan.fScanEnable = false;
231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530232 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233}
234
235/* Set scan timing parameters according to state of other driver sessions */
236/* No validation of the parameters is performed. */
237static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType,
238 tCsrScanRequest *pScanRequest)
239{
240#ifdef WLAN_AP_STA_CONCURRENCY
241 if (csr_is_any_session_connected(pMac)) {
242 /* Reset passive scan time as per ini parameter. */
243 cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
244 pMac->roam.configParam.nPassiveMaxChnTimeConc);
245 /* If multi-session, use the appropriate default scan times */
246 if (scanType == eSIR_ACTIVE_SCAN) {
247 pScanRequest->maxChnTime =
248 pMac->roam.configParam.nActiveMaxChnTimeConc;
249 pScanRequest->minChnTime =
250 pMac->roam.configParam.nActiveMinChnTimeConc;
251 } else {
252 pScanRequest->maxChnTime =
253 pMac->roam.configParam.nPassiveMaxChnTimeConc;
254 pScanRequest->minChnTime =
255 pMac->roam.configParam.nPassiveMinChnTimeConc;
256 }
257 pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc;
258
Agrawal Ashish17bb3902016-05-05 13:29:40 +0530259 pScanRequest->min_rest_time =
260 pMac->roam.configParam.min_rest_time_conc;
261 pScanRequest->idle_time =
262 pMac->roam.configParam.idle_time_conc;
263
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800264 /* Return so that fields set above will not be overwritten. */
265 return;
266 }
267#endif
268
269 /* This portion of the code executed if multi-session not supported */
270 /* (WLAN_AP_STA_CONCURRENCY not defined) or no multi-session. */
271 /* Use the "regular" (non-concurrency) default scan timing. */
272 cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
273 pMac->roam.configParam.nPassiveMaxChnTime);
274 if (pScanRequest->scanType == eSIR_ACTIVE_SCAN) {
275 pScanRequest->maxChnTime =
276 pMac->roam.configParam.nActiveMaxChnTime;
277 pScanRequest->minChnTime =
278 pMac->roam.configParam.nActiveMinChnTime;
279 } else {
280 pScanRequest->maxChnTime =
281 pMac->roam.configParam.nPassiveMaxChnTime;
282 pScanRequest->minChnTime =
283 pMac->roam.configParam.nPassiveMinChnTime;
284 }
285#ifdef WLAN_AP_STA_CONCURRENCY
Agrawal Ashish17bb3902016-05-05 13:29:40 +0530286
287 /* No rest time/Idle time if no sessions are connected. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 pScanRequest->restTime = 0;
Agrawal Ashish17bb3902016-05-05 13:29:40 +0530289 pScanRequest->min_rest_time = 0;
290 pScanRequest->idle_time = 0;
291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292#endif
293}
294
295/**
296 * csr_scan_2g_only_request() - This function will update the scan request with
297 * only 2.4GHz valid channel list.
298 * @mac_ctx: Pointer to Global MAC structure
299 * @scan_cmd scan cmd
300 * @scan_req scan req
301 *
302 * This function will update the scan request with only 2.4GHz valid channel
303 * list.
304 *
305 * @Return: status of operation
306 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530307static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800308csr_scan_2g_only_request(tpAniSirGlobal mac_ctx,
309 tSmeCmd *scan_cmd,
310 tCsrScanRequest *scan_req)
311{
312 uint8_t idx, lst_sz = 0;
313
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530314 QDF_ASSERT(scan_cmd && scan_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315 /* To silence the KW tool null check is added */
316 if ((scan_cmd == NULL) || (scan_req == NULL)) {
317 sms_log(mac_ctx, LOGE,
318 FL(" Scan Cmd or Scan Request is NULL "));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530319 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320 }
321
322 if (eCSR_SCAN_REQUEST_FULL_SCAN != scan_req->requestType)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530323 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324
325 sms_log(mac_ctx, LOG1,
326 FL("Scanning only 2G Channels during first scan"));
327
328 /* Contsruct valid Supported 2.4 GHz Channel List */
329 if (NULL == scan_req->ChannelInfo.ChannelList) {
330 scan_req->ChannelInfo.ChannelList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530331 qdf_mem_malloc(NUM_24GHZ_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800332 if (NULL == scan_req->ChannelInfo.ChannelList) {
333 sms_log(mac_ctx, LOGE, FL("Memory allocation failed."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530334 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335 }
336 for (idx = 1; idx <= NUM_24GHZ_CHANNELS; idx++) {
337 if (csr_is_supported_channel(mac_ctx, idx)) {
338 scan_req->ChannelInfo.ChannelList[lst_sz] = idx;
339 lst_sz++;
340 }
341 }
342 } else {
343 for (idx = 0;
344 idx < scan_req->ChannelInfo.numOfChannels;
345 idx++) {
346 if (scan_req->ChannelInfo.ChannelList[idx] <=
347 CDS_24_GHZ_CHANNEL_14
348 && csr_is_supported_channel(mac_ctx,
349 scan_req->ChannelInfo.ChannelList[idx])) {
350 scan_req->ChannelInfo.ChannelList[lst_sz] =
351 scan_req->ChannelInfo.ChannelList[idx];
352 lst_sz++;
353 }
354 }
355 }
356 scan_req->ChannelInfo.numOfChannels = lst_sz;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530357 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358}
359
360static void
361csr_set_scan_reason(tSmeCmd *scan_cmd, eCsrRequestType req_type)
362{
363 switch (req_type) {
364 case eCSR_SCAN_REQUEST_11D_SCAN:
365 scan_cmd->u.scanCmd.reason = eCsrScan11d1;
366 break;
367#ifdef SOFTAP_CHANNEL_RANGE
368 case eCSR_SCAN_SOFTAP_CHANNEL_RANGE:
369#endif
370 case eCSR_SCAN_REQUEST_FULL_SCAN:
371 case eCSR_SCAN_P2P_DISCOVERY:
372 scan_cmd->u.scanCmd.reason = eCsrScanUserRequest;
373 break;
374 case eCSR_SCAN_HO_PROBE_SCAN:
375 scan_cmd->u.scanCmd.reason = eCsrScanProbeBss;
376 break;
377 case eCSR_SCAN_P2P_FIND_PEER:
378 scan_cmd->u.scanCmd.reason = eCsrScanP2PFindPeer;
379 break;
380 default:
381 break;
382 }
383}
384
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530385static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386csr_issue_11d_scan(tpAniSirGlobal mac_ctx, tSmeCmd *scan_cmd,
387 tCsrScanRequest *scan_req, uint16_t session_id)
388{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530389 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 tSmeCmd *scan_11d_cmd = NULL;
391 tCsrScanRequest tmp_rq;
392 tCsrChannelInfo *pChnInfo = &tmp_rq.ChannelInfo;
393 uint32_t numChn = mac_ctx->scan.base_channels.numChannels;
394 tCsrRoamSession *csr_session = CSR_GET_SESSION(mac_ctx, session_id);
395
396 if (csr_session == NULL) {
397 sms_log(mac_ctx, LOGE, FL("session %d not found"),
398 session_id);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530399 QDF_ASSERT(0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530400 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 }
402
403 if (!(((false == mac_ctx->first_scan_done)
404 && (eCSR_SCAN_REQUEST_11D_SCAN != scan_req->requestType))
405#ifdef SOFTAP_CHANNEL_RANGE
406 && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != scan_req->requestType)
407#endif
408 && (false == mac_ctx->scan.fEnableBypass11d)))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530409 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530411 qdf_mem_set(&tmp_rq, sizeof(tCsrScanRequest), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 scan_11d_cmd = csr_get_command_buffer(mac_ctx);
413 if (!scan_11d_cmd) {
414 sms_log(mac_ctx, LOGE, FL("scan_11d_cmd failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530415 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416 }
417
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530418 qdf_mem_set(&scan_11d_cmd->u.scanCmd, sizeof(tScanCmd), 0);
419 pChnInfo->ChannelList = qdf_mem_malloc(numChn);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 if (NULL == pChnInfo->ChannelList) {
421 sms_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530422 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530424 qdf_mem_copy(pChnInfo->ChannelList,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 mac_ctx->scan.base_channels.channelList, numChn);
426
427 pChnInfo->numOfChannels = (uint8_t) numChn;
428 scan_11d_cmd->command = eSmeCommandScan;
429 scan_11d_cmd->u.scanCmd.callback = mac_ctx->scan.callback11dScanDone;
430 scan_11d_cmd->u.scanCmd.pContext = NULL;
431 wma_get_scan_id(&scan_11d_cmd->u.scanCmd.scanID);
432 tmp_rq.BSSType = eCSR_BSS_TYPE_ANY;
433 tmp_rq.scan_id = scan_11d_cmd->u.scanCmd.scanID;
434
Anurag Chouhan210db072016-02-22 18:42:15 +0530435 status = qdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530436 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437 csr_scan_active_list_timeout_handle, &scan_11d_cmd);
438
439 if (csr_is11d_supported(mac_ctx)) {
440 tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan;
441 if (scan_req->bcnRptReqScan)
442 tmp_rq.scanType = scan_req->scanType ?
443 eSIR_PASSIVE_SCAN : scan_req->scanType;
444 else
445 tmp_rq.scanType = eSIR_PASSIVE_SCAN;
446 tmp_rq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
447 scan_11d_cmd->u.scanCmd.reason = eCsrScan11d1;
448 tmp_rq.maxChnTime =
449 mac_ctx->roam.configParam.nPassiveMaxChnTime;
450 tmp_rq.minChnTime =
451 mac_ctx->roam.configParam.nPassiveMinChnTime;
452 } else {
453 tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan;
454 if (scan_req->bcnRptReqScan)
455 tmp_rq.scanType = scan_req->scanType;
456 else
457 tmp_rq.scanType = eSIR_ACTIVE_SCAN;
458 tmp_rq.requestType = scan_req->requestType;
459 scan_11d_cmd->u.scanCmd.reason = scan_cmd->u.scanCmd.reason;
460 tmp_rq.maxChnTime = mac_ctx->roam.configParam.nActiveMaxChnTime;
461 tmp_rq.minChnTime = mac_ctx->roam.configParam.nActiveMinChnTime;
462 }
463 if (mac_ctx->roam.configParam.nInitialDwellTime) {
464 tmp_rq.maxChnTime = mac_ctx->roam.configParam.nInitialDwellTime;
465 sms_log(mac_ctx, LOG1, FL("11d scan, updating dwell time for first scan %u"),
466 tmp_rq.maxChnTime);
467 }
468
469 status = csr_scan_copy_request(mac_ctx,
470 &scan_11d_cmd->u.scanCmd.u.scanRequest, &tmp_rq);
471 /* Free the channel list */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530472 qdf_mem_free(pChnInfo->ChannelList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473 pChnInfo->ChannelList = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530474 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 sms_log(mac_ctx, LOGE, FL("csr_scan_copy_request failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530476 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477 }
478
479 mac_ctx->scan.scanProfile.numOfChannels =
480 scan_11d_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
481
482
483 status = csr_queue_sme_command(mac_ctx, scan_11d_cmd, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530484 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485 sms_log(mac_ctx, LOGE, FL("Failed to send message status = %d"),
486 status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530487 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530489 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490}
491
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530492QDF_STATUS csr_scan_request(tpAniSirGlobal pMac, uint16_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800493 tCsrScanRequest *scan_req,
494 csr_scan_completeCallback callback, void *pContext)
495{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530496 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 tSmeCmd *scan_cmd = NULL;
498 tCsrScanRequest *pTempScanReq = NULL;
499 tCsrConfig *cfg_prm = &pMac->roam.configParam;
500
501 if (scan_req == NULL) {
502 sms_log(pMac, LOGE, FL("scan_req is NULL"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530503 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504 return status;
505 }
506
507 /*
508 * During group formation, the P2P client scans for GO with the specific
509 * SSID. There will be chances of GO switching to other channels because
510 * of scan or to STA channel in case of STA+GO MCC scenario. So to
511 * increase the possibility of client to find the GO, the dwell time of
512 * scan is increased to 100ms.
513 * If the scan request is for specific SSId the length of SSID will be
514 * greater than 7 as SSID for p2p search contains "DIRECT-")
515 */
516 if (scan_req->p2pSearch
517 && scan_req->SSIDs.numOfSSIDs
518 && (NULL != scan_req->SSIDs.SSIDList)
519 && (scan_req->SSIDs.SSIDList->SSID.length > DIRECT_SSID_LEN)) {
520 sms_log(pMac, LOG1, FL("P2P: Increasing the min and max Dwell time to %d for specific SSID scan %.*s"),
521 MAX_CHN_TIME_TO_FIND_GO,
522 scan_req->SSIDs.SSIDList->SSID.length,
523 scan_req->SSIDs.SSIDList->SSID.ssId);
524 scan_req->maxChnTime = MAX_CHN_TIME_TO_FIND_GO;
525 scan_req->minChnTime = MIN_CHN_TIME_TO_FIND_GO;
526 }
527
528 if (!pMac->scan.fScanEnable) {
529 sms_log(pMac, LOGE, FL("SId: %d Scanning not enabled Scan type=%u, numOfSSIDs=%d P2P search=%d"),
530 sessionId, scan_req->requestType,
531 scan_req->SSIDs.numOfSSIDs,
532 scan_req->p2pSearch);
533 goto release_cmd;
534 }
535
536 scan_cmd = csr_get_command_buffer(pMac);
537 if (!scan_cmd) {
538 sms_log(pMac, LOGE, FL("scan_cmd is NULL"));
539 goto release_cmd;
540 }
541
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530542 qdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543 scan_cmd->command = eSmeCommandScan;
544 scan_cmd->sessionId = sessionId;
545 if (scan_cmd->sessionId >= CSR_ROAM_SESSION_MAX)
546 sms_log(pMac, LOGE, FL("Invalid Sme SessionID: %d"), sessionId);
547 scan_cmd->u.scanCmd.callback = callback;
548 scan_cmd->u.scanCmd.pContext = pContext;
549 csr_set_scan_reason(scan_cmd, scan_req->requestType);
550 if (scan_req->minChnTime == 0 && scan_req->maxChnTime == 0) {
551 /* The caller doesn't set the time correctly. Set it here */
552 csr_set_default_scan_timing(pMac, scan_req->scanType, scan_req);
553 sms_log(pMac, LOG1,
554 FL("Setting default min %d and max %d ChnTime"),
555 scan_req->minChnTime, scan_req->maxChnTime);
556 }
557#ifdef WLAN_AP_STA_CONCURRENCY
Agrawal Ashish17bb3902016-05-05 13:29:40 +0530558 /*
559 * Need to set restTime/min_Ret_time/idle_time
560 * only if at least one session is connected
561 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562 if (scan_req->restTime == 0 && csr_is_any_session_connected(pMac)) {
563 scan_req->restTime = cfg_prm->nRestTimeConc;
Agrawal Ashish17bb3902016-05-05 13:29:40 +0530564 scan_req->min_rest_time = cfg_prm->min_rest_time_conc;
565 scan_req->idle_time = cfg_prm->idle_time_conc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 if (scan_req->scanType == eSIR_ACTIVE_SCAN) {
567 scan_req->maxChnTime = cfg_prm->nActiveMaxChnTimeConc;
568 scan_req->minChnTime = cfg_prm->nActiveMinChnTimeConc;
569 } else {
570 scan_req->maxChnTime = cfg_prm->nPassiveMaxChnTimeConc;
571 scan_req->minChnTime = cfg_prm->nPassiveMinChnTimeConc;
572 }
573 }
574#endif
575 /* Increase dwell time in case P2P Search and Miracast is not present */
576 if (scan_req->p2pSearch && scan_req->ChannelInfo.numOfChannels
577 == P2P_SOCIAL_CHANNELS && (!(pMac->sme.miracast_value))) {
578 scan_req->maxChnTime += P2P_SEARCH_DWELL_TIME_INCREASE;
579 }
580 scan_cmd->u.scanCmd.scanID = scan_req->scan_id;
581 /*
582 * If it is the first scan request from HDD, CSR checks if it is for 11d
583 * If it is not, CSR will save the scan request in the pending cmd queue
584 * & issue an 11d scan request to PE.
585 */
586 status = csr_issue_11d_scan(pMac, scan_cmd, scan_req, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530587 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 goto release_cmd;
589
590 /*
591 * Scan only 2G Channels if set in ini file. This is mainly to reduce
592 * the First Scan duration once we turn on Wifi
593 */
594 if (pMac->scan.fFirstScanOnly2GChnl
595 && false == pMac->first_scan_done) {
596 csr_scan_2g_only_request(pMac, scan_cmd, scan_req);
597 pMac->first_scan_done = true;
598 }
599
600
601 if (cfg_prm->nInitialDwellTime) {
602 scan_req->maxChnTime = cfg_prm->nInitialDwellTime;
603 cfg_prm->nInitialDwellTime = 0;
604 sms_log(pMac, LOG1, FL("updating dwell time for first scan %u"),
605 scan_req->maxChnTime);
606 }
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +0530607 scan_req->scan_adaptive_dwell_mode = cfg_prm->scan_adaptive_dwell_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608
609 status = csr_scan_copy_request(pMac, &scan_cmd->u.scanCmd.u.scanRequest,
610 scan_req);
611 /*
612 * Reset the variable after the first scan is queued after loading the
613 * driver. The purpose of this parameter is that DFS channels are
614 * skipped during the first scan after loading the driver. The above API
615 * builds the target scan request in which this variable is used.
616 */
617 cfg_prm->initial_scan_no_dfs_chnl = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530618 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619 sms_log(pMac, LOGE,
620 FL("fail to copy request status = %d"), status);
621 goto release_cmd;
622 }
623
624 pTempScanReq = &scan_cmd->u.scanCmd.u.scanRequest;
625 pMac->scan.scanProfile.numOfChannels =
626 pTempScanReq->ChannelInfo.numOfChannels;
Anurag Chouhan210db072016-02-22 18:42:15 +0530627 status = qdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530628 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629 csr_scan_active_list_timeout_handle, scan_cmd);
630 sms_log(pMac, LOG1,
631 FL("SId=%d scanId=%d Scan reason=%u numSSIDs=%d numChan=%d P2P search=%d minCT=%d maxCT=%d uIEFieldLen=%d"),
632 sessionId, scan_cmd->u.scanCmd.scanID,
633 scan_cmd->u.scanCmd.reason, pTempScanReq->SSIDs.numOfSSIDs,
634 pTempScanReq->ChannelInfo.numOfChannels,
635 pTempScanReq->p2pSearch, pTempScanReq->minChnTime,
636 pTempScanReq->maxChnTime, pTempScanReq->uIEFieldLen);
637
638 status = csr_queue_sme_command(pMac, scan_cmd, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 sms_log(pMac, LOGE,
641 FL("fail to send message status = %d"), status);
642 }
643
644release_cmd:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530645 if (!QDF_IS_STATUS_SUCCESS(status) && scan_cmd) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 sms_log(pMac, LOGE, FL(" SId: %d Failed with status=%d"
647 " Scan reason=%u numOfSSIDs=%d"
648 " P2P search=%d scanId=%d"),
649 sessionId, status, scan_cmd->u.scanCmd.reason,
650 scan_req->SSIDs.numOfSSIDs, scan_req->p2pSearch,
651 scan_cmd->u.scanCmd.scanID);
652 csr_release_command_scan(pMac, scan_cmd);
653 }
654
655 return status;
656}
657
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530658QDF_STATUS csr_issue_roam_after_lostlink_scan(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 uint32_t sessionId,
660 eCsrRoamReason reason)
661{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530662 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663 tScanResultHandle hBSSList = NULL;
664 tCsrScanResultFilter *pScanFilter = NULL;
665 uint32_t roamId = 0;
666 tCsrRoamProfile *pProfile = NULL;
667 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
668
669 if (!pSession) {
670 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530671 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672 }
673
674 sms_log(pMac, LOG1, FL("Entry"));
675 if (pSession->fCancelRoaming) {
676 sms_log(pMac, LOGW, FL("lost link roaming canceled"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530677 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 goto free_filter;
679 }
680 /* Here is the profile we need to connect to */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530681 pScanFilter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800682 if (NULL == pScanFilter) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530683 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 goto free_filter;
685 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530686 qdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 if (NULL == pSession->pCurRoamProfile) {
688 pScanFilter->EncryptionType.numEntries = 1;
689 pScanFilter->EncryptionType.encryptionType[0] =
690 eCSR_ENCRYPT_TYPE_NONE;
691 } else {
692 /*
693 * We have to make a copy of pCurRoamProfile because it will
694 * be free inside csr_roam_issue_connect
695 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530696 pProfile = qdf_mem_malloc(sizeof(tCsrRoamProfile));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 if (NULL == pProfile) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530698 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto free_filter;
700 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530701 qdf_mem_set(pProfile, sizeof(tCsrRoamProfile), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 status = csr_roam_copy_profile(pMac, pProfile,
703 pSession->pCurRoamProfile);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530704 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 goto free_filter;
706 status = csr_roam_prepare_filter_from_profile(pMac, pProfile,
707 pScanFilter);
708 } /* We have a profile */
709 roamId = GET_NEXT_ROAM_ID(&pMac->roam);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530710 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 goto free_filter;
712
713 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530714 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 goto free_filter;
716
717 if (eCsrLostLink1 == reason) {
718 /* if possible put the last connected BSS in beginning */
719 csr_move_bss_to_head_from_bssid(pMac,
720 &pSession->connectedProfile.bssid, hBSSList);
721 }
722 status = csr_roam_issue_connect(pMac, sessionId, pProfile, hBSSList,
723 reason, roamId, true, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530724 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725 csr_scan_result_purge(pMac, hBSSList);
726 }
727
728free_filter:
729 if (pScanFilter) {
730 /* we need to free memory for filter if profile exists */
731 csr_free_scan_filter(pMac, pScanFilter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530732 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800733 }
734 if (NULL != pProfile) {
735 csr_release_profile(pMac, pProfile);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530736 qdf_mem_free(pProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800737 }
738 return status;
739}
740
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530741QDF_STATUS csr_scan_handle_failed_lostlink1(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742 uint32_t sessionId)
743{
744 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
745
746 if (!pSession) {
747 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530748 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800749 }
750 sms_log(pMac, LOGW, "Lost link scan 1 failed");
751 if (pSession->fCancelRoaming)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530752 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753 if (!pSession->pCurRoamProfile)
754 return csr_scan_request_lost_link3(pMac, sessionId);
755 /*
756 * We fail lostlink1 but there may be other BSS in the cached result
757 * fit the profile. Give it a try first
758 */
759 if (pSession->pCurRoamProfile->SSIDs.numOfSSIDs == 0 ||
760 pSession->pCurRoamProfile->SSIDs.numOfSSIDs > 1)
761 /* try lostlink scan2 */
762 return csr_scan_request_lost_link2(pMac, sessionId);
763 if (!pSession->pCurRoamProfile->ChannelInfo.ChannelList
764 || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) {
765 /* go straight to lostlink scan3 */
766 return csr_scan_request_lost_link3(pMac, sessionId);
767 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530768 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769}
770
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530771QDF_STATUS csr_scan_handle_failed_lostlink2(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 uint32_t sessionId)
773{
774 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
775
776 if (!pSession) {
777 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530778 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 }
780
781 sms_log(pMac, LOGW, "Lost link scan 2 failed");
782 if (pSession->fCancelRoaming)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530783 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784
785 if (!pSession->pCurRoamProfile
786 || !pSession->pCurRoamProfile->ChannelInfo.ChannelList
787 || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) {
788 /* try lostlink scan3 */
789 return csr_scan_request_lost_link3(pMac, sessionId);
790 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530791 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792}
793
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530794QDF_STATUS csr_scan_handle_failed_lostlink3(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795 uint32_t sessionId)
796{
797 sms_log(pMac, LOGW, "Lost link scan 3 failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530798 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799}
800
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530801static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802csr_update_lost_link1_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
803 tCsrRoamSession *pSession, uint32_t session_id)
804{
805 uint8_t i, num_ch = 0;
806 tScanResultHandle bss_lst = NULL;
807 tCsrScanResultInfo *scan_result = NULL;
808 tCsrScanResultFilter *scan_filter = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530809 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 tCsrSSIDs *ssid_list = &cmd->u.scanCmd.u.scanRequest.SSIDs;
811 tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo;
812
813 cmd->command = eSmeCommandScan;
814 cmd->sessionId = (uint8_t) session_id;
815 cmd->u.scanCmd.reason = eCsrScanLostLink1;
816 cmd->u.scanCmd.callback = NULL;
817 cmd->u.scanCmd.pContext = NULL;
818 cmd->u.scanCmd.u.scanRequest.maxChnTime =
819 mac_ctx->roam.configParam.nActiveMaxChnTime;
820 cmd->u.scanCmd.u.scanRequest.minChnTime =
821 mac_ctx->roam.configParam.nActiveMinChnTime;
822 cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
823 wma_get_scan_id(&cmd->u.scanCmd.scanID);
Anurag Chouhan210db072016-02-22 18:42:15 +0530824 status = qdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530825 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 csr_scan_active_list_timeout_handle, &cmd);
827 cmd->u.scanCmd.u.scanRequest.scan_id =
828 cmd->u.scanCmd.scanID;
829
830 if (pSession->connectedProfile.SSID.length) {
831 /*
832 * on error: following memory will be released by call to
833 * csr_release_command_scan in the end
834 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530835 ssid_list->SSIDList = qdf_mem_malloc(sizeof(tCsrSSIDInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800836 if (NULL == ssid_list->SSIDList)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530837 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 ssid_list->numOfSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530839 qdf_mem_copy(&ssid_list->SSIDList[0].SSID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840 &pSession->connectedProfile.SSID,
841 sizeof(tSirMacSSid));
842 } else {
843 ssid_list->numOfSSIDs = 0;
844 }
845
846 if (!pSession->pCurRoamProfile)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530847 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530849 scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800850 if (NULL == scan_filter)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530851 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530853 qdf_mem_set(scan_filter, sizeof(tCsrScanResultFilter), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854 status = csr_roam_prepare_filter_from_profile(mac_ctx,
855 pSession->pCurRoamProfile, scan_filter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530856 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857 goto free_lost_link1_local_mem;
858
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530859 if (!(QDF_IS_STATUS_SUCCESS(csr_scan_get_result(mac_ctx, scan_filter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860 &bss_lst)) && bss_lst)) {
861 if (csr_roam_is_channel_valid(mac_ctx,
862 pSession->connectedProfile.operationChannel)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530863 ch_info->ChannelList = qdf_mem_malloc(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800864 if (NULL == ch_info->ChannelList) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530865 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866 goto free_lost_link1_local_mem;
867 }
868 ch_info->ChannelList[0] =
869 pSession->connectedProfile.operationChannel;
870 ch_info->numOfChannels = 1;
871 }
Arif Hussaind3bf1112016-07-29 10:16:53 -0700872 csr_free_scan_filter(mac_ctx, scan_filter);
873 qdf_mem_free(scan_filter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874 return status;
875 }
876
877 /* on error: this mem will be released by csr_release_command_scan */
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530878 ch_info->ChannelList = qdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 if (NULL == ch_info->ChannelList) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530880 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800881 goto free_lost_link1_local_mem;
882 }
883
884 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
885 while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) {
886 for (i = 0; i < num_ch; i++) {
887 if (ch_info->ChannelList[i] ==
888 scan_result->BssDescriptor.channelId)
889 break;
890 }
891 if (i == num_ch)
892 ch_info->ChannelList[num_ch++] =
893 scan_result->BssDescriptor.channelId;
894 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
895 }
896 /* Include the last connected BSS' channel */
897 if (csr_roam_is_channel_valid(mac_ctx,
898 pSession->connectedProfile.operationChannel)) {
899 for (i = 0; i < num_ch; i++) {
900 if (ch_info->ChannelList[i] ==
901 pSession->connectedProfile.operationChannel)
902 break;
903 }
904 if (i == num_ch)
905 ch_info->ChannelList[num_ch++] =
906 pSession->connectedProfile.operationChannel;
907 }
908 ch_info->numOfChannels = num_ch;
909free_lost_link1_local_mem:
910 if (scan_filter) {
911 csr_free_scan_filter(mac_ctx, scan_filter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530912 qdf_mem_free(scan_filter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800913 }
914 if (bss_lst)
915 csr_scan_result_purge(mac_ctx, bss_lst);
916 return status;
917}
918
919/**
920 * csr_scan_request_lost_link1() - start scan on link lost 1
921 * @mac_ctx: mac global context
922 * @session_id: session id
923 *
924 * Lostlink1 scan is to actively scan the last connected profile's SSID on all
925 * matched BSS channels. If no roam profile (it should not), it is like
926 * lostlinkscan3
927 *
928 * Return: status of operation
929 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530930QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931csr_scan_request_lost_link1(tpAniSirGlobal mac_ctx, uint32_t session_id)
932{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530933 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 tSmeCmd *cmd = NULL;
935 tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
936
937 if (!session) {
938 sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530939 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940 }
941
942 sms_log(mac_ctx, LOGW, FL("Entry"));
943 cmd = csr_get_command_buffer(mac_ctx);
944 if (!cmd) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530945 status = QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800946 goto release_lost_link1_cmd;
947 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530948 qdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 status = csr_update_lost_link1_cmd(mac_ctx, cmd, session, session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530950 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800951 goto release_lost_link1_cmd;
952
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530953 qdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530954 sizeof(struct qdf_mac_addr), 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 status = csr_queue_sme_command(mac_ctx, cmd, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530956 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957 sms_log(mac_ctx, LOGE,
958 FL("fail to send message status = %d"), status);
959 }
960
961release_lost_link1_cmd:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530962 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
964 if (cmd)
965 csr_release_command_scan(mac_ctx, cmd);
966 status = csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
967 }
968 return status;
969}
970
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530971static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972csr_update_lost_link2_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
973 uint32_t session_id, tCsrRoamSession *session)
974{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530975 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 uint8_t i, num_ch = 0;
977 tScanResultHandle bss_lst = NULL;
978 tCsrScanResultInfo *scan_result = NULL;
979 tCsrScanResultFilter *scan_fltr = NULL;
980 tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo;
981
982 cmd->command = eSmeCommandScan;
983 cmd->sessionId = (uint8_t) session_id;
984 cmd->u.scanCmd.reason = eCsrScanLostLink2;
985 cmd->u.scanCmd.callback = NULL;
986 cmd->u.scanCmd.pContext = NULL;
987 cmd->u.scanCmd.u.scanRequest.maxChnTime =
988 mac_ctx->roam.configParam.nActiveMaxChnTime;
989 cmd->u.scanCmd.u.scanRequest.minChnTime =
990 mac_ctx->roam.configParam.nActiveMinChnTime;
991 cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
992 wma_get_scan_id(&cmd->u.scanCmd.scanID);
993 cmd->u.scanCmd.u.scanRequest.scan_id =
994 cmd->u.scanCmd.scanID;
995 if (!session->pCurRoamProfile)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530996 return QDF_STATUS_SUCCESS;
Anurag Chouhan210db072016-02-22 18:42:15 +0530997 status = qdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530998 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800999 csr_scan_active_list_timeout_handle, &cmd);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301000 scan_fltr = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001 if (NULL == scan_fltr)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301002 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001003
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301004 qdf_mem_set(scan_fltr, sizeof(tCsrScanResultFilter), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001005 status = csr_roam_prepare_filter_from_profile(mac_ctx,
1006 session->pCurRoamProfile, scan_fltr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301007 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008 goto free_lost_link2_local_mem;
1009
1010 status = csr_scan_get_result(mac_ctx, scan_fltr, &bss_lst);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301011 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 goto free_lost_link2_local_mem;
1013
1014 if (!bss_lst)
1015 goto free_lost_link2_local_mem;
1016
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301017 ch_info->ChannelList = qdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001018 if (NULL == ch_info->ChannelList) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301019 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001020 goto free_lost_link2_local_mem;
1021 }
1022 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
1023 while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) {
1024 for (i = 0; i < num_ch; i++) {
1025 if (ch_info->ChannelList[i] ==
1026 scan_result->BssDescriptor.channelId)
1027 break;
1028 }
1029 if (i == num_ch)
1030 ch_info->ChannelList[num_ch++] =
1031 scan_result->BssDescriptor.channelId;
1032 scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
1033 }
1034 ch_info->numOfChannels = num_ch;
1035
1036free_lost_link2_local_mem:
1037 if (scan_fltr) {
1038 csr_free_scan_filter(mac_ctx, scan_fltr);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301039 qdf_mem_free(scan_fltr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040 }
1041 if (bss_lst)
1042 csr_scan_result_purge(mac_ctx, bss_lst);
1043 return status;
1044}
1045
1046/**
1047 * csr_scan_request_lost_link2() - start scan on link lost 2
1048 * @mac_ctx: mac global context
1049 * @session_id: session id
1050 *
1051 * Lostlink2 scan is to actively scan the all SSIDs of the last roaming
1052 * profile's on all matched BSS channels. Since MAC doesn't support multiple
1053 * SSID, we scan all SSIDs and filter them afterwards
1054 *
1055 * Return: status of operation
1056 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301057QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001058csr_scan_request_lost_link2(tpAniSirGlobal mac_ctx, uint32_t session_id)
1059{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301060 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001061 tSmeCmd *cmd = NULL;
1062 tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
1063
1064 if (!session) {
1065 sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301066 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067 }
1068
1069 sms_log(mac_ctx, LOGW, FL(" called"));
1070 cmd = csr_get_command_buffer(mac_ctx);
1071 if (!cmd) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301072 status = QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001073 goto release_lost_link2_cmd;
1074 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301075 qdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001076 status = csr_update_lost_link2_cmd(mac_ctx, cmd, session_id, session);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301077 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 goto release_lost_link2_cmd;
1079
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301080 qdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301081 sizeof(struct qdf_mac_addr), 0xFF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 /* Put to the head in pending queue */
1083 status = csr_queue_sme_command(mac_ctx, cmd, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301084 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085 sms_log(mac_ctx, LOGE,
1086 FL("fail to send message status = %d"), status);
1087 goto release_lost_link2_cmd;
1088 }
1089
1090release_lost_link2_cmd:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301091 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
1093 if (cmd)
1094 csr_release_command_scan(mac_ctx, cmd);
1095 status = csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
1096 }
1097 return status;
1098}
1099
1100/**
1101 * csr_scan_request_lost_link3() - To actively scan all valid channels
1102 * @mac_ctx: mac global context
1103 * @session_id: session id
1104 *
1105 * Return: status of operation
1106 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301107QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108csr_scan_request_lost_link3(tpAniSirGlobal mac_ctx, uint32_t session_id)
1109{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301110 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 tSmeCmd *cmd;
1112
1113 sms_log(mac_ctx, LOGW, FL(" called"));
1114 do {
1115 cmd = csr_get_command_buffer(mac_ctx);
1116 if (!cmd) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301117 status = QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118 break;
1119 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301120 qdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 cmd->command = eSmeCommandScan;
1122 cmd->sessionId = (uint8_t) session_id;
1123 cmd->u.scanCmd.reason = eCsrScanLostLink3;
1124 cmd->u.scanCmd.callback = NULL;
1125 cmd->u.scanCmd.pContext = NULL;
1126 cmd->u.scanCmd.u.scanRequest.maxChnTime =
1127 mac_ctx->roam.configParam.nActiveMaxChnTime;
1128 cmd->u.scanCmd.u.scanRequest.minChnTime =
1129 mac_ctx->roam.configParam.nActiveMinChnTime;
1130 cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
1131 wma_get_scan_id(&cmd->u.scanCmd.scanID);
Anurag Chouhan210db072016-02-22 18:42:15 +05301132 status = qdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301133 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 csr_scan_active_list_timeout_handle, &cmd);
1135 cmd->u.scanCmd.u.scanRequest.scan_id =
1136 cmd->u.scanCmd.scanID;
Anurag Chouhanc5548422016-02-24 18:33:27 +05301137 qdf_set_macaddr_broadcast(&cmd->u.scanCmd.u.scanRequest.bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138 /* Put to the head of pending queue */
1139 status = csr_queue_sme_command(mac_ctx, cmd, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301140 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 sms_log(mac_ctx, LOGE,
1142 FL("fail to send message status = %d"), status);
1143 break;
1144 }
1145 } while (0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301146 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
1148 if (cmd)
1149 csr_release_command_scan(mac_ctx, cmd);
1150 }
1151
1152 return status;
1153}
1154
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301155QDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 tSmeCmd *pCommand)
1157{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301158 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159 tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE;
1160 tCsrScanResultFilter *pScanFilter = NULL;
1161 tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
1162 uint32_t sessionId = pCommand->sessionId;
1163
1164 do {
1165 /* If this scan is for LFR */
1166 if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) {
1167 /* notify LFR state m/c */
1168 status = csr_neighbor_roam_sssid_scan_done(pMac,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301169 sessionId, QDF_STATUS_SUCCESS);
1170 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 csr_neighbor_roam_start_lfr_scan(pMac,
1172 sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301173 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 break;
1175 }
1176 /*
1177 * If there is roam command waiting, ignore this roam because
1178 * the newer roam command is the one to execute
1179 */
1180 if (csr_is_roam_command_waiting_for_session(pMac, sessionId)) {
1181 sms_log(pMac, LOGW,
1182 FL("aborts because roam command waiting"));
1183 break;
1184 }
1185 if (pProfile == NULL)
1186 break;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301187 pScanFilter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001188 if (NULL == pScanFilter) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301189 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001190 break;
1191 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301192 qdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193 status = csr_roam_prepare_filter_from_profile(pMac, pProfile,
1194 pScanFilter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301195 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196 break;
1197 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301198 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 break;
kaliu154d7892015-12-30 17:27:58 +05301200 if (pMac->roam.roamSession[sessionId].connectState ==
1201 eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING) {
1202 sms_log(pMac, LOGE,
1203 FL("upper layer issued disconnetion"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301204 status = QDF_STATUS_E_FAILURE;
kaliu154d7892015-12-30 17:27:58 +05301205 break;
1206 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207 status = csr_roam_issue_connect(pMac, sessionId, pProfile,
1208 hBSSList, eCsrHddIssued,
1209 pCommand->u.scanCmd.roamId,
1210 true, true);
1211 } while (0);
1212
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301213 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001214 if (CSR_INVALID_SCANRESULT_HANDLE != hBSSList) {
1215 csr_scan_result_purge(pMac, hBSSList);
1216 }
1217 /* We haven't done anything to this profile */
1218 csr_roam_call_callback(pMac, sessionId, NULL,
1219 pCommand->u.scanCmd.roamId,
1220 eCSR_ROAM_ASSOCIATION_FAILURE,
Abhishek Singhc9941602016-08-09 16:06:22 +05301221 eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222 }
1223 if (pScanFilter) {
1224 csr_free_scan_filter(pMac, pScanFilter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301225 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 }
1227 return status;
1228}
1229
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301230QDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 tSmeCmd *pCommand)
1232{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301233 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 uint32_t sessionId = pCommand->sessionId;
1235 tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
1236 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
1237 eCsrRoamResult roam_result;
1238
1239 if (!pSession) {
1240 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301241 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 }
1243 /* If this scan is for LFR */
1244 if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) {
1245 /* notify LFR state m/c */
1246 status = csr_neighbor_roam_sssid_scan_done(pMac, sessionId,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301247 QDF_STATUS_E_FAILURE);
1248 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 csr_neighbor_roam_start_lfr_scan(pMac, sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301250 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 }
1252#ifdef WLAN_DEBUG
1253 if (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1) {
1254 char str[36];
1255 tSirMacSSid *ptr_ssid =
1256 &pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_copy(str, ptr_ssid->ssId, ptr_ssid->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 str[ptr_ssid->length] = 0;
1259 sms_log(pMac, LOGW, FL("SSID = %s"), str);
1260 }
1261#endif
1262 /*
1263 * Check whether it is for start ibss. No need to do anything if it
1264 * is a JOIN request
1265 */
1266 if (pProfile && CSR_IS_START_IBSS(pProfile)) {
1267 status = csr_roam_issue_connect(pMac, sessionId, pProfile, NULL,
1268 eCsrHddIssued, pCommand->u.scanCmd.roamId,
1269 true, true);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301270 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 sms_log(pMac, LOGE,
1272 FL("failed to issue startIBSS, status: 0x%08X"),
1273 status);
1274 csr_roam_call_callback(pMac, sessionId, NULL,
1275 pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED,
1276 eCSR_ROAM_RESULT_FAILURE);
1277 }
1278 return status;
1279 }
1280 roam_result = eCSR_ROAM_RESULT_FAILURE;
1281 if (NULL != pProfile && csr_is_bss_type_ibss(pProfile->BSSType)) {
1282 roam_result = eCSR_ROAM_RESULT_IBSS_START_FAILED;
1283 goto roam_completion;
1284 }
1285 /* Only indicate assoc_completion if we indicate assoc_start. */
1286 if (pSession->bRefAssocStartCnt > 0) {
1287 tCsrRoamInfo *pRoamInfo = NULL, roamInfo;
1288
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301289 qdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 pRoamInfo = &roamInfo;
1291 if (pCommand->u.roamCmd.pRoamBssEntry) {
1292 tCsrScanResult *pScanResult = GET_BASE_ADDR(
1293 pCommand->u.roamCmd.pRoamBssEntry,
1294 tCsrScanResult, Link);
1295 roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor;
1296 }
1297 roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
1298 roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
1299 pSession->bRefAssocStartCnt--;
1300 csr_roam_call_callback(pMac, sessionId, pRoamInfo,
1301 pCommand->u.scanCmd.roamId,
1302 eCSR_ROAM_ASSOCIATION_COMPLETION,
Abhishek Singhc9941602016-08-09 16:06:22 +05301303 eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001304 } else {
1305 csr_roam_call_callback(pMac, sessionId, NULL,
1306 pCommand->u.scanCmd.roamId,
1307 eCSR_ROAM_ASSOCIATION_FAILURE,
Abhishek Singhc9941602016-08-09 16:06:22 +05301308 eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309 }
1310roam_completion:
1311 csr_roam_completion(pMac, sessionId, NULL, pCommand, roam_result,
1312 false);
1313 return status;
1314}
1315
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301316QDF_STATUS csr_scan_result_purge(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317 tScanResultHandle hScanList)
1318{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301319 QDF_STATUS status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320 tScanResultList *pScanList = (tScanResultList *) hScanList;
1321
1322 if (pScanList) {
1323 status = csr_ll_scan_purge_result(pMac, &pScanList->List);
1324 csr_ll_close(&pScanList->List);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301325 qdf_mem_free(pScanList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 }
1327 return status;
1328}
1329
1330/**
Abhishek Singhc9941602016-08-09 16:06:22 +05301331 * csr_remove_bssid_from_scan_list() - remove the bssid from
1332 * scan list
1333 * @mac_tx: mac context.
1334 * @bssid: bssid to be removed
1335 *
1336 * This function remove the given bssid from scan list.
1337 *
1338 * Return: void.
1339 */
1340void csr_remove_bssid_from_scan_list(tpAniSirGlobal mac_ctx,
1341 tSirMacAddr bssid)
1342{
1343 tListElem *entry, *free_elem;
1344 tCsrScanResult *bss_desc;
1345 tDblLinkList *list = &mac_ctx->scan.scanResultList;
1346
1347 csr_ll_lock(list);
1348 entry = csr_ll_peek_head(list, LL_ACCESS_NOLOCK);
1349 while (entry != NULL) {
1350 bss_desc = GET_BASE_ADDR(entry, tCsrScanResult, Link);
1351 if (!qdf_mem_cmp(bss_desc->Result.BssDescriptor.bssId,
1352 bssid, sizeof(tSirMacAddr))) {
1353 free_elem = entry;
1354 entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
1355 csr_ll_remove_entry(list, free_elem, LL_ACCESS_NOLOCK);
1356 csr_free_scan_result_entry(mac_ctx, bss_desc);
1357 sms_log(mac_ctx, LOGW, FL("Removed BSS entry:%pM"),
1358 bssid);
1359 continue;
1360 }
1361
1362 entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
1363 }
1364
1365 csr_ll_unlock(list);
1366}
1367
1368/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369 * csr_derive_prefer_value_from_rssi() - to derive prefer value
1370 * @mac_ctx: Global MAC Context
1371 * @rssi: RSSI of the BSS
1372 *
1373 * This routine will derive preferred value from given rssi
1374 *
1375 * Return: value between 0 to 14
1376 */
1377static int csr_derive_prefer_value_from_rssi(tpAniSirGlobal mac_ctx, int rssi)
1378{
1379 int i = CSR_NUM_RSSI_CAT - 1, pref_val = 0;
1380 while (i >= 0) {
1381 if (rssi >= mac_ctx->roam.configParam.RSSICat[i]) {
1382 pref_val = mac_ctx->roam.configParam.BssPreferValue[i];
1383 break;
1384 }
1385 i--;
1386 };
1387 return pref_val;
1388}
1389
1390/**
1391 * is_channel_found_in_pcl() - to check if channel is present in pcl
1392 * @mac_ctx: Global MAC Context
1393 * @channel_id: channel of bss
1394 * @filter: pointer to filter created through profile
1395 *
1396 * to check if provided channel is present in pcl
1397 *
1398 * Return: true or false
1399 */
1400static bool is_channel_found_in_pcl(tpAniSirGlobal mac_ctx, int channel_id,
1401 tCsrScanResultFilter *filter)
1402{
1403 int i;
1404 bool status = false;
1405
1406 if (NULL == filter)
1407 return status;
1408
1409 for (i = 0; i < filter->pcl_channels.numChannels; i++) {
1410 if (filter->pcl_channels.channelList[i] == channel_id) {
1411 status = true;
1412 break;
1413 }
1414 }
1415 return status;
1416}
1417/**
1418 * csr_get_altered_rssi() - Artificially increase/decrease RSSI
1419 * @mac_ctx: Global MAC Context pointer.
1420 * @rssi: Actual RSSI of the AP.
1421 * @channel_id: Channel on which the AP is parked.
1422 * @bssid: BSSID of the AP to connect to.
1423 *
1424 * This routine will apply the boost and penalty parameters
1425 * if the channel_id is of 5G band and it will also apply
1426 * the preferred bssid score if there is a match between
1427 * the bssid and the global preferred bssid list.
1428 *
1429 * Return: The modified RSSI Value
1430 */
1431static int csr_get_altered_rssi(tpAniSirGlobal mac_ctx, int rssi,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301432 uint8_t channel_id, struct qdf_mac_addr *bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001433{
1434 int modified_rssi;
1435 int boost_factor;
1436 int penalty_factor;
1437 int i;
1438 struct roam_ext_params *roam_params;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301439 struct qdf_mac_addr fav_bssid;
1440 struct qdf_mac_addr local_bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441
1442 modified_rssi = rssi;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301443 qdf_mem_zero(&local_bssid.bytes, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444 if (bssid)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301445 qdf_mem_copy(local_bssid.bytes, bssid->bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301446 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 roam_params = &mac_ctx->roam.configParam.roam_params;
1448 /*
1449 * If the 5G pref feature is enabled, apply the roaming
1450 * parameters to boost or penalize the rssi.
1451 * Boost Factor = boost_factor * (Actual RSSI - boost Threshold)
1452 * Penalty Factor = penalty factor * (penalty threshold - Actual RSSI)
1453 */
1454 if (CSR_IS_SELECT_5G_PREFERRED(mac_ctx) &&
1455 CDS_IS_CHANNEL_5GHZ(channel_id)) {
1456 if (rssi > roam_params->raise_rssi_thresh_5g) {
1457 /* Check and boost the threshold*/
1458 boost_factor = roam_params->raise_factor_5g *
1459 (rssi - roam_params->raise_rssi_thresh_5g);
1460 /* Check and penalize the threshold */
1461 modified_rssi += CSR_MIN(roam_params->max_raise_rssi_5g,
1462 boost_factor);
1463 } else if (rssi < roam_params->drop_rssi_thresh_5g) {
1464 penalty_factor = roam_params->drop_factor_5g *
1465 (roam_params->drop_rssi_thresh_5g - rssi);
1466 modified_rssi -= CSR_MAX(roam_params->max_drop_rssi_5g,
1467 penalty_factor);
1468 }
1469 sms_log(mac_ctx, LOG2,
1470 FL("5G BSSID"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"),
1471 MAC_ADDR_ARRAY(local_bssid.bytes),
1472 rssi, modified_rssi, channel_id);
1473 }
1474 /*
1475 * Check if there are preferred bssid and then apply the
1476 * preferred score
1477 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301478 qdf_mem_zero(&fav_bssid.bytes, QDF_MAC_ADDR_SIZE);
Varun Reddy Yeturuf76f6de2015-11-17 21:33:53 -08001479 if (bssid && roam_params->num_bssid_favored) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480 for (i = 0; i < roam_params->num_bssid_favored; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301481 qdf_mem_copy(fav_bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 &roam_params->bssid_favored[i],
Anurag Chouhan6d760662016-02-20 16:05:43 +05301483 QDF_MAC_ADDR_SIZE);
Anurag Chouhanc5548422016-02-24 18:33:27 +05301484 if (!qdf_is_macaddr_equal(&fav_bssid, bssid))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485 continue;
1486 modified_rssi += roam_params->bssid_favored_factor[i];
1487 sms_log(mac_ctx, LOG2,
1488 FL("Pref"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"),
1489 MAC_ADDR_ARRAY(local_bssid.bytes),
1490 rssi, modified_rssi, channel_id);
1491 }
1492 }
1493 return modified_rssi;
1494}
1495
1496/**
1497 * csr_get_bss_prefer_value() - Get the preference value for BSS
1498 * @mac_ctx: Global MAC Context
1499 * @rssi: RSSI of the BSS
1500 * @bssid: BSSID to which the preference value is returned
1501 * @channel_id: Channel on which the AP is parked
1502 *
1503 * Each BSS descriptor should be assigned a preference value ranging from
1504 * 14-0, which will be used as an RSSI bucket score while sorting the
1505 * scan results.
1506 *
1507 * Return: Preference value for the BSSID
1508 */
1509static uint32_t csr_get_bss_prefer_value(tpAniSirGlobal mac_ctx, int rssi,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301510 struct qdf_mac_addr *bssid, int channel_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511{
1512 uint32_t ret = 0;
1513 int modified_rssi;
1514
1515 /*
1516 * The RSSI does not get modified in case the 5G
1517 * preference or preferred BSSID is not applicable
1518 */
1519 modified_rssi = csr_get_altered_rssi(mac_ctx, rssi, channel_id, bssid);
1520 ret = csr_derive_prefer_value_from_rssi(mac_ctx, modified_rssi);
1521
1522 return ret;
1523}
1524
1525/* Return a CapValue base on the capabilities of a BSS */
1526static uint32_t csr_get_bss_cap_value(tpAniSirGlobal pMac,
1527 tSirBssDescription *pBssDesc,
1528 tDot11fBeaconIEs *pIes)
1529{
1530 uint32_t ret = CSR_BSS_CAP_VALUE_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001531 if (CSR_IS_ROAM_PREFER_5GHZ(pMac) || CSR_IS_SELECT_5G_PREFERRED(pMac)) {
1532 if ((pBssDesc) && CDS_IS_CHANNEL_5GHZ(pBssDesc->channelId)) {
1533 ret += CSR_BSS_CAP_VALUE_5GHZ;
1534 }
1535 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536 /*
1537 * if strict select 5GHz is non-zero then ignore the capability checking
1538 */
1539 if (pIes && !CSR_IS_SELECT_5GHZ_MARGIN(pMac)) {
1540 /* We only care about 11N capability */
1541 if (pIes->VHTCaps.present)
1542 ret += CSR_BSS_CAP_VALUE_VHT;
1543 else if (pIes->HTCaps.present)
1544 ret += CSR_BSS_CAP_VALUE_HT;
1545 if (CSR_IS_QOS_BSS(pIes)) {
1546 ret += CSR_BSS_CAP_VALUE_WMM;
1547 /* Give advantage to UAPSD */
1548 if (CSR_IS_UAPSD_BSS(pIes)) {
1549 ret += CSR_BSS_CAP_VALUE_UAPSD;
1550 }
1551 }
1552 }
1553
1554 return ret;
1555}
1556
1557/**
1558 * csr_is_better_rssi() - Is bss1 better than bss2
1559 * @mac_ctx: Global MAC Context pointer.
1560 * @bss1: Pointer to the first BSS.
1561 * @bss2: Pointer to the second BSS.
1562 *
1563 * This routine helps in determining the preference value
1564 * of a particular BSS in the scan result which is further
1565 * used in the sorting logic of the final candidate AP's.
1566 *
1567 * Return: true, if bss1 is better than bss2
1568 * false, if bss2 is better than bss1.
1569 */
1570static bool csr_is_better_rssi(tpAniSirGlobal mac_ctx,
1571 tCsrScanResult *bss1, tCsrScanResult *bss2)
1572{
1573 bool ret;
1574 int rssi1, rssi2;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301575 struct qdf_mac_addr local_mac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001576
1577 rssi1 = bss1->Result.BssDescriptor.rssi;
1578 rssi2 = bss2->Result.BssDescriptor.rssi;
1579 /*
1580 * Apply the boost and penlty logic and check
1581 * which is the best RSSI
1582 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301583 qdf_mem_zero(&local_mac.bytes, QDF_MAC_ADDR_SIZE);
1584 qdf_mem_copy(&local_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301585 &bss1->Result.BssDescriptor.bssId, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586 rssi1 = csr_get_altered_rssi(mac_ctx, rssi1,
1587 bss1->Result.BssDescriptor.channelId,
1588 &local_mac);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301589 qdf_mem_copy(&local_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301590 &bss2->Result.BssDescriptor.bssId, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591 rssi2 = csr_get_altered_rssi(mac_ctx, rssi2,
1592 bss2->Result.BssDescriptor.channelId,
1593 &local_mac);
1594 if (CSR_IS_BETTER_RSSI(rssi1, rssi2))
1595 ret = true;
1596 else
1597 ret = false;
1598 return ret;
1599}
1600
1601/**
1602 * csr_is_better_bss() - Is bss1 better than bss2
1603 * @mac_ctx: Global MAC Context pointer.
1604 * @bss1: Pointer to the first BSS.
1605 * @bss2: Pointer to the second BSS.
1606 *
1607 * This routine helps in determining the preference value
1608 * of a particular BSS in the scan result which is further
1609 * used in the sorting logic of the final candidate AP's.
1610 *
1611 * Return: true, if bss1 is better than bss2
1612 * false, if bss2 is better than bss1.
1613 */
1614static bool csr_is_better_bss(tpAniSirGlobal mac_ctx,
1615 tCsrScanResult *bss1, tCsrScanResult *bss2)
1616{
1617 bool ret;
1618
1619 if (CSR_IS_BETTER_PREFER_VALUE(bss1->preferValue, bss2->preferValue)) {
1620 ret = true;
1621 } else if (CSR_IS_EQUAL_PREFER_VALUE
1622 (bss1->preferValue, bss2->preferValue)) {
1623 if (CSR_IS_BETTER_CAP_VALUE(bss1->capValue, bss2->capValue))
1624 ret = true;
1625 else if (CSR_IS_EQUAL_CAP_VALUE
1626 (bss1->capValue, bss2->capValue)) {
1627 if (csr_is_better_rssi(mac_ctx, bss1, bss2))
1628 ret = true;
1629 else
1630 ret = false;
1631 } else {
1632 ret = false;
1633 }
1634 } else {
1635 ret = false;
1636 }
1637
1638 return ret;
1639}
1640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001641/* Add the channel to the occupiedChannels array */
1642static void csr_scan_add_to_occupied_channels(tpAniSirGlobal pMac,
Kapil Gupta0a2477b2016-08-23 18:00:34 +05301643 tCsrScanResult *pResult,
1644 uint8_t sessionId,
1645 tCsrChannel *occupied_ch,
1646 tDot11fBeaconIEs *pIes,
1647 bool is_init_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301649 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 uint8_t ch;
1651 uint8_t num_occupied_ch = occupied_ch->numChannels;
1652 uint8_t *occupied_ch_lst = occupied_ch->channelList;
1653
1654 ch = pResult->Result.BssDescriptor.channelId;
Kapil Gupta0a2477b2016-08-23 18:00:34 +05301655 if (!csr_neighbor_roam_connected_profile_match(pMac,
1656 sessionId, pResult, pIes))
1657 return;
1658
1659 if (is_init_list)
1660 pMac->scan.roam_candidate_count[sessionId]++;
1661
1662 if (csr_is_channel_present_in_list(occupied_ch_lst,
1663 num_occupied_ch, ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 return;
1665
1666 status = csr_add_to_channel_list_front(occupied_ch_lst,
1667 num_occupied_ch, ch);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301668 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001669 occupied_ch->numChannels++;
1670 sms_log(pMac, LOG2,
1671 FL("Added channel %d to the list (count=%d)"),
1672 ch, occupied_ch->numChannels);
1673 if (occupied_ch->numChannels >
1674 CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN)
1675 occupied_ch->numChannels =
1676 CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN;
1677 }
1678}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001679
1680/* Put the BSS into the scan result list */
1681/* pIes can not be NULL */
1682static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult,
1683 tDot11fBeaconIEs *pIes, uint32_t sessionId)
1684{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
1686 &pMac->roam.neighborRoamInfo[sessionId];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001687
Anurag Chouhan6d760662016-02-20 16:05:43 +05301688 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 uint8_t channel_id = pResult->Result.BssDescriptor.channelId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301690 qdf_mem_zero(&bssid.bytes, QDF_MAC_ADDR_SIZE);
1691 qdf_mem_copy(bssid.bytes, &pResult->Result.BssDescriptor.bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301692 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693 pResult->preferValue = csr_get_bss_prefer_value(pMac,
1694 (int)pResult->Result.BssDescriptor.rssi,
1695 &bssid, channel_id);
1696 pResult->capValue = csr_get_bss_cap_value(pMac,
1697 &pResult->Result.BssDescriptor, pIes);
1698 csr_ll_insert_tail(&pMac->scan.scanResultList, &pResult->Link,
1699 LL_ACCESS_LOCK);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001700 if (0 == pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) {
1701 /*
1702 * Build the occupied channel list, only if
1703 * "gNeighborScanChannelList" is NOT set in the cfg.ini file
1704 */
1705 csr_scan_add_to_occupied_channels(pMac, pResult, sessionId,
Kapil Gupta0a2477b2016-08-23 18:00:34 +05301706 &pMac->scan.occupiedChannels[sessionId], pIes,
1707 false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001708 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001709}
1710
1711static void
1712csr_parser_scan_result_for_5ghz_preference(tpAniSirGlobal pMac,
1713 tCsrScanResultFilter *pFilter)
1714{
1715 bool fMatch;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301716 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001717 tListElem *pEntry;
1718 tDot11fBeaconIEs *pIes;
1719 tCsrScanResult *pBssDesc;
1720 uint8_t i = 0;
1721
1722 /* Find out the best AP Rssi going thru the scan results */
1723 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
1724 while (NULL != pEntry) {
1725 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
1726 fMatch = false;
1727
1728 for (i = 0; pFilter && (i < pFilter->SSIDs.numOfSSIDs); i++) {
1729 fMatch = csr_is_ssid_match(pMac,
1730 pFilter->SSIDs.SSIDList[i].SSID.ssId,
1731 pFilter->SSIDs.SSIDList[i].SSID.length,
1732 pBssDesc->Result.ssId.ssId,
1733 pBssDesc->Result.ssId.length, true);
1734 if (!fMatch)
1735 continue;
1736
1737 pIes = (tDot11fBeaconIEs *)(pBssDesc->Result.pvIes);
1738 /* At this time, Result.pvIes may be NULL */
1739 status = csr_get_parsed_bss_description_ies(pMac,
1740 &pBssDesc->Result.BssDescriptor, &pIes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301741 if (!pIes && (!QDF_IS_STATUS_SUCCESS(status)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742 continue;
1743
1744 sms_log(pMac, LOG1, FL("SSID Matched"));
1745 if (pFilter->bOSENAssociation) {
1746 fMatch = true;
1747 sms_log(pMac, LOG1, FL("Security Matched"));
1748 if ((pBssDesc->Result.pvIes == NULL) && pIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301749 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750 continue;
1751 }
1752#ifdef WLAN_FEATURE_11W
1753 fMatch = csr_is_security_match(pMac, &pFilter->authType,
1754 &pFilter->EncryptionType,
1755 &pFilter->mcEncryptionType,
1756 &pFilter->MFPEnabled,
1757 &pFilter->MFPRequired,
1758 &pFilter->MFPCapable,
1759 &pBssDesc->Result.BssDescriptor,
1760 pIes, NULL, NULL, NULL);
1761#else
1762 fMatch = csr_is_security_match(pMac, &pFilter->authType,
1763 &pFilter->EncryptionType,
1764 &pFilter->mcEncryptionType,
1765 NULL, NULL, NULL,
1766 &pBssDesc->Result.BssDescriptor,
1767 pIes, NULL, NULL, NULL);
1768#endif
1769 if ((pBssDesc->Result.pvIes == NULL) && pIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301770 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 if (fMatch)
1772 sms_log(pMac, LOG1, FL("Security Matched"));
1773 } /* for loop ends */
1774
1775 if (fMatch
1776 && (pBssDesc->Result.BssDescriptor.rssi >
1777 pMac->scan.inScanResultBestAPRssi)) {
1778 sms_log(pMac, LOG1,
1779 FL("Best AP Rssi changed from %d to %d"),
1780 pMac->scan.inScanResultBestAPRssi,
1781 pBssDesc->Result.BssDescriptor.rssi);
1782 pMac->scan.inScanResultBestAPRssi =
1783 pBssDesc->Result.BssDescriptor.rssi;
1784 }
1785 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
1786 LL_ACCESS_NOLOCK);
1787 }
1788}
1789
1790static void
1791csr_prefer_5ghz(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter)
1792{
1793 tListElem *pEntry;
1794 tCsrScanResult *pBssDesc;
1795 struct roam_ext_params *roam_params = NULL;
1796
1797 if (!pMac->roam.configParam.nSelect5GHzMargin &&
1798 !CSR_IS_SELECT_5G_PREFERRED(pMac))
1799 return;
1800
1801 pMac->scan.inScanResultBestAPRssi = -128;
1802 roam_params = &pMac->roam.configParam.roam_params;
1803#ifdef WLAN_DEBUG_ROAM_OFFLOAD
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301804 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805 FL("nSelect5GHzMargin"));
1806#endif
1807 csr_ll_lock(&pMac->scan.scanResultList);
1808 /*
1809 * For 5G preference feature, there is no
1810 * need to check the filter match and also re-program the
1811 * RSSI bucket categories, since we use the RSSI values
1812 * while setting the preference value for the BSS.
1813 * There is no need to check the match for roaming since
1814 * it is already done.
1815 */
1816 if (!CSR_IS_SELECT_5G_PREFERRED(pMac))
1817 csr_parser_scan_result_for_5ghz_preference(pMac, pFilter);
1818 if (-128 != pMac->scan.inScanResultBestAPRssi ||
1819 CSR_IS_SELECT_5G_PREFERRED(pMac)) {
1820 sms_log(pMac, LOG1, FL("Best AP Rssi is %d"),
1821 pMac->scan.inScanResultBestAPRssi);
1822 /* Modify Rssi category based on best AP Rssi */
1823 if (-128 != pMac->scan.inScanResultBestAPRssi)
1824 csr_assign_rssi_for_category(pMac,
1825 pMac->scan.inScanResultBestAPRssi,
1826 pMac->roam.configParam.bCatRssiOffset);
1827 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList,
1828 LL_ACCESS_NOLOCK);
1829 while (NULL != pEntry) {
1830 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
1831 /*
1832 * re-assign preference value based on modified
1833 * rssi bucket (or) 5G Preference feature.
1834 */
1835 pBssDesc->preferValue = csr_get_bss_prefer_value(pMac,
1836 (int)pBssDesc->Result.BssDescriptor.rssi,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301837 (struct qdf_mac_addr *)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 &pBssDesc->Result.BssDescriptor.bssId,
1839 pBssDesc->Result.BssDescriptor.channelId);
1840
1841 sms_log(pMac, LOG2, FL("BSSID("MAC_ADDRESS_STR") Rssi(%d) Chnl(%d) PrefVal(%u) SSID=%.*s"),
1842 MAC_ADDR_ARRAY(
1843 pBssDesc->Result.BssDescriptor.bssId),
1844 pBssDesc->Result.BssDescriptor.rssi,
1845 pBssDesc->Result.BssDescriptor.channelId,
1846 pBssDesc->preferValue,
1847 pBssDesc->Result.ssId.length,
1848 pBssDesc->Result.ssId.ssId);
1849 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
1850 LL_ACCESS_NOLOCK);
1851 }
1852 }
1853 csr_ll_unlock(&pMac->scan.scanResultList);
1854}
1855
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301856static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857csr_save_ies(tpAniSirGlobal pMac,
1858 tCsrScanResultFilter *pFilter,
1859 tCsrScanResult *pBssDesc,
1860 tDot11fBeaconIEs **pNewIes,
1861 bool *fMatch,
1862 eCsrEncryptionType *uc,
1863 eCsrEncryptionType *mc,
1864 eCsrAuthType *auth)
1865{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301866 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 tDot11fBeaconIEs *pIes = NULL;
1868
1869 if (!pFilter)
1870 return status;
1871 *fMatch = csr_match_bss(pMac, &pBssDesc->Result.BssDescriptor,
1872 pFilter, auth, uc, mc, &pIes);
1873#ifdef WLAN_DEBUG_ROAM_OFFLOAD
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301874 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 FL("csr_match_bss fmatch %d"), *fMatch);
1876#endif
1877 if (NULL == pIes)
1878 return status;
1879 /* Only save it when matching */
1880 if (!(*fMatch) && !pBssDesc->Result.pvIes) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301881 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 return status;
1883 }
1884 if (!pBssDesc->Result.pvIes) {
1885 /*
1886 * csr_match_bss allocates the memory. Simply pass it and it
1887 * is freed later
1888 */
1889 *pNewIes = pIes;
1890 return status;
1891 }
1892 /*
1893 * The pIes is allocated by someone else. make a copy
1894 * Only to save parsed IEs if caller provides a filter. Most likely the
1895 * caller is using to for association, hence save the parsed IEs
1896 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301897 *pNewIes = qdf_mem_malloc(sizeof(tDot11fBeaconIEs));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 if (NULL == *pNewIes) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301899 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 sms_log(pMac, LOGE, FL("fail to allocate memory for IEs"));
1901 /* Need to free memory allocated by csr_match_bss */
1902 if (!pBssDesc->Result.pvIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301903 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904 return status;
1905 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301906 qdf_mem_copy(*pNewIes, pIes, sizeof(tDot11fBeaconIEs));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907 return status;
1908}
1909
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301910static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911csr_save_scan_entry(tpAniSirGlobal pMac,
1912 tCsrScanResultFilter *pFilter,
1913 bool fMatch,
1914 tCsrScanResult *pBssDesc,
1915 tDot11fBeaconIEs *pNewIes,
1916 tScanResultList *pRetList,
1917 uint32_t *count,
1918 eCsrEncryptionType uc,
1919 eCsrEncryptionType mc,
1920 eCsrAuthType *auth)
1921{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301922 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 tCsrScanResult *pResult;
1924 uint32_t bssLen, allocLen;
1925 /* To sort the list */
1926 tListElem *pTmpEntry;
1927 tCsrScanResult *pTmpResult;
1928
1929 if (!(NULL == pFilter || fMatch))
1930 return status;
1931
1932 bssLen = pBssDesc->Result.BssDescriptor.length +
1933 sizeof(pBssDesc->Result.BssDescriptor.length);
1934 allocLen = sizeof(tCsrScanResult) + bssLen;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301935 pResult = qdf_mem_malloc(allocLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 if (NULL == pResult) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301937 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938 sms_log(pMac, LOGE,
1939 FL("fail to allocate memory for scan result, len=%d"),
1940 allocLen);
1941 if (pNewIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301942 qdf_mem_free(pNewIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 return status;
1944 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301945 qdf_mem_set(pResult, allocLen, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 pResult->capValue = pBssDesc->capValue;
1947 pResult->preferValue = pBssDesc->preferValue;
1948 pResult->ucEncryptionType = uc;
1949 pResult->mcEncryptionType = mc;
1950 pResult->authType = *auth;
1951 pResult->Result.ssId = pBssDesc->Result.ssId;
1952 pResult->Result.timer = pBssDesc->Result.timer;
1953 /* save the pIes for later use */
1954 pResult->Result.pvIes = pNewIes;
1955 /* save bss description */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301956 qdf_mem_copy(&pResult->Result.BssDescriptor,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 &pBssDesc->Result.BssDescriptor,
1958 bssLen);
1959 /*
1960 * No need to lock pRetList because it is locally allocated and no
1961 * outside can access it at this time
1962 */
1963 if (csr_ll_is_list_empty(&pRetList->List, LL_ACCESS_NOLOCK)) {
1964 csr_ll_insert_tail(&pRetList->List, &pResult->Link,
1965 LL_ACCESS_NOLOCK);
1966 (*count)++;
1967 return status;
1968 }
1969
1970 pTmpEntry = csr_ll_peek_head(&pRetList->List, LL_ACCESS_NOLOCK);
1971 while (pTmpEntry) {
1972 pTmpResult = GET_BASE_ADDR(pTmpEntry, tCsrScanResult, Link);
1973 if (csr_is_better_bss(pMac, pResult, pTmpResult)) {
1974 csr_ll_insert_entry(&pRetList->List, pTmpEntry,
1975 &pResult->Link, LL_ACCESS_NOLOCK);
1976 /* To indicate we are done */
1977 pResult = NULL;
1978 break;
1979 }
1980 pTmpEntry = csr_ll_next(&pRetList->List,
1981 pTmpEntry, LL_ACCESS_NOLOCK);
1982 }
1983 if (pResult != NULL) {
1984 /* This one is not better than any one */
1985 csr_ll_insert_tail(&pRetList->List, &pResult->Link,
1986 LL_ACCESS_NOLOCK);
1987 }
1988 (*count)++;
1989 return status;
1990}
1991
1992/**
1993 * csr_calc_pref_val_by_pcl() - to calculate preferred value
1994 * @mac_ctx: mac context
1995 * @filter: filter to find match from scan result
1996 * @bss_descr: pointer to bss descriptor
1997 *
1998 * this routine calculates the new preferred value to be given to
1999 * provided bss if its channel falls under preferred channel list.
2000 * Thump rule is higer the RSSI better the boost.
2001 *
2002 * Return: success or failure
2003 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302004static QDF_STATUS csr_calc_pref_val_by_pcl(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 tCsrScanResultFilter *filter,
2006 tCsrScanResult *bss_descr)
2007{
2008 int temp_rssi = 0, new_pref_val = 0;
2009 int orig_pref_val = 0;
2010
2011 if (NULL == mac_ctx || NULL == bss_descr)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302012 return QDF_STATUS_E_FAILURE;
Krunal Soni35b404c2016-07-14 23:36:00 -07002013 if (filter && (0 != filter->BSSIDs.numOfBSSIDs)) {
2014 sms_log(mac_ctx, LOGW,
2015 FL("filter has specific bssid, no point of boosting"));
2016 return QDF_STATUS_SUCCESS;
2017 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018
Krunal Soni3091bcc2016-06-23 12:28:21 -07002019 if (is_channel_found_in_pcl(mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 bss_descr->Result.BssDescriptor.channelId, filter) &&
2021 (bss_descr->Result.BssDescriptor.rssi > PCL_RSSI_THRESHOLD)) {
2022 orig_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx,
2023 bss_descr->Result.BssDescriptor.rssi);
2024 temp_rssi = bss_descr->Result.BssDescriptor.rssi +
2025 (PCL_ADVANTAGE/(CSR_NUM_RSSI_CAT -
2026 orig_pref_val));
2027 if (temp_rssi > 0)
2028 temp_rssi = 0;
2029 new_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx,
2030 temp_rssi);
2031
2032 sms_log(mac_ctx, LOG1,
2033 FL("%pM: rssi:%d org pref=%d temp rssi:%d new pref=%d pref=%d updated pref=%d"),
2034 bss_descr->Result.BssDescriptor.bssId,
2035 bss_descr->Result.BssDescriptor.rssi,
2036 orig_pref_val, temp_rssi, new_pref_val,
2037 bss_descr->preferValue,
2038 CSR_MAX(new_pref_val, bss_descr->preferValue));
2039
2040 bss_descr->preferValue =
2041 CSR_MAX(new_pref_val, bss_descr->preferValue);
2042 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302043 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044}
2045
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302046static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002047csr_parse_scan_results(tpAniSirGlobal pMac,
2048 tCsrScanResultFilter *pFilter,
2049 tScanResultList *pRetList,
2050 uint32_t *count)
2051{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302052 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 tListElem *pEntry;
2054 bool fMatch = false;
2055 tCsrScanResult *pBssDesc = NULL;
2056 tDot11fBeaconIEs *pIes, *pNewIes = NULL;
2057 eCsrEncryptionType uc, mc;
2058 eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2059 uint32_t len = 0;
2060 enum cds_con_mode new_mode;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05302061 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062
2063
2064 csr_ll_lock(&pMac->scan.scanResultList);
2065
Krunal Soni35b404c2016-07-14 23:36:00 -07002066 if (pFilter && (0 == pFilter->BSSIDs.numOfBSSIDs)) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002067 if (cds_map_concurrency_mode(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068 &pFilter->csrPersona, &new_mode)) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002069 status = cds_get_pcl(new_mode,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302070 &pFilter->pcl_channels.channelList[0], &len,
2071 weight_list, QDF_ARRAY_SIZE(weight_list));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 pFilter->pcl_channels.numChannels = (uint8_t)len;
2073 }
2074 }
2075
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302076 if (QDF_STATUS_E_FAILURE == status)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302077 sms_log(pMac, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 FL("Retrieving pcl failed from HDD"));
2079 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
2080 while (pEntry) {
2081 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2082 pIes = (tDot11fBeaconIEs *) (pBssDesc->Result.pvIes);
2083 /*
2084 * if pBssDesc->Result.pvIes is NULL, we need to free any memory
2085 * allocated by csr_match_bss for any error condition,
2086 * otherwiase, it will be freed later
2087 */
2088 fMatch = false;
2089 pNewIes = NULL;
2090 status = csr_save_ies(pMac, pFilter, pBssDesc, &pNewIes,
2091 &fMatch, &uc, &mc, &auth);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302092 if (!QDF_IS_STATUS_SUCCESS(status)) {
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302093 sms_log(pMac, LOG1, FL("save ies fail %d"),
2094 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 break;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002097 /*
2098 * Modify the prefer value to honor PCL list
2099 */
2100 if (pFilter && pFilter->pcl_channels.numChannels > 0)
2101 csr_calc_pref_val_by_pcl(pMac, pFilter, pBssDesc);
2102 status = csr_save_scan_entry(pMac, pFilter, fMatch, pBssDesc,
2103 pNewIes, pRetList, count, uc, mc,
2104 &auth);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302105 if (!QDF_IS_STATUS_SUCCESS(status)) {
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302106 sms_log(pMac, LOG1, FL("save entry fail %d"),
2107 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002108 break;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302109 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002110 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
2111 LL_ACCESS_NOLOCK);
2112 } /* while */
2113 csr_ll_unlock(&pMac->scan.scanResultList);
2114 return status;
2115}
2116
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302117QDF_STATUS csr_scan_get_result(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002118 tCsrScanResultFilter *pFilter,
2119 tScanResultHandle *phResult)
2120{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302121 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 tScanResultList *pRetList;
2123 uint32_t count = 0;
2124
2125 if (phResult)
2126 *phResult = CSR_INVALID_SCANRESULT_HANDLE;
2127
2128 csr_prefer_5ghz(pMac, pFilter);
2129
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302130 pRetList = qdf_mem_malloc(sizeof(tScanResultList));
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302131 if (NULL == pRetList) {
2132 sms_log(pMac, LOGE, FL("pRetList is NULL"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302133 return QDF_STATUS_E_NOMEM;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302134 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002135
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302136 qdf_mem_set(pRetList, sizeof(tScanResultList), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137 csr_ll_open(pMac->hHdd, &pRetList->List);
2138 pRetList->pCurEntry = NULL;
2139 status = csr_parse_scan_results(pMac, pFilter, pRetList, &count);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05302140 sms_log(pMac, LOG1, FL("return %d BSS %d"),
2141 csr_ll_count(&pRetList->List), status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302142 if (!QDF_IS_STATUS_SUCCESS(status) || (phResult == NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143 /* Fail or No one wants the result. */
2144 csr_scan_result_purge(pMac, (tScanResultHandle) pRetList);
2145 } else {
2146 if (0 == count) {
2147 /* We are here meaning the there is no match */
2148 csr_ll_close(&pRetList->List);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302149 qdf_mem_free(pRetList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302150 status = QDF_STATUS_E_NULL_VALUE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002151 } else if (phResult) {
2152 *phResult = pRetList;
2153 }
2154 }
2155 return status;
2156}
2157
2158/*
2159 * NOTE: This routine is being added to make
2160 * sure that scan results are not being flushed
2161 * while roaming. If the scan results are flushed,
2162 * we are unable to recover from
2163 * csr_roam_roaming_state_disassoc_rsp_processor.
2164 * If it is needed to remove this routine,
2165 * first ensure that we recover gracefully from
2166 * csr_roam_roaming_state_disassoc_rsp_processor if
2167 * csr_scan_get_result returns with a failure because
2168 * of not being able to find the roaming BSS.
2169 */
2170bool csr_scan_flush_denied(tpAniSirGlobal pMac)
2171{
2172 uint8_t sessionId;
2173
2174 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
2175 if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
2176 if (csr_neighbor_middle_of_roaming(pMac, sessionId))
2177 return 1;
2178 }
2179 }
2180 return 0;
2181}
2182
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302183QDF_STATUS csr_scan_flush_result(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184{
2185 bool isFlushDenied = csr_scan_flush_denied(pMac);
2186
2187 if (isFlushDenied) {
2188 sms_log(pMac, LOGW, "%s: scan flush denied in roam state %d",
2189 __func__, isFlushDenied);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302190 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 }
2192
2193 sms_log(pMac, LOG4, "%s: Flushing all scan results", __func__);
2194 csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults);
2195 csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302196 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197}
2198
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302199QDF_STATUS csr_scan_flush_selective_result(tpAniSirGlobal pMac, bool flushP2P)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302201 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 tListElem *pEntry, *pFreeElem;
2203 tCsrScanResult *pBssDesc;
2204 tDblLinkList *pList = &pMac->scan.scanResultList;
2205
2206 csr_ll_lock(pList);
2207
2208 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
2209 while (pEntry != NULL) {
2210 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302211 if (flushP2P != qdf_mem_cmp(pBssDesc->Result.ssId.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 "DIRECT-", 7)) {
2213 pFreeElem = pEntry;
2214 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2215 csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK);
2216 csr_free_scan_result_entry(pMac, pBssDesc);
2217 continue;
2218 }
2219 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2220 }
2221
2222 csr_ll_unlock(pList);
2223
2224 return status;
2225}
2226
2227void csr_scan_flush_bss_entry(tpAniSirGlobal pMac,
2228 tpSmeCsaOffloadInd pCsaOffloadInd)
2229{
2230 tListElem *pEntry, *pFreeElem;
2231 tCsrScanResult *pBssDesc;
2232 tDblLinkList *pList = &pMac->scan.scanResultList;
2233
2234 csr_ll_lock(pList);
2235
2236 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
2237 while (pEntry != NULL) {
2238 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302239 if (!qdf_mem_cmp(pBssDesc->Result.BssDescriptor.bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302240 pCsaOffloadInd->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 pFreeElem = pEntry;
2242 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2243 csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK);
2244 csr_free_scan_result_entry(pMac, pBssDesc);
2245 sms_log(pMac, LOG1, FL("Removed BSS entry:%pM"),
Srinivas Girigowdac9148f72015-11-25 12:42:32 -08002246 pCsaOffloadInd->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 continue;
2248 }
2249
2250 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
2251 }
2252
2253 csr_ll_unlock(pList);
2254}
2255
2256/**
2257 * csr_check11d_channel
2258 *
2259 ***FUNCTION:
2260 * This function is called from csr_scan_filter_results function and
2261 * compare channel number with given channel list.
2262 *
2263 ***LOGIC:
2264 * Check Scan result channel number with CFG channel list
2265 *
2266 ***ASSUMPTIONS:
2267 *
2268 *
2269 ***NOTE:
2270 *
2271 * @param channelId channel number
2272 * @param pChannelList Pointer to channel list
2273 * @param numChannels Number of channel in channel list
2274 *
2275 * @return Status
2276 */
2277
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302278QDF_STATUS csr_check11d_channel(uint8_t channelId, uint8_t *pChannelList,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 uint32_t numChannels)
2280{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302281 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 uint8_t i = 0;
2283
2284 for (i = 0; i < numChannels; i++) {
2285 if (pChannelList[i] == channelId) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302286 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287 break;
2288 }
2289 }
2290 return status;
2291}
2292
2293/**
2294 * csr_scan_filter_results
2295 *
2296 ***FUNCTION:
2297 * This function is called from csr_apply_country_information function and
2298 * filter scan result based on valid channel list number.
2299 *
2300 ***LOGIC:
2301 * Get scan result from scan list and Check Scan result channel number
2302 * with 11d channel list if channel number is found in 11d channel list
2303 * then do not remove scan result entry from scan list
2304 *
2305 ***ASSUMPTIONS:
2306 *
2307 *
2308 ***NOTE:
2309 *
2310 * @param pMac Pointer to Global MAC structure
2311 *
2312 * @return Status
2313 */
2314
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302315QDF_STATUS csr_scan_filter_results(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302317 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318 tListElem *pEntry, *pTempEntry;
2319 tCsrScanResult *pBssDesc;
2320 uint32_t len = sizeof(pMac->roam.validChannelList);
2321
2322 /* Get valid channels list from CFG */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302323 if (!QDF_IS_STATUS_SUCCESS(csr_get_cfg_valid_channels(pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 pMac->roam.
2325 validChannelList,
2326 &len))) {
2327 sms_log(pMac, LOGE, "Failed to get Channel list from CFG");
2328 }
2329
2330 csr_ll_lock(&pMac->scan.scanResultList);
2331 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
2332 while (pEntry) {
2333 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2334 pTempEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
2335 LL_ACCESS_NOLOCK);
2336 if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId,
2337 pMac->roam.validChannelList, len)) {
2338 /* Remove Scan result which does not have 11d channel */
2339 if (csr_ll_remove_entry(&pMac->scan.scanResultList,
2340 pEntry, LL_ACCESS_NOLOCK)) {
2341 csr_free_scan_result_entry(pMac, pBssDesc);
2342 }
2343 } else {
2344 sms_log(pMac, LOG1, FL("%d is a Valid channel"),
2345 pBssDesc->Result.BssDescriptor.channelId);
2346 }
2347 pEntry = pTempEntry;
2348 }
2349
2350 csr_ll_unlock(&pMac->scan.scanResultList);
2351 csr_ll_lock(&pMac->scan.tempScanResults);
2352
2353 pEntry = csr_ll_peek_head(&pMac->scan.tempScanResults,
2354 LL_ACCESS_NOLOCK);
2355 while (pEntry) {
2356 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2357 pTempEntry = csr_ll_next(&pMac->scan.tempScanResults, pEntry,
2358 LL_ACCESS_NOLOCK);
2359 if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId,
2360 pMac->roam.validChannelList, len)) {
2361 /* Remove Scan result which does not have 11d channel */
2362 if (csr_ll_remove_entry
2363 (&pMac->scan.tempScanResults, pEntry,
2364 LL_ACCESS_NOLOCK)) {
2365 csr_free_scan_result_entry(pMac, pBssDesc);
2366 }
2367 } else {
2368 sms_log(pMac, LOG1, FL("%d is a Valid channel"),
2369 pBssDesc->Result.BssDescriptor.channelId);
2370 }
2371 pEntry = pTempEntry;
2372 }
2373
2374 csr_ll_unlock(&pMac->scan.tempScanResults);
2375 return status;
2376}
2377
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302378QDF_STATUS csr_scan_copy_result_list(tpAniSirGlobal pMac, tScanResultHandle hIn,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 tScanResultHandle *phResult)
2380{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302381 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 tScanResultList *pRetList, *pInList = (tScanResultList *) hIn;
2383 tCsrScanResult *pResult, *pScanResult;
2384 uint32_t count = 0;
2385 tListElem *pEntry;
2386 uint32_t bssLen, allocLen;
2387
2388 if (phResult) {
2389 *phResult = CSR_INVALID_SCANRESULT_HANDLE;
2390 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302391 pRetList = qdf_mem_malloc(sizeof(tScanResultList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 if (NULL == pRetList)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302393 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002394 else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302395 qdf_mem_set(pRetList, sizeof(tScanResultList), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 csr_ll_open(pMac->hHdd, &pRetList->List);
2397 pRetList->pCurEntry = NULL;
2398 csr_ll_lock(&pMac->scan.scanResultList);
2399 csr_ll_lock(&pInList->List);
2400
2401 pEntry = csr_ll_peek_head(&pInList->List, LL_ACCESS_NOLOCK);
2402 while (pEntry) {
2403 pScanResult =
2404 GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2405 bssLen =
2406 pScanResult->Result.BssDescriptor.length +
2407 sizeof(pScanResult->Result.BssDescriptor.length);
2408 allocLen = sizeof(tCsrScanResult) + bssLen;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302409 pResult = qdf_mem_malloc(allocLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410 if (NULL == pResult)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302411 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002412 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302413 status = QDF_STATUS_SUCCESS;
2414 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 csr_scan_result_purge(pMac,
2416 (tScanResultHandle *)
2417 pRetList);
2418 count = 0;
2419 break;
2420 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302421 qdf_mem_set(pResult, allocLen, 0);
2422 qdf_mem_copy(&pResult->Result.BssDescriptor,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 &pScanResult->Result.BssDescriptor,
2424 bssLen);
2425 if (pScanResult->Result.pvIes) {
2426 pResult->Result.pvIes =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302427 qdf_mem_malloc(sizeof(tDot11fBeaconIEs));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 if (NULL == pResult->Result.pvIes)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302429 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302431 status = QDF_STATUS_SUCCESS;
2432 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 /* Free the memory we allocate above first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302434 qdf_mem_free(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 csr_scan_result_purge(pMac,
2436 (tScanResultHandle *)
2437 pRetList);
2438 count = 0;
2439 break;
2440 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302441 qdf_mem_copy(pResult->Result.pvIes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 pScanResult->Result.pvIes,
2443 sizeof(tDot11fBeaconIEs));
2444 }
2445 csr_ll_insert_tail(&pRetList->List, &pResult->Link,
2446 LL_ACCESS_LOCK);
2447 count++;
2448 pEntry =
2449 csr_ll_next(&pInList->List, pEntry, LL_ACCESS_NOLOCK);
2450 } /* while */
2451 csr_ll_unlock(&pInList->List);
2452 csr_ll_unlock(&pMac->scan.scanResultList);
2453
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302454 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 if (0 == count) {
2456 csr_ll_close(&pRetList->List);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302457 qdf_mem_free(pRetList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302458 status = QDF_STATUS_E_NULL_VALUE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 } else if (phResult) {
2460 *phResult = pRetList;
2461 }
2462 }
2463 } /* Allocated pRetList */
2464
2465 return status;
2466}
2467
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302468QDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 void *pMsgBuf)
2470{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302471 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 tSirMbMsg *pMsg = (tSirMbMsg *) pMsgBuf;
2473 tCsrRoamSession *pSession;
2474 tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
2475 tCsrRoamInfo roamInfo;
2476 tCsrRoamInfo *pRoamInfo = NULL;
2477 uint32_t sessionId;
2478
2479 if (eWNI_SME_SCAN_RSP == pMsg->type)
2480 return csr_scan_sme_scan_response(pMac, pMsgBuf);
2481
2482 if (pMsg->type != eWNI_SME_UPPER_LAYER_ASSOC_CNF) {
2483 if (csr_is_any_session_in_connect_state(pMac)) {
2484 /*
2485 * In case of we are connected, we need to check whether
2486 * connect status changes because scan may also run
2487 * while connected.
2488 */
2489 csr_roam_check_for_link_status_change(pMac,
2490 (tSirSmeRsp *) pMsgBuf);
2491 } else {
2492 sms_log(pMac, LOGW,
2493 FL("Message [0x%04x] received in wrong state"),
2494 pMsg->type);
2495 }
2496 return status;
2497 }
2498
2499 sms_log(pMac, LOG1,
2500 FL("Scanning: ASSOC cnf can be given to upper layer"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302501 qdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 pRoamInfo = &roamInfo;
2503 pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *) pMsgBuf;
2504 status = csr_roam_get_session_id_from_bssid(pMac,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302505 (struct qdf_mac_addr *)pUpperLayerAssocCnf->bssId, &sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 pSession = CSR_GET_SESSION(pMac, sessionId);
2507
2508 if (!pSession) {
2509 sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302510 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511 }
2512
2513 /* send the status code as Success */
2514 pRoamInfo->statusCode = eSIR_SME_SUCCESS;
2515 pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
2516 pRoamInfo->staId = (uint8_t) pUpperLayerAssocCnf->aid;
2517 pRoamInfo->rsnIELen = (uint8_t) pUpperLayerAssocCnf->rsnIE.length;
2518 pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata;
2519 pRoamInfo->addIELen = (uint8_t) pUpperLayerAssocCnf->addIE.length;
2520 pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302521 qdf_mem_copy(pRoamInfo->peerMac.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 pUpperLayerAssocCnf->peerMacAddr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302523 QDF_MAC_ADDR_SIZE);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302524 qdf_mem_copy(&pRoamInfo->bssid.bytes, pUpperLayerAssocCnf->bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302525 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta;
2527 if (CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile)) {
2528 pMac->roam.roamSession[sessionId].connectState =
2529 eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED;
2530 pRoamInfo->fReassocReq = pUpperLayerAssocCnf->reassocReq;
2531 status = csr_roam_call_callback(pMac, sessionId,
2532 pRoamInfo, 0,
2533 eCSR_ROAM_INFRA_IND,
2534 eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
2535 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 return status;
2537}
2538
2539void csr_check_n_save_wsc_ie(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr,
2540 tSirBssDescription *pOldBssDescr)
2541{
2542 int idx, len;
2543 uint8_t *pbIe;
2544
2545 /* If failed to remove, assuming someone else got it. */
2546 if ((pNewBssDescr->fProbeRsp != pOldBssDescr->fProbeRsp) &&
2547 (0 == pNewBssDescr->WscIeLen)) {
2548 idx = 0;
2549 len = pOldBssDescr->length - sizeof(tSirBssDescription) +
2550 sizeof(uint16_t) + sizeof(uint32_t) -
2551 DOT11F_IE_WSCPROBERES_MIN_LEN - 2;
2552 pbIe = (uint8_t *) pOldBssDescr->ieFields;
2553 /* Save WPS IE if it exists */
2554 pNewBssDescr->WscIeLen = 0;
2555 while (idx < len) {
2556 if ((DOT11F_EID_WSCPROBERES == pbIe[0]) &&
2557 (0x00 == pbIe[2]) && (0x50 == pbIe[3])
2558 && (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) {
2559 /* Founrd it */
2560 if ((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >=
2561 pbIe[1]) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302562 qdf_mem_copy(pNewBssDescr->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 WscIeProbeRsp, pbIe,
2564 pbIe[1] + 2);
2565 pNewBssDescr->WscIeLen = pbIe[1] + 2;
2566 }
2567 break;
2568 }
2569 idx += pbIe[1] + 2;
2570 pbIe += pbIe[1] + 2;
2571 }
2572 }
2573}
2574
2575/* pIes may be NULL */
2576bool csr_remove_dup_bss_description(tpAniSirGlobal pMac,
2577 tSirBssDescription *bss_dscp,
2578 tDot11fBeaconIEs *pIes, tAniSSID *pSsid,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302579 unsigned long *timer, bool fForced)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580{
2581 tListElem *pEntry;
2582 tCsrScanResult *scan_entry;
2583 bool fRC = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584
2585 /*
2586 * Walk through all the chained BssDescriptions. If we find a chained
2587 * BssDescription that matches the BssID of the BssDescription passed
2588 * in, then these must be duplicate scan results for this Bss. In that
2589 * case, remove the 'old' Bss description from the linked list.
2590 */
2591 csr_ll_lock(&pMac->scan.scanResultList);
2592 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
2593
2594 while (pEntry) {
2595 scan_entry = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
2596 /*
2597 * we have a duplicate scan results only when BSSID, SSID,
2598 * Channel and NetworkType matches
2599 */
2600 if (csr_is_duplicate_bss_description(pMac,
2601 &scan_entry->Result.BssDescriptor,
2602 bss_dscp, pIes, fForced)) {
Deepak Dhamdhere652d7e82015-08-06 14:16:53 -07002603 if (bss_dscp->rx_channel == bss_dscp->channelId) {
2604 /*
2605 * Update rssi values only if beacon is
2606 * received on the same channel that was
2607 * sent on.
2608 */
2609 int32_t rssi_new, rssi_old;
2610 const int32_t weight =
2611 CSR_SCAN_RESULT_RSSI_WEIGHT;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002612
Deepak Dhamdhere652d7e82015-08-06 14:16:53 -07002613 rssi_new = (int32_t) bss_dscp->rssi;
2614 rssi_old = (int32_t) scan_entry->
2615 Result.BssDescriptor.rssi;
2616 rssi_new = ((rssi_new * weight) +
2617 rssi_old * (100 - weight)) / 100;
2618 bss_dscp->rssi = (int8_t) rssi_new;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002619
Deepak Dhamdhere652d7e82015-08-06 14:16:53 -07002620 rssi_new = (int32_t) bss_dscp->rssi_raw;
2621 rssi_old = (int32_t) scan_entry->
2622 Result.BssDescriptor.rssi_raw;
2623 rssi_new = ((rssi_new * weight) +
2624 rssi_old * (100 - weight)) / 100;
2625 bss_dscp->rssi_raw = (int8_t) rssi_new;
2626 }
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07002627
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 /* Remove the old entry from the list */
2629 if (csr_ll_remove_entry
2630 (&pMac->scan.scanResultList, pEntry,
2631 LL_ACCESS_NOLOCK)) {
2632 /*
2633 * we need to free the memory associated with
2634 * this node. If failed to remove, assuming
2635 * someone else got it.
2636 */
2637 *pSsid = scan_entry->Result.ssId;
2638 *timer = scan_entry->Result.timer;
2639 csr_check_n_save_wsc_ie(pMac, bss_dscp,
2640 &scan_entry->Result.
2641 BssDescriptor);
2642 csr_free_scan_result_entry(pMac, scan_entry);
2643 } else {
2644 sms_log(pMac, LOGW, FL("fail to remove entry"));
2645 }
2646 fRC = true;
2647 /*
2648 * If we found a match, we can stop looking through
2649 * the list.
2650 */
2651 break;
2652 }
2653 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
2654 LL_ACCESS_NOLOCK);
2655 }
2656
2657 csr_ll_unlock(&pMac->scan.scanResultList);
2658 return fRC;
2659}
2660
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302661QDF_STATUS csr_add_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 tSirBssDescription *pBssDesc,
2663 tDot11fBeaconIEs *pIes)
2664{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302665 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
2667 tPmkidCandidateInfo *pmkid_info = NULL;
2668#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
2669 WLAN_HOST_DIAG_EVENT_DEF(secEvent,
2670 host_event_wlan_security_payload_type);
2671#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
2672 if (!pSession) {
2673 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302674 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 }
2676
2677 sms_log(pMac, LOGW, FL("NumPmkidCandidate = %d"),
2678 pSession->NumPmkidCandidate);
2679 if (!pIes)
2680 return status;
2681 /* check if this is a RSN BSS */
2682 if (!pIes->RSN.present)
2683 return status;
2684
2685 if (pSession->NumPmkidCandidate >= CSR_MAX_PMKID_ALLOWED)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687
2688 /* BSS is capable of doing pre-authentication */
2689#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302690 qdf_mem_set(&secEvent, sizeof(host_event_wlan_security_payload_type),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002691 0);
2692 secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND;
2693 secEvent.encryptionModeMulticast = (uint8_t)diag_enc_type_from_csr_type(
2694 pSession->connectedProfile.mcEncryptionType);
2695 secEvent.encryptionModeUnicast = (uint8_t)diag_enc_type_from_csr_type(
2696 pSession->connectedProfile.EncryptionType);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302697 qdf_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302698 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 secEvent.authMode = (uint8_t)diag_auth_type_from_csr_type(
2700 pSession->connectedProfile.AuthType);
2701 WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
2702#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
2703
2704 pmkid_info = &pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate];
2705 /* if yes, then add to PMKIDCandidateList */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302706 qdf_mem_copy(pmkid_info->BSSID.bytes, pBssDesc->bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302707 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 /* Bit 0 offirst byte - PreAuthentication Capability */
2709 if ((pIes->RSN.RSN_Cap[0] >> 0) & 0x1)
2710 pmkid_info->preAuthSupported = true;
2711 else
2712 pmkid_info->preAuthSupported = false;
2713 pSession->NumPmkidCandidate++;
2714 return status;
2715}
2716
2717/*
2718 * This function checks whether new AP is found for the current connected
2719 * profile. If it is found, it return the sessionId, else it return invalid
2720 * sessionID
2721 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302722QDF_STATUS csr_process_bss_desc_for_pmkid_list(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 tSirBssDescription *pBssDesc,
2724 tDot11fBeaconIEs *pIes,
2725 uint8_t sessionId)
2726{
2727 tCsrRoamSession *pSession;
2728 tDot11fBeaconIEs *pIesLocal = pIes;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302729 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730
2731 if (!(pIesLocal ||
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302732 QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733 csr_get_parsed_bss_description_ies(pMac, pBssDesc,
2734 &pIesLocal))))
2735 return status;
2736
2737 if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
2738 if (!pIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302739 qdf_mem_free(pIesLocal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 return status;
2741 }
2742
2743 pSession = CSR_GET_SESSION(pMac, sessionId);
2744 if (csr_is_conn_state_connected_infra(pMac, sessionId)
2745 && (eCSR_AUTH_TYPE_RSN == pSession->connectedProfile.AuthType)
2746 && csr_match_bss_to_connect_profile(pMac,
2747 &pSession->connectedProfile,
2748 pBssDesc, pIesLocal)) {
2749 /* This new BSS fits the current profile connected */
2750 status = csr_add_pmkid_candidate_list(pMac, sessionId,
2751 pBssDesc, pIesLocal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302752 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753 sms_log(pMac, LOGE,
2754 FL("csr_add_pmkid_candidate_list failed"));
2755 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302756 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002757 }
2758
2759 if (!pIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302760 qdf_mem_free(pIesLocal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761
2762 return status;
2763}
2764
2765#ifdef FEATURE_WLAN_WAPI
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302766QDF_STATUS csr_add_bkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 tSirBssDescription *pBssDesc,
2768 tDot11fBeaconIEs *pIes)
2769{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302770 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002771 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
2772
2773 if (!pSession) {
2774 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302775 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 }
2777
2778 sms_log(pMac, LOGW,
2779 "csr_add_bkid_candidate_list called pMac->scan.NumBkidCandidate = %d",
2780 pSession->NumBkidCandidate);
2781 if (pIes) {
2782 /* check if this is a WAPI BSS */
2783 if (pIes->WAPI.present) {
2784 /* Check if the BSS is capable of doing pre-authentication */
2785 if (pSession->NumBkidCandidate < CSR_MAX_BKID_ALLOWED) {
2786
2787 /* if yes, then add to BKIDCandidateList */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302788 qdf_mem_copy(pSession->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789 BkidCandidateInfo[pSession->
2790 NumBkidCandidate].
2791 BSSID.bytes, pBssDesc->bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05302792 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 if (pIes->WAPI.preauth) {
2794 pSession->BkidCandidateInfo[pSession->
2795 NumBkidCandidate].
2796 preAuthSupported = true;
2797 } else {
2798 pSession->BkidCandidateInfo[pSession->
2799 NumBkidCandidate].
2800 preAuthSupported = false;
2801 }
2802 pSession->NumBkidCandidate++;
2803 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302804 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 }
2806 }
2807 }
2808
2809 return status;
2810}
2811
2812/*
2813 * This function checks whether new AP is found for the current connected
2814 * profile, if so add to BKIDCandidateList
2815 */
2816bool csr_process_bss_desc_for_bkid_list(tpAniSirGlobal pMac,
2817 tSirBssDescription *pBssDesc,
2818 tDot11fBeaconIEs *pIes)
2819{
2820 bool fRC = false;
2821 tDot11fBeaconIEs *pIesLocal = pIes;
2822 uint32_t sessionId;
2823 tCsrRoamSession *pSession;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302824 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825
2826 if (!(pIesLocal ||
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302827 QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 csr_get_parsed_bss_description_ies(pMac, pBssDesc,
2829 &pIesLocal))))
2830 return fRC;
2831
2832 for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
2833 if (!CSR_IS_SESSION_VALID(pMac, sessionId))
2834 continue;
2835 pSession = CSR_GET_SESSION(pMac, sessionId);
2836 if (csr_is_conn_state_connected_infra(pMac, sessionId)
2837 && (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE ==
2838 pSession->connectedProfile.AuthType)
2839 && csr_match_bss_to_connect_profile(pMac,
2840 &pSession->connectedProfile,
2841 pBssDesc, pIesLocal)) {
2842 /* this new BSS fits the current profile connected */
2843 status = csr_add_bkid_candidate_list(pMac, sessionId,
2844 pBssDesc, pIesLocal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302845 if (QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 fRC = true;
2847 }
2848 }
2849 if (!pIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302850 qdf_mem_free(pIesLocal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 return fRC;
2852}
2853
2854#endif
2855
2856static void
2857csr_remove_from_tmp_list(tpAniSirGlobal mac_ctx,
2858 uint8_t reason,
2859 uint8_t session_id)
2860{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302861 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 tListElem *entry;
2863 tCsrScanResult *bss_dscp;
2864 tDot11fBeaconIEs *local_ie = NULL;
2865 bool dup_bss;
2866 tAniSSID tmpSsid;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302867 unsigned long timer = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002868
2869 tmpSsid.length = 0;
2870 while ((entry = csr_ll_remove_tail(&mac_ctx->scan.tempScanResults,
2871 LL_ACCESS_LOCK)) != NULL) {
2872 bss_dscp = GET_BASE_ADDR(entry, tCsrScanResult, Link);
2873 sms_log(mac_ctx, LOG2,
2874 FL("...Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = -%d"),
2875 MAC_ADDR_ARRAY(bss_dscp->Result.BssDescriptor.
2876 bssId),
2877 bss_dscp->Result.BssDescriptor.channelId,
2878 bss_dscp->Result.BssDescriptor.rssi * (-1));
2879
2880 /* At this time, bss_dscp->Result.pvIes may be NULL */
2881 local_ie = (tDot11fBeaconIEs *)(bss_dscp->Result.pvIes);
2882 status = csr_get_parsed_bss_description_ies(mac_ctx,
2883 &bss_dscp->Result.BssDescriptor, &local_ie);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302884 if (!(local_ie || QDF_IS_STATUS_SUCCESS(status))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 sms_log(mac_ctx, LOGE, FL("Cannot pared IEs"));
2886 csr_free_scan_result_entry(mac_ctx, bss_dscp);
2887 continue;
2888 }
2889 dup_bss = csr_remove_dup_bss_description(mac_ctx,
2890 &bss_dscp->Result.BssDescriptor,
2891 local_ie, &tmpSsid, &timer, false);
2892 /*
2893 * Check whether we have reach out limit, but don't lose the
2894 * LFR candidates came from FW
2895 */
2896 if (CSR_SCAN_IS_OVER_BSS_LIMIT(mac_ctx)) {
2897 sms_log(mac_ctx, LOGW, FL("BSS limit reached"));
2898 if ((bss_dscp->Result.pvIes == NULL) && local_ie)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302899 qdf_mem_free(local_ie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 csr_free_scan_result_entry(mac_ctx, bss_dscp);
2901 /* Continue because there may be duplicated BSS */
2902 continue;
2903 }
2904 /* check for duplicate scan results */
2905 if (!dup_bss) {
2906 status = csr_process_bss_desc_for_pmkid_list(mac_ctx,
2907 &bss_dscp->Result.BssDescriptor,
2908 local_ie, session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302909 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 /* Found a new BSS */
2911 csr_roam_call_callback(mac_ctx, session_id,
2912 NULL, 0, eCSR_ROAM_SCAN_FOUND_NEW_BSS,
2913 eCSR_ROAM_RESULT_NONE);
2914 }
2915 } else {
2916 /*
2917 * Check if the new one has SSID it it, if not, use
2918 * the older SSID if it exists.
2919 *
2920 * New BSS has a hidden SSID and old one has the SSID.
2921 * Keep the SSID only if diff of saved SSID time and
2922 * current time is less than 1 min to avoid side effect
2923 * of saving SSID with old one is that if AP changes
2924 * its SSID while remain hidden, we may never see it
2925 * and also to address the requirement of When we remove
2926 * hidden ssid from the profile i.e., forget the SSID
2927 * via GUI that SSID shouldn't see in the profile
2928 */
Anurag Chouhan210db072016-02-22 18:42:15 +05302929 unsigned long time_gap = qdf_mc_timer_get_system_time() -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930 timer;
2931 if ((0 == bss_dscp->Result.ssId.length)
2932 && (time_gap <= HIDDEN_TIMER)
2933 && tmpSsid.length) {
2934 bss_dscp->Result.timer = timer;
2935 bss_dscp->Result.ssId = tmpSsid;
2936 }
2937 }
2938
2939 if (csr_is11d_supported(mac_ctx)
2940 && local_ie->Country.present) {
2941 csr_add_vote_for_country_info(mac_ctx,
2942 local_ie->Country.country);
2943 sms_log(mac_ctx, LOGW,
2944 FL("11d AP Bssid "MAC_ADDRESS_STR
2945 " chan= %d, rssi = -%d, countryCode %c%c"),
2946 MAC_ADDR_ARRAY(
2947 bss_dscp->Result.BssDescriptor.bssId),
2948 bss_dscp->Result.BssDescriptor.channelId,
2949 bss_dscp->Result.BssDescriptor.rssi * (-1),
2950 local_ie->Country.country[0],
2951 local_ie->Country.country[1]);
2952 }
2953 /* append to main list */
2954 csr_scan_add_result(mac_ctx, bss_dscp, local_ie, session_id);
2955 if ((bss_dscp->Result.pvIes == NULL) && local_ie)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302956 qdf_mem_free(local_ie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 } /* end of loop */
2958}
2959
2960static void csr_move_temp_scan_results_to_main_list(tpAniSirGlobal pMac,
2961 uint8_t reason,
2962 uint8_t sessionId)
2963{
2964 tCsrRoamSession *pSession;
2965 uint32_t i;
2966
2967 /* remove the BSS descriptions from temporary list */
2968 csr_remove_from_tmp_list(pMac, reason, sessionId);
2969 /*
2970 * We don't need to update CC while connected to an AP which is
2971 * advertising CC already
2972 */
2973 if (!csr_is11d_supported(pMac))
2974 return;
2975
2976 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
2977 if (!CSR_IS_SESSION_VALID(pMac, i))
2978 continue;
2979 pSession = CSR_GET_SESSION(pMac, i);
2980 if (csr_is_conn_state_connected(pMac, i)) {
2981 sms_log(pMac, LOGW,
2982 FL("No need to update CC in connected state"));
2983 return;
2984 }
2985 }
Agrawal Ashishfb87b162016-05-05 16:31:20 +05302986 if (csr_elected_country_info(pMac))
2987 csr_learn_11dcountry_information(pMac, NULL, NULL, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988}
2989
2990static tCsrScanResult *csr_scan_save_bss_description(tpAniSirGlobal pMac,
2991 tSirBssDescription *
2992 pBSSDescription,
2993 tDot11fBeaconIEs *pIes,
2994 uint8_t sessionId)
2995{
2996 tCsrScanResult *pCsrBssDescription = NULL;
2997 uint32_t cbBSSDesc;
2998 uint32_t cbAllocated;
2999
3000 /* figure out how big the BSS description is (the BSSDesc->length does NOT */
3001 /* include the size of the length field itself). */
3002 cbBSSDesc = pBSSDescription->length + sizeof(pBSSDescription->length);
3003
3004 cbAllocated = sizeof(tCsrScanResult) + cbBSSDesc;
3005
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303006 pCsrBssDescription = qdf_mem_malloc(cbAllocated);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 if (NULL != pCsrBssDescription) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303008 qdf_mem_set(pCsrBssDescription, cbAllocated, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 pCsrBssDescription->AgingCount =
3010 (int32_t) pMac->roam.configParam.agingCount;
3011 sms_log(pMac, LOGW,
3012 FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "),
3013 pCsrBssDescription->AgingCount,
3014 MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.
3015 bssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303016 qdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 pBSSDescription, cbBSSDesc);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303018#if defined(QDF_ENSBALED)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 if (NULL != pCsrBssDescription->Result.pvIes) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303020 QDF_ASSERT(pCsrBssDescription->Result.pvIes == NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 return NULL;
3022 }
3023#endif
3024 csr_scan_add_result(pMac, pCsrBssDescription, pIes, sessionId);
3025 }
3026
3027 return pCsrBssDescription;
3028}
3029
3030/* Append a Bss Description... */
3031tCsrScanResult *csr_scan_append_bss_description(tpAniSirGlobal pMac,
3032 tSirBssDescription *
3033 pSirBssDescription,
3034 tDot11fBeaconIEs *pIes,
3035 bool fForced, uint8_t sessionId)
3036{
3037 tCsrScanResult *pCsrBssDescription = NULL;
3038 tAniSSID tmpSsid;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303039 unsigned long timer = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 int result;
3041
3042 tmpSsid.length = 0;
3043 result = csr_remove_dup_bss_description(pMac, pSirBssDescription,
3044 pIes, &tmpSsid, &timer,
3045 fForced);
3046 pCsrBssDescription = csr_scan_save_bss_description(pMac,
3047 pSirBssDescription, pIes, sessionId);
3048 if (result && (pCsrBssDescription != NULL)) {
3049 /*
3050 * Check if the new one has SSID it it, if not, use the older
3051 * SSID if it exists.
3052 */
3053 if ((0 == pCsrBssDescription->Result.ssId.length)
3054 && tmpSsid.length) {
3055 /*
3056 * New BSS has a hidden SSID and old one has the SSID.
3057 * Keep the SSID only if diff of saved SSID time and
3058 * current time is less than 1 min to avoid side effect
3059 * of saving SSID with old one is that if AP changes its
3060 * SSID while remain hidden, we may never see it and
3061 * also to address the requirement of. When we remove
3062 * hidden ssid from the profile i.e., forget the SSID
3063 * via GUI that SSID shouldn't see in the profile
3064 */
Anurag Chouhan210db072016-02-22 18:42:15 +05303065 if ((qdf_mc_timer_get_system_time() - timer) <=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 HIDDEN_TIMER) {
3067 pCsrBssDescription->Result.ssId = tmpSsid;
3068 pCsrBssDescription->Result.timer = timer;
3069 }
3070 }
3071 }
3072
3073 return pCsrBssDescription;
3074}
3075
3076void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList)
3077{
3078 tCsrChannelPowerInfo *pChannelSet;
3079 tListElem *pEntry;
3080
3081 csr_ll_lock(pChannelList);
3082 /*
3083 * Remove the channel sets from the learned list and put them
3084 * in the free list
3085 */
3086 while ((pEntry = csr_ll_remove_head(pChannelList,
3087 LL_ACCESS_NOLOCK)) != NULL) {
3088 pChannelSet = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link);
3089 if (pChannelSet)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303090 qdf_mem_free(pChannelSet);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003091 }
3092 csr_ll_unlock(pChannelList);
3093 return;
3094}
3095
3096/*
3097 * Save the channelList into the ultimate storage as the final stage of channel
3098 * Input: pCountryInfo -- the country code (e.g. "USI"), channel list, and power
3099 * limit are all stored inside this data structure
3100 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303101QDF_STATUS csr_save_to_channel_power2_g_5_g(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102 uint32_t tableSize,
3103 tSirMacChanInfo *channelTable)
3104{
3105 uint32_t i = tableSize / sizeof(tSirMacChanInfo);
3106 tSirMacChanInfo *pChannelInfo;
3107 tCsrChannelPowerInfo *pChannelSet;
3108 bool f2GHzInfoFound = false;
3109 bool f2GListPurged = false, f5GListPurged = false;
3110
3111 pChannelInfo = channelTable;
3112 /* atleast 3 bytes have to be remaining -- from "countryString" */
3113 while (i--) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303114 pChannelSet = qdf_mem_malloc(sizeof(tCsrChannelPowerInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 if (NULL == pChannelSet) {
3116 pChannelInfo++;
3117 continue;
3118 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303119 qdf_mem_set(pChannelSet, sizeof(tCsrChannelPowerInfo), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 pChannelSet->firstChannel = pChannelInfo->firstChanNum;
3121 pChannelSet->numChannels = pChannelInfo->numChannels;
3122 /*
3123 * Now set the inter-channel offset based on the frequency band
3124 * the channel set lies in
3125 */
3126 if ((CDS_IS_CHANNEL_24GHZ(pChannelSet->firstChannel)) &&
3127 ((pChannelSet->firstChannel +
3128 (pChannelSet->numChannels - 1)) <=
Amar Singhal7a1726a2015-10-14 16:28:11 -07003129 CDS_MAX_24GHZ_CHANNEL_NUMBER)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 pChannelSet->interChannelOffset = 1;
3131 f2GHzInfoFound = true;
3132 } else if ((CDS_IS_CHANNEL_5GHZ(pChannelSet->firstChannel))
3133 && ((pChannelSet->firstChannel +
3134 ((pChannelSet->numChannels - 1) * 4)) <=
Amar Singhal7a1726a2015-10-14 16:28:11 -07003135 CDS_MAX_5GHZ_CHANNEL_NUMBER)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136 pChannelSet->interChannelOffset = 4;
3137 f2GHzInfoFound = false;
3138 } else {
3139 sms_log(pMac, LOGW,
3140 FL("Invalid Channel %d Present in Country IE"),
3141 pChannelSet->firstChannel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303142 qdf_mem_free(pChannelSet);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303143 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303145 pChannelSet->txPower = QDF_MIN(pChannelInfo->maxTxPower,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 pMac->roam.configParam.nTxPowerCap);
3147 if (f2GHzInfoFound) {
3148 if (!f2GListPurged) {
3149 /* purge previous results if found new */
3150 csr_purge_channel_power(pMac,
3151 &pMac->scan.
3152 channelPowerInfoList24);
3153 f2GListPurged = true;
3154 }
3155 if (CSR_IS_OPERATING_BG_BAND(pMac)) {
3156 /* add to the list of 2.4 GHz channel sets */
3157 csr_ll_insert_tail(&pMac->scan.
3158 channelPowerInfoList24,
3159 &pChannelSet->link,
3160 LL_ACCESS_LOCK);
3161 } else {
3162 sms_log(pMac, LOGW,
3163 FL("Adding 11B/G ch in 11A. 1st ch %d"),
3164 pChannelSet->firstChannel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303165 qdf_mem_free(pChannelSet);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 }
3167 } else {
3168 /* 5GHz info found */
3169 if (!f5GListPurged) {
3170 /* purge previous results if found new */
3171 csr_purge_channel_power(pMac,
3172 &pMac->scan.
3173 channelPowerInfoList5G);
3174 f5GListPurged = true;
3175 }
3176 if (CSR_IS_OPERATING_A_BAND(pMac)) {
3177 /* add to the list of 5GHz channel sets */
3178 csr_ll_insert_tail(&pMac->scan.
3179 channelPowerInfoList5G,
3180 &pChannelSet->link,
3181 LL_ACCESS_LOCK);
3182 } else {
3183 sms_log(pMac, LOGW,
3184 FL("Adding 11A ch in B/G. 1st ch %d"),
3185 pChannelSet->firstChannel);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303186 qdf_mem_free(pChannelSet);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187 }
3188 }
3189 pChannelInfo++; /* move to next entry */
3190 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303191 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192}
3193
3194static void csr_clear_dfs_channel_list(tpAniSirGlobal pMac)
3195{
3196 tSirMbMsg *pMsg;
3197 uint16_t msgLen;
3198
3199 msgLen = (uint16_t) (sizeof(tSirMbMsg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303200 pMsg = qdf_mem_malloc(msgLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201 if (NULL != pMsg) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303202 qdf_mem_set((void *)pMsg, msgLen, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 pMsg->type = eWNI_SME_CLEAR_DFS_CHANNEL_LIST;
3204 pMsg->msgLen = msgLen;
3205 cds_send_mb_message_to_mac(pMsg);
3206 }
3207}
3208
3209void csr_apply_power2_current(tpAniSirGlobal pMac)
3210{
3211 sms_log(pMac, LOG3, FL(" Updating Cfg with power settings"));
3212 csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList24,
3213 WNI_CFG_MAX_TX_POWER_2_4);
3214 csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList5G,
3215 WNI_CFG_MAX_TX_POWER_5);
3216}
3217
3218void csr_apply_channel_power_info_to_fw(tpAniSirGlobal mac_ctx,
3219 tCsrChannel *ch_lst,
3220 uint8_t *countryCode)
3221{
3222 int i;
3223 uint8_t num_ch = 0;
3224 uint8_t tempNumChannels = 0;
3225 tCsrChannel tmp_ch_lst;
3226
3227 if (ch_lst->numChannels) {
3228 tempNumChannels = CSR_MIN(ch_lst->numChannels,
3229 WNI_CFG_VALID_CHANNEL_LIST_LEN);
3230 for (i = 0; i < tempNumChannels; i++) {
3231 tmp_ch_lst.channelList[num_ch] = ch_lst->channelList[i];
3232 num_ch++;
3233 }
3234 tmp_ch_lst.numChannels = num_ch;
3235 /* Store the channel+power info in the global place: Cfg */
3236 csr_apply_power2_current(mac_ctx);
3237 csr_set_cfg_valid_channel_list(mac_ctx, tmp_ch_lst.channelList,
3238 tmp_ch_lst.numChannels);
3239 /*
3240 * extend scan capability, build a scan list based on the
3241 * channel list : channel# + active/passive scan
3242 */
3243 csr_set_cfg_scan_control_list(mac_ctx, countryCode,
3244 &tmp_ch_lst);
3245 /* Send msg to Lim to clear DFS channel list */
3246 csr_clear_dfs_channel_list(mac_ctx);
3247 } else {
3248 sms_log(mac_ctx, LOGE, FL("11D channel list is empty"));
3249 }
3250 csr_set_cfg_country_code(mac_ctx, countryCode);
3251}
3252
3253#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3254static void csr_diag_reset_country_information(tpAniSirGlobal pMac)
3255{
3256
3257 host_log_802_11d_pkt_type *p11dLog;
3258 int Index;
3259 WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type,
3260 LOG_WLAN_80211D_C);
3261 if (!p11dLog)
3262 return;
3263
3264 p11dLog->eventId = WLAN_80211D_EVENT_RESET;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303265 qdf_mem_copy(p11dLog->countryCode, pMac->scan.countryCodeCurrent, 3);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 p11dLog->numChannel = pMac->scan.base_channels.numChannels;
3267 if (p11dLog->numChannel <= HOST_LOG_MAX_NUM_CHANNEL) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303268 qdf_mem_copy(p11dLog->Channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003269 pMac->scan.base_channels.channelList,
3270 p11dLog->numChannel);
3271 for (Index = 0;
3272 Index < pMac->scan.base_channels.numChannels;
3273 Index++) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05303274 p11dLog->TxPwr[Index] = QDF_MIN(
Amar Singhala297bfa2015-10-15 15:07:29 -07003275 pMac->scan.defaultPowerTable[Index].power,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 pMac->roam.configParam.nTxPowerCap);
3277 }
3278 }
3279 if (!pMac->roam.configParam.Is11dSupportEnabled)
3280 p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
3281 else
3282 p11dLog->supportMultipleDomain =
3283 WLAN_80211D_SUPPORT_MULTI_DOMAIN;
3284 WLAN_HOST_DIAG_LOG_REPORT(p11dLog);
3285}
3286#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3287
3288/**
3289 * csr_apply_channel_power_info_wrapper() - sends channel info to fw
3290 * @pMac: main MAC data structure
3291 *
3292 * This function sends the channel power info to firmware
3293 *
3294 * Return: none
3295 */
3296void csr_apply_channel_power_info_wrapper(tpAniSirGlobal pMac)
3297{
3298
3299#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3300 csr_diag_reset_country_information(pMac);
3301#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
3302 csr_prune_channel_list_for_mode(pMac, &pMac->scan.base_channels);
3303 csr_save_channel_power_for_band(pMac, false);
3304 csr_save_channel_power_for_band(pMac, true);
3305 /* apply the channel list, power settings, and the country code. */
3306 csr_apply_channel_power_info_to_fw(pMac,
3307 &pMac->scan.base_channels, pMac->scan.countryCodeCurrent);
3308 /* clear the 11d channel list */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303309 qdf_mem_set(&pMac->scan.channels11d, sizeof(pMac->scan.channels11d), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310}
3311
3312void csr_clear_votes_for_country_info(tpAniSirGlobal pMac)
3313{
3314 pMac->scan.countryCodeCount = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303315 qdf_mem_set(pMac->scan.votes11d,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 sizeof(tCsrVotes11d) * CSR_MAX_NUM_COUNTRY_CODE, 0);
3317}
3318
3319void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode)
3320{
3321 bool match = false;
3322 uint8_t i;
3323
3324 /* convert to UPPER here so we are assured
3325 * the strings are always in upper case.
3326 */
3327 for (i = 0; i < 3; i++) {
3328 pCountryCode[i] = (uint8_t) csr_to_upper(pCountryCode[i]);
3329 }
3330
3331 /* Some of the 'old' Cisco 350 series AP's advertise NA as the
3332 * country code (for North America ??). NA is not a valid country code
3333 * or domain so let's allow this by changing it to the proper
3334 * country code (which is US). We've also seen some NETGEAR AP's
3335 * that have "XX " as the country code with valid 2.4 GHz US channel
3336 * information. If we cannot find the country code advertised in the
3337 * 11d information element, let's default to US.
3338 */
3339
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303340 if (!QDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 pCountryCode, NULL,
Amar Singhala297bfa2015-10-15 15:07:29 -07003342 SOURCE_QUERY))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 pCountryCode[0] = '0';
3344 pCountryCode[1] = '0';
3345 }
3346
3347 /* We've seen some of the AP's improperly put a 0 for the
3348 * third character of the country code. spec says valid charcters are
3349 * 'O' (for outdoor), 'I' for Indoor, or ' ' (space; for either).
3350 * if we see a 0 in this third character, let's change it to a ' '.
3351 */
3352 if (0 == pCountryCode[2]) {
3353 pCountryCode[2] = ' ';
3354 }
3355
3356 for (i = 0; i < pMac->scan.countryCodeCount; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303357 match = (!qdf_mem_cmp(pMac->scan.votes11d[i].countryCode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003358 pCountryCode, 2));
3359 if (match) {
3360 break;
3361 }
3362 }
3363
3364 if (match) {
3365 pMac->scan.votes11d[i].votes++;
3366 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303367 qdf_mem_copy(pMac->scan.votes11d[pMac->scan.countryCodeCount].
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 countryCode, pCountryCode, 3);
3369 pMac->scan.votes11d[pMac->scan.countryCodeCount].votes = 1;
3370 pMac->scan.countryCodeCount++;
3371 }
3372
3373 return;
3374}
3375
3376bool csr_elected_country_info(tpAniSirGlobal pMac)
3377{
3378 bool fRet = false;
3379 uint8_t maxVotes = 0;
3380 uint8_t i, j = 0;
3381
3382 if (!pMac->scan.countryCodeCount) {
Agrawal Ashishfb87b162016-05-05 16:31:20 +05303383 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
3384 "No AP with 11d Country code is present in scan list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003385 return fRet;
3386 }
3387 maxVotes = pMac->scan.votes11d[0].votes;
3388 fRet = true;
3389
3390 for (i = 1; i < pMac->scan.countryCodeCount; i++) {
3391 /* If we have a tie for max votes for 2 different country codes,
3392 * pick random.we can put some more intelligence - TBD
3393 */
3394 if (maxVotes < pMac->scan.votes11d[i].votes) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303395 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396 " Votes for Country %c%c : %d\n",
3397 pMac->scan.votes11d[i].countryCode[0],
3398 pMac->scan.votes11d[i].countryCode[1],
3399 pMac->scan.votes11d[i].votes);
3400
3401 maxVotes = pMac->scan.votes11d[i].votes;
3402 j = i;
3403 fRet = true;
3404 }
3405
3406 }
3407 if (fRet) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303408 qdf_mem_copy(pMac->scan.countryCodeElected,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 pMac->scan.votes11d[j].countryCode,
3410 WNI_CFG_COUNTRY_CODE_LEN);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303411 qdf_mem_copy(pMac->scan.countryCode11d,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003412 pMac->scan.votes11d[j].countryCode,
3413 WNI_CFG_COUNTRY_CODE_LEN);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303414 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 "Selected Country is %c%c With count %d\n",
3416 pMac->scan.votes11d[j].countryCode[0],
3417 pMac->scan.votes11d[j].countryCode[1],
3418 pMac->scan.votes11d[j].votes);
3419 }
3420 return fRet;
3421}
3422
3423/**
3424 * csr_set_country_code() - Set country code
3425 * @pMac: main MAC data structure
3426 * @pCountry: ptr to Country Code
3427 *
3428 * This function sends the channel power info to firmware
3429 *
3430 * Return: none
3431 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303432QDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303434 QDF_STATUS status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 v_REGDOMAIN_t domainId;
3436
3437 if (pCountry) {
3438
3439 status = csr_get_regulatory_domain_for_country(pMac, pCountry,
Amar Singhala297bfa2015-10-15 15:07:29 -07003440 &domainId,
3441 SOURCE_USERSPACE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303442 if (QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303443 qdf_mem_copy(pMac->scan.countryCodeCurrent,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444 pCountry,
3445 WNI_CFG_COUNTRY_CODE_LEN);
3446 csr_set_cfg_country_code(pMac, pCountry);
3447 }
3448 }
3449 return status;
3450}
3451
3452/* caller allocated memory for pNumChn and pChnPowerInfo */
3453/* As input, *pNumChn has the size of the array of pChnPowerInfo */
3454/* Upon return, *pNumChn has the number of channels assigned. */
3455void csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list,
3456 uint32_t *num_ch,
Amar Singhala297bfa2015-10-15 15:07:29 -07003457 struct channel_power *chn_pwr_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458{
3459 tListElem *entry;
3460 uint32_t chn_idx = 0, idx;
3461 tCsrChannelPowerInfo *ch_set;
3462
3463 /* Get 2.4Ghz first */
3464 entry = csr_ll_peek_head(list, LL_ACCESS_LOCK);
3465 while (entry && (chn_idx < *num_ch)) {
3466 ch_set = GET_BASE_ADDR(entry, tCsrChannelPowerInfo, link);
3467 for (idx = 0; (idx < ch_set->numChannels)
3468 && (chn_idx < *num_ch); idx++) {
Amar Singhala297bfa2015-10-15 15:07:29 -07003469 chn_pwr_info[chn_idx].chan_num =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 (uint8_t) (ch_set->firstChannel
3471 + (idx * ch_set->interChannelOffset));
Amar Singhala297bfa2015-10-15 15:07:29 -07003472 chn_pwr_info[chn_idx++].power = ch_set->txPower;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 }
3474 entry = csr_ll_next(list, entry, LL_ACCESS_LOCK);
3475 }
3476 *num_ch = chn_idx;
3477
3478 return;
3479}
3480
3481#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3482void csr_diag_apply_country_info(tpAniSirGlobal mac_ctx)
3483{
3484 host_log_802_11d_pkt_type *p11dLog;
Amar Singhala297bfa2015-10-15 15:07:29 -07003485 struct channel_power chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 uint32_t nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp;
3487
3488 WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type,
3489 LOG_WLAN_80211D_C);
3490 if (!p11dLog)
3491 return;
3492
3493 p11dLog->eventId = WLAN_80211D_EVENT_COUNTRY_SET;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303494 qdf_mem_copy(p11dLog->countryCode, mac_ctx->scan.countryCode11d, 3);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 p11dLog->numChannel = mac_ctx->scan.channels11d.numChannels;
3496 if (p11dLog->numChannel > HOST_LOG_MAX_NUM_CHANNEL)
3497 goto diag_end;
3498
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303499 qdf_mem_copy(p11dLog->Channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 mac_ctx->scan.channels11d.channelList,
3501 p11dLog->numChannel);
3502 csr_get_channel_power_info(mac_ctx,
3503 &mac_ctx->scan.channelPowerInfoList24,
3504 &nChnInfo, chnPwrInfo);
3505 nTmp = nChnInfo;
3506 nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN - nTmp;
3507 csr_get_channel_power_info(mac_ctx,
3508 &mac_ctx->scan.channelPowerInfoList5G,
3509 &nChnInfo, &chnPwrInfo[nTmp]);
3510 for (nTmp = 0; nTmp < p11dLog->numChannel; nTmp++) {
3511 for (nChnInfo = 0;
3512 nChnInfo < WNI_CFG_VALID_CHANNEL_LIST_LEN;
3513 nChnInfo++) {
3514 if (p11dLog->Channels[nTmp] ==
Amar Singhala297bfa2015-10-15 15:07:29 -07003515 chnPwrInfo[nChnInfo].chan_num) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 p11dLog->TxPwr[nTmp] =
Amar Singhala297bfa2015-10-15 15:07:29 -07003517 chnPwrInfo[nChnInfo].power;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 break;
3519 }
3520 }
3521 }
3522diag_end:
3523 if (!mac_ctx->roam.configParam.Is11dSupportEnabled)
3524 p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
3525 else
3526 p11dLog->supportMultipleDomain =
3527 WLAN_80211D_SUPPORT_MULTI_DOMAIN;
3528 WLAN_HOST_DIAG_LOG_REPORT(p11dLog);
3529}
3530#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3531
3532/**
3533 * csr_apply_country_information() - apply country code information
3534 * @pMac: core MAC data structure
3535 *
3536 * This function programs the new country code
3537 *
3538 * Return: none
3539 */
3540void csr_apply_country_information(tpAniSirGlobal pMac)
3541{
3542 v_REGDOMAIN_t domainId;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303543 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544
3545 if (!csr_is11d_supported(pMac)
3546 || 0 == pMac->scan.channelOf11dInfo)
3547 return;
3548 status = csr_get_regulatory_domain_for_country(pMac,
Amar Singhala297bfa2015-10-15 15:07:29 -07003549 pMac->scan.countryCode11d, &domainId, SOURCE_QUERY);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303550 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 return;
3552 /* Check whether we need to enforce default domain */
3553#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3554 csr_diag_apply_country_info(pMac);
3555#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3556
3557 if (pMac->scan.domainIdCurrent != domainId)
3558 return;
3559 if (pMac->scan.domainIdCurrent != domainId) {
3560 sms_log(pMac, LOGW, FL("Domain Changed Old %d, new %d"),
3561 pMac->scan.domainIdCurrent, domainId);
3562 status = wma_set_reg_domain(pMac, domainId);
3563 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303564 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565 sms_log(pMac, LOGE, FL("fail to set regId %d"), domainId);
3566 pMac->scan.domainIdCurrent = domainId;
3567 /* switch to active scans using this new channel list */
3568 pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
3569}
3570
3571void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fill_5f)
3572{
3573 uint32_t idx, count = 0;
3574 tSirMacChanInfo *chan_info;
3575 tSirMacChanInfo *ch_info_start;
3576 int32_t max_ch_idx;
3577 bool tmp_bool;
3578 uint8_t ch = 0;
3579
3580 max_ch_idx =
3581 (pMac->scan.base_channels.numChannels <
3582 WNI_CFG_VALID_CHANNEL_LIST_LEN) ?
3583 pMac->scan.base_channels.numChannels :
3584 WNI_CFG_VALID_CHANNEL_LIST_LEN;
3585
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303586 chan_info = qdf_mem_malloc(sizeof(tSirMacChanInfo) *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 WNI_CFG_VALID_CHANNEL_LIST_LEN);
3588 if (NULL == chan_info)
3589 return;
3590
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303591 qdf_mem_set(chan_info, sizeof(tSirMacChanInfo) *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 WNI_CFG_VALID_CHANNEL_LIST_LEN, 0);
3593 ch_info_start = chan_info;
3594 for (idx = 0; idx < max_ch_idx; idx++) {
Amar Singhala297bfa2015-10-15 15:07:29 -07003595 ch = pMac->scan.defaultPowerTable[idx].chan_num;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003596 tmp_bool = (fill_5f && CDS_IS_CHANNEL_5GHZ(ch))
3597 || (!fill_5f && CDS_IS_CHANNEL_24GHZ(ch));
3598 if (!tmp_bool)
3599 continue;
3600
3601 if (count >= WNI_CFG_VALID_CHANNEL_LIST_LEN) {
3602 sms_log(pMac, LOGW, FL("count(%d) exceeded"), count);
3603 break;
3604 }
3605
3606 chan_info->firstChanNum =
Amar Singhala297bfa2015-10-15 15:07:29 -07003607 pMac->scan.defaultPowerTable[idx].chan_num;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608 chan_info->numChannels = 1;
3609 chan_info->maxTxPower =
Anurag Chouhan6d760662016-02-20 16:05:43 +05303610 QDF_MIN(pMac->scan.defaultPowerTable[idx].power,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 pMac->roam.configParam.nTxPowerCap);
3612 chan_info++;
3613 count++;
3614 }
3615 if (count) {
3616 csr_save_to_channel_power2_g_5_g(pMac,
3617 count * sizeof(tSirMacChanInfo), ch_info_start);
3618 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303619 qdf_mem_free(ch_info_start);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620}
3621
3622bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId)
3623{
3624 bool fRet = false;
3625 uint32_t i;
3626
3627 for (i = 0; i < pMac->scan.base_channels.numChannels; i++) {
3628 if (channelId ==
3629 pMac->scan.base_channels.channelList[i]) {
3630 fRet = true;
3631 break;
3632 }
3633 }
3634
3635 return fRet;
3636}
3637
3638/*
3639 * 802.11D only: Gather 11d IE via beacon or Probe response and store them in pAdapter->channels11d
3640 */
3641bool csr_learn_11dcountry_information(tpAniSirGlobal pMac,
3642 tSirBssDescription *pSirBssDesc,
3643 tDot11fBeaconIEs *pIes, bool fForce)
3644{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303645 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 uint8_t *pCountryCodeSelected;
3647 bool fRet = false;
3648 v_REGDOMAIN_t domainId;
3649 tDot11fBeaconIEs *pIesLocal = pIes;
3650 bool useVoting = false;
3651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652 if ((NULL == pSirBssDesc) && (NULL == pIes))
3653 useVoting = true;
3654
3655 /* check if .11d support is enabled */
3656 if (!csr_is11d_supported(pMac))
3657 goto free_ie;
3658
3659 if (false == useVoting) {
3660 if (!pIesLocal &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303661 (!QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 csr_get_parsed_bss_description_ies(
3663 pMac, pSirBssDesc, &pIesLocal))))
3664 goto free_ie;
3665 /* check if country information element is present */
3666 if (!pIesLocal->Country.present)
3667 /* No country info */
3668 goto free_ie;
3669 status = csr_get_regulatory_domain_for_country(pMac,
3670 pIesLocal->Country.country, &domainId,
Amar Singhala297bfa2015-10-15 15:07:29 -07003671 SOURCE_QUERY);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303672 if (QDF_IS_STATUS_SUCCESS(status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 && (domainId == REGDOMAIN_WORLD))
3674 goto free_ie;
3675 } /* useVoting == false */
3676
3677 if (false == useVoting)
3678 pCountryCodeSelected = pIesLocal->Country.country;
3679 else
3680 pCountryCodeSelected = pMac->scan.countryCodeElected;
3681
3682 status = csr_get_regulatory_domain_for_country(pMac,
Amar Singhala297bfa2015-10-15 15:07:29 -07003683 pCountryCodeSelected, &domainId, SOURCE_11D);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303684 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003685 sms_log(pMac, LOGE, FL("fail to get regId %d"), domainId);
3686 fRet = false;
3687 goto free_ie;
3688 }
3689
3690 /* updating 11d Country Code with Country code selected. */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303691 qdf_mem_copy(pMac->scan.countryCode11d, pCountryCodeSelected,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 WNI_CFG_COUNTRY_CODE_LEN);
3693 fRet = true;
3694free_ie:
3695 if (!pIes && pIesLocal) {
3696 /* locally allocated */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303697 qdf_mem_free(pIesLocal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 }
3699 return fRet;
3700}
3701
3702void csr_save_scan_results(tpAniSirGlobal pMac, uint8_t reason,
3703 uint8_t sessionId)
3704{
3705 sms_log(pMac, LOG4, "%s: Saving scan results", __func__);
3706
3707 /* initialize this to false. profMoveInterimScanResultsToMainList() routine */
3708 /* will set this to the channel where an .11d beacon is seen */
3709 pMac->scan.channelOf11dInfo = 0;
3710 /* move the scan results from interim list to the main scan list */
3711 csr_move_temp_scan_results_to_main_list(pMac, reason, sessionId);
3712
3713 /* Now check if we gathered any domain/country specific information */
3714 /* If so, we should update channel list and apply Tx power settings */
3715 if (csr_is11d_supported(pMac)) {
3716 csr_apply_country_information(pMac);
3717 }
3718}
3719
3720void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
3721{
3722 switch (pCommand->u.scanCmd.reason) {
3723 case eCsrScanAbortNormalScan:
3724 default:
3725 csr_scan_free_request(pMac, &pCommand->u.scanCmd.u.scanRequest);
3726 break;
3727 }
3728 if (pCommand->u.scanCmd.pToRoamProfile) {
3729 csr_release_profile(pMac, pCommand->u.scanCmd.pToRoamProfile);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303730 qdf_mem_free(pCommand->u.scanCmd.pToRoamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303732 qdf_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733}
3734
3735eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac,
3736 tSmeCmd *pCommand,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303737 bool fSuccess,
3738 uint8_t *chan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739{
3740 eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303741 int8_t channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742
3743 switch (pCommand->u.scanCmd.reason) {
3744 case eCsrScan11d1:
3745 NextCommand =
3746 (fSuccess) ? eCsrNext11dScan1Success :
3747 eCsrNext11dScan1Failure;
3748 break;
3749 case eCsrScan11d2:
3750 NextCommand =
3751 (fSuccess) ? eCsrNext11dScan2Success :
3752 eCsrNext11dScan2Failure;
3753 break;
3754 case eCsrScan11dDone:
3755 NextCommand = eCsrNext11dScanComplete;
3756 break;
3757 case eCsrScanLostLink1:
3758 NextCommand =
3759 (fSuccess) ? eCsrNextLostLinkScan1Success :
3760 eCsrNextLostLinkScan1Failed;
3761 break;
3762 case eCsrScanLostLink2:
3763 NextCommand =
3764 (fSuccess) ? eCsrNextLostLinkScan2Success :
3765 eCsrNextLostLinkScan2Failed;
3766 break;
3767 case eCsrScanLostLink3:
3768 NextCommand =
3769 (fSuccess) ? eCsrNextLostLinkScan3Success :
3770 eCsrNextLostLinkScan3Failed;
3771 break;
3772 case eCsrScanForSsid:
Krunal Soni3091bcc2016-06-23 12:28:21 -07003773 /* success:
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303774 * set hw_mode success -> csr_scan_handle_search_for_ssid
3775 * set hw_mode fail -> csr_scan_handle_search_for_ssid_failure
3776 * failure: csr_scan_handle_search_for_ssid_failure
3777 */
Krunal Soni3091bcc2016-06-23 12:28:21 -07003778 sms_log(pMac, LOG1, FL("Resp for eCsrScanForSsid"));
3779 channel = cds_search_and_check_for_session_conc(
3780 pCommand->sessionId,
3781 pCommand->u.scanCmd.pToRoamProfile);
3782 if ((!channel) || !fSuccess) {
3783 NextCommand = eCsrNexteScanForSsidFailure;
3784 sms_log(pMac, LOG1,
3785 FL("next ScanForSsidFailure %d %d"),
3786 channel, fSuccess);
3787 } else {
3788 NextCommand = eCsrNextCheckAllowConc;
3789 *chan = channel;
3790 sms_log(pMac, LOG1, FL("next CheckAllowConc"));
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303791 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 break;
3793 default:
3794 NextCommand = eCsrNextScanNothing;
3795 break;
3796 }
3797 return NextCommand;
3798}
3799
3800/* Return whether the pCommand is finished. */
3801bool csr_handle_scan11d1_failure(tpAniSirGlobal pMac, tSmeCmd *pCommand)
3802{
3803 bool fRet = true;
3804
3805 /* Apply back the default setting and passively scan one more time. */
3806 csr_apply_channel_power_info_wrapper(pMac);
3807 pCommand->u.scanCmd.reason = eCsrScan11d2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303808 if (QDF_IS_STATUS_SUCCESS(csr_scan_channels(pMac, pCommand))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809 fRet = false;
3810 }
3811
3812 return fRet;
3813}
3814
3815#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
3816static void
3817csr_diag_scan_complete(tpAniSirGlobal pMac,
3818 tSmeCmd *pCommand,
3819 tSirSmeScanRsp *pScanRsp)
3820{
3821 host_log_scan_pkt_type *pScanLog = NULL;
3822 tScanResultHandle hScanResult;
3823 tCsrScanResultInfo *pScanResult;
3824 tDot11fBeaconIEs *pIes;
3825 int n = 0, c = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303826 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827
3828 WLAN_HOST_DIAG_LOG_ALLOC(pScanLog,
3829 host_log_scan_pkt_type,
3830 LOG_WLAN_SCAN_C);
3831 if (!pScanLog)
3832 return;
3833
3834 if (eCsrScanProbeBss == pCommand->u.scanCmd.reason) {
3835 pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_RSP;
3836 } else {
3837 if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)
3838 pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP;
3839 else
3840 pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP;
3841 }
3842 if (eSIR_SME_SUCCESS != pScanRsp->statusCode) {
3843 pScanLog->status = WLAN_SCAN_STATUS_FAILURE;
3844 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
3845 return;
3846 }
3847
3848 status = csr_scan_get_result(pMac, NULL, &hScanResult);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303849 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
3851 return;
3852 }
3853
3854 pScanResult = csr_scan_result_get_next(pMac, hScanResult);
3855 while (pScanResult != NULL) {
3856 if (n < HOST_LOG_MAX_NUM_BSSID) {
3857 status = csr_get_parsed_bss_description_ies(pMac,
3858 &pScanResult->BssDescriptor, &pIes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303859 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 sms_log(pMac, LOGE, FL("fail to parse IEs"));
3861 break;
3862 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303863 qdf_mem_copy(pScanLog->bssid[n],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 pScanResult->BssDescriptor.bssId, 6);
3865 if (pIes && pIes->SSID.present &&
3866 HOST_LOG_MAX_SSID_SIZE >= pIes->SSID.num_ssid) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303867 qdf_mem_copy(pScanLog->ssid[n],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868 pIes->SSID.ssid,
3869 pIes->SSID.num_ssid);
3870 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303871 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 n++;
3873 }
3874 c++;
3875 pScanResult = csr_scan_result_get_next(pMac, hScanResult);
3876 }
3877 pScanLog->numSsid = (uint8_t) n;
3878 pScanLog->totalSsid = (uint8_t) c;
3879 csr_scan_result_purge(pMac, hScanResult);
3880 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
3881
3882 csr_diag_event_report(pMac, eCSR_EVENT_SCAN_COMPLETE, eSIR_SUCCESS,
3883 eSIR_SUCCESS);
3884 if (c > 0)
3885 csr_diag_event_report(pMac, eCSR_EVENT_SCAN_RES_FOUND,
3886 eSIR_SUCCESS, eSIR_SUCCESS);
3887}
3888#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
3889
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303890/**
3891 * csr_save_profile() - Save the profile info from sme command
3892 * @mac_ctx: Global MAC context
3893 * @save_cmd: Pointer where the command will be saved
3894 * @command: Command from which the profile will be saved
3895 *
3896 * Saves the profile information from the SME's scan command
3897 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303898 * Return: QDF_STATUS
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303899 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303900QDF_STATUS csr_save_profile(tpAniSirGlobal mac_ctx,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303901 tSmeCmd *save_cmd, tSmeCmd *command)
3902{
3903 tCsrScanResult *scan_result;
3904 tCsrScanResult *temp;
3905 uint32_t bss_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303906 QDF_STATUS status;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303907
3908 save_cmd->u.scanCmd.pToRoamProfile =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303909 qdf_mem_malloc(sizeof(tCsrRoamProfile));
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303910 if (!save_cmd->u.scanCmd.pToRoamProfile) {
3911 sms_log(mac_ctx, LOGE, FL("pToRoamProfile mem fail"));
3912 goto error;
3913 }
3914
3915 status = csr_roam_copy_profile(mac_ctx,
3916 save_cmd->u.scanCmd.pToRoamProfile,
3917 command->u.scanCmd.pToRoamProfile);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303918 if (!QDF_IS_STATUS_SUCCESS(status)) {
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303919 sms_log(mac_ctx, LOGE, FL("csr_roam_copy_profile fail"));
3920 goto error;
3921 }
3922
3923 save_cmd->sessionId = command->sessionId;
3924 save_cmd->u.scanCmd.roamId = command->u.scanCmd.roamId;
3925 save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs =
3926 command->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs;
3927 save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303928 qdf_mem_malloc(
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303929 save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs *
3930 sizeof(tCsrSSIDInfo));
3931 if (!save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList) {
3932 sms_log(mac_ctx, LOGE, FL("SSIDList mem fail"));
3933 goto error;
3934 }
3935
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303936 qdf_mem_copy(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303937 command->u.scanCmd.u.scanRequest.SSIDs.SSIDList,
3938 save_cmd->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs *
3939 sizeof(tCsrSSIDInfo));
3940
3941 if (!command->u.roamCmd.pRoamBssEntry)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303942 return QDF_STATUS_SUCCESS;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303943
3944 scan_result = GET_BASE_ADDR(command->u.roamCmd.pRoamBssEntry,
3945 tCsrScanResult, Link);
3946
3947 bss_len = scan_result->Result.BssDescriptor.length +
3948 sizeof(scan_result->Result.BssDescriptor.length);
3949
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303950 temp = qdf_mem_malloc(sizeof(tCsrScanResult) + bss_len);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303951 if (!temp) {
3952 sms_log(mac_ctx, LOGE, FL("bss mem fail"));
3953 goto error;
3954 }
3955
3956 temp->AgingCount = scan_result->AgingCount;
3957 temp->preferValue = scan_result->preferValue;
3958 temp->capValue = scan_result->capValue;
3959 temp->ucEncryptionType = scan_result->ucEncryptionType;
3960 temp->mcEncryptionType = scan_result->mcEncryptionType;
3961 temp->authType = scan_result->authType;
3962 /* pvIes is unsued in success/failure */
3963 temp->Result.pvIes = NULL;
3964
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303965 qdf_mem_copy(temp->Result.pvIes,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303966 scan_result->Result.pvIes,
3967 sizeof(*scan_result->Result.pvIes));
3968 temp->Result.ssId.length = scan_result->Result.ssId.length;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303969 qdf_mem_copy(temp->Result.ssId.ssId,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303970 scan_result->Result.ssId.ssId,
3971 sizeof(scan_result->Result.ssId.ssId));
3972 temp->Result.timer = scan_result->Result.timer;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303973 qdf_mem_copy(&temp->Result.BssDescriptor,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303974 &scan_result->Result.BssDescriptor,
3975 sizeof(temp->Result.BssDescriptor));
3976 temp->Link.last = temp->Link.next = NULL;
3977 save_cmd->u.roamCmd.pRoamBssEntry = (tListElem *)temp;
3978
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303979 return QDF_STATUS_SUCCESS;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303980error:
3981 csr_scan_handle_search_for_ssid_failure(mac_ctx,
3982 command);
3983 if (save_cmd->u.roamCmd.pRoamBssEntry)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303984 qdf_mem_free(save_cmd->u.roamCmd.pRoamBssEntry);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303985 if (save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303986 qdf_mem_free(save_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303987 if (save_cmd->u.scanCmd.pToRoamProfile)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303988 qdf_mem_free(save_cmd->u.scanCmd.pToRoamProfile);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303990 return QDF_STATUS_E_FAILURE;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303991}
3992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993static void
3994csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand,
3995 eCsrScanCompleteNextCommand *nxt_cmd,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05303996 bool *remove_cmd, uint32_t session_id,
3997 uint8_t chan)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303999 QDF_STATUS status, ret;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304000 tSmeCmd *save_cmd = NULL;
4001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 switch (*nxt_cmd) {
4003 case eCsrNext11dScan1Success:
4004 case eCsrNext11dScan2Success:
4005 sms_log(mac_ctx, LOG2,
4006 FL("11dScan1/3 produced results. Reissue Active scan"));
4007 /*
4008 * if we found country information, no need to continue scanning
4009 * further, bail out
4010 */
4011 *remove_cmd = true;
4012 *nxt_cmd = eCsrNext11dScanComplete;
4013 break;
4014 case eCsrNext11dScan1Failure:
4015 /*
4016 * We are not done yet. 11d scan fail once. We will try to reset
4017 * anything and do it over again. The only meaningful thing for
4018 * this retry is that we cannot find 11d information after a
4019 * reset so we clear the "old" 11d info and give it once more
4020 * chance
4021 */
4022 *remove_cmd = csr_handle_scan11d1_failure(mac_ctx, pCommand);
4023 if (*remove_cmd)
4024 *nxt_cmd = eCsrNext11dScanComplete;
4025 break;
4026 case eCsrNextLostLinkScan1Success:
4027 status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
4028 eCsrLostLink1);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304029 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
4031 break;
4032 case eCsrNextLostLinkScan2Success:
4033 status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
4034 eCsrLostLink2);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304035 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
4037 break;
4038 case eCsrNextLostLinkScan3Success:
4039 status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
4040 eCsrLostLink3);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304041 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 csr_scan_handle_failed_lostlink3(mac_ctx, session_id);
4043 break;
4044 case eCsrNextLostLinkScan1Failed:
4045 csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
4046 break;
4047 case eCsrNextLostLinkScan2Failed:
4048 csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
4049 break;
4050 case eCsrNextLostLinkScan3Failed:
4051 csr_scan_handle_failed_lostlink3(mac_ctx, session_id);
4052 break;
4053 case eCsrNexteScanForSsidSuccess:
4054 csr_scan_handle_search_for_ssid(mac_ctx, pCommand);
4055 break;
4056 case eCsrNexteScanForSsidFailure:
4057 csr_scan_handle_search_for_ssid_failure(mac_ctx, pCommand);
4058 break;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304059 case eCsrNextCheckAllowConc:
4060 ret = cds_current_connections_update(pCommand->sessionId,
4061 chan,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05304062 SIR_UPDATE_REASON_HIDDEN_STA);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304063 sms_log(mac_ctx, LOG1, FL("chan: %d session: %d status: %d"),
4064 chan, pCommand->sessionId, ret);
4065 if (mac_ctx->sme.saved_scan_cmd) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304066 qdf_mem_free(mac_ctx->sme.saved_scan_cmd);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304067 mac_ctx->sme.saved_scan_cmd = NULL;
4068 sms_log(mac_ctx, LOGE,
4069 FL("memory should have been free. Check!"));
4070 }
4071
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304072 save_cmd = (tSmeCmd *) qdf_mem_malloc(sizeof(*pCommand));
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304073 if (!save_cmd) {
4074 sms_log(mac_ctx, LOGE, FL("save_cmd mem fail"));
4075 goto error;
4076 }
4077
4078 status = csr_save_profile(mac_ctx, save_cmd, pCommand);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304079 if (!QDF_IS_STATUS_SUCCESS(status)) {
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304080 /* csr_save_profile should report error */
4081 sms_log(mac_ctx, LOGE, FL("profile save failed %d"),
4082 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304083 qdf_mem_free(save_cmd);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304084 return;
4085 }
4086
4087 mac_ctx->sme.saved_scan_cmd = (void *)save_cmd;
4088
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304089 if (QDF_STATUS_E_FAILURE == ret) {
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304090error:
4091 sms_log(mac_ctx, LOGE, FL("conn update fail %d"), chan);
4092 csr_scan_handle_search_for_ssid_failure(mac_ctx,
4093 pCommand);
4094 if (mac_ctx->sme.saved_scan_cmd) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304095 qdf_mem_free(mac_ctx->sme.saved_scan_cmd);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304096 mac_ctx->sme.saved_scan_cmd = NULL;
4097 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304098 } else if ((QDF_STATUS_E_NOSUPPORT == ret) ||
4099 (QDF_STATUS_E_ALREADY == ret)) {
Chandrasekaran, Manishekar78b98262015-11-06 15:22:46 +05304100 sms_log(mac_ctx, LOGE, FL("conn update ret %d"), ret);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304101 csr_scan_handle_search_for_ssid(mac_ctx, pCommand);
4102 if (mac_ctx->sme.saved_scan_cmd) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304103 qdf_mem_free(mac_ctx->sme.saved_scan_cmd);
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304104 mac_ctx->sme.saved_scan_cmd = NULL;
4105 }
4106 }
Chandrasekaran, Manishekar78b98262015-11-06 15:22:46 +05304107 /* Else: Set hw mode was issued and the saved connect would
4108 * be issued after set hw mode response
4109 */
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304110 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 default:
4112 break;
4113 }
4114}
4115
4116/**
4117 * csr_get_active_scan_entry() - To get scan entry from active command list
4118 *
4119 * @mac_ctx - MAC context
4120 * @scan_id - Scan identifier of the scan request
4121 * @entry - scan entry returned.
4122 *
4123 * Scan entry in the active scan list mapping to the sent scan id
4124 * is returned to the caller.
4125 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304126 * Return: QDF_STATUS.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304128QDF_STATUS csr_get_active_scan_entry(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 uint32_t scan_id, tListElem **entry)
4130{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304131 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 tListElem *localentry;
4133 tSmeCmd *cmd;
4134 uint32_t cmd_scan_id = 0;
4135
4136 csr_ll_lock(&mac_ctx->sme.smeScanCmdActiveList);
4137
4138 if (csr_ll_is_list_empty(&mac_ctx->sme.smeScanCmdActiveList,
4139 LL_ACCESS_NOLOCK)) {
4140 sms_log(mac_ctx, LOGE,
4141 FL(" Active list Empty scanId: %d"), scan_id);
Sandeep Puligilla4f1ae702015-11-24 17:19:48 -08004142 csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304143 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 }
4145 localentry = csr_ll_peek_head(&mac_ctx->sme.smeScanCmdActiveList,
4146 LL_ACCESS_NOLOCK);
4147 do {
4148 cmd = GET_BASE_ADDR(localentry, tSmeCmd, Link);
4149 if (cmd->command == eSmeCommandScan)
4150 cmd_scan_id = cmd->u.scanCmd.u.scanRequest.scan_id;
4151 else if (cmd->command == eSmeCommandRemainOnChannel)
4152 cmd_scan_id = cmd->u.remainChlCmd.scan_id;
4153 if (cmd_scan_id == scan_id) {
4154 sms_log(mac_ctx, LOG1, FL(" scanId Matched %d"),
4155 scan_id);
4156 *entry = localentry;
4157 csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304158 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159 }
4160 localentry = csr_ll_next(&mac_ctx->sme.smeScanCmdActiveList,
4161 localentry, LL_ACCESS_NOLOCK);
4162 } while (localentry);
4163 csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
4164 return status;
4165}
4166
4167/* Return whether the command should be removed */
4168bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp)
4169{
4170 eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
4171 tListElem *pEntry = NULL;
4172 tSmeCmd *pCommand;
4173 bool fRemoveCommand = true;
4174 bool fSuccess;
4175 uint32_t sessionId = 0;
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304176 uint8_t chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004177
4178 csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry);
4179 if (!pEntry) {
4180 sms_log(pMac, LOGE,
4181 FL("Scan Completion called but NO cmd ACTIVE ..."));
4182 return false;
4183 }
4184
4185 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
4186 /*
4187 * If the head of the queue is Active and it is a SCAN command, remove
4188 * and put this on the Free queue.
4189 */
4190 if (eSmeCommandScan != pCommand->command) {
4191 sms_log(pMac, LOGW,
4192 FL("Scan Completion called, but active SCAN cmd"));
4193 return false;
4194 }
4195
4196 sessionId = pCommand->sessionId;
4197 if (eSIR_SME_SUCCESS != pScanRsp->statusCode) {
4198 fSuccess = false;
4199 } else {
4200 /*
4201 * pMac->scan.tempScanResults is not empty meaning the scan
4202 * found something. This check only valid here because
4203 * csrSaveScanresults is not yet called
4204 */
4205 fSuccess = (!csr_ll_is_list_empty(&pMac->scan.tempScanResults,
4206 LL_ACCESS_LOCK));
4207 }
4208 if (pCommand->u.scanCmd.abortScanDueToBandChange) {
4209 /*
4210 * Scan aborted due to band change
4211 * The scan results need to be flushed
4212 */
4213 if (pCommand->u.scanCmd.callback
4214 != pMac->scan.callback11dScanDone) {
4215 sms_log(pMac, LOG1, FL("Filtering the scan results"));
4216 csr_scan_filter_results(pMac);
4217 } else {
4218 sms_log(pMac, LOG1,
4219 FL("11d_scan_done, flushing the scan results"));
4220 }
4221 pCommand->u.scanCmd.abortScanDueToBandChange = false;
4222 }
4223 csr_save_scan_results(pMac, pCommand->u.scanCmd.reason, sessionId);
Amar Singhal83a047a2016-05-19 15:56:11 -07004224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
4226 csr_diag_scan_complete(pMac, pCommand, pScanRsp);
4227#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304228 NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess,
4229 &chan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004230 /* We reuse the command here instead reissue a new command */
4231 csr_handle_nxt_cmd(pMac, pCommand, &NextCommand,
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304232 &fRemoveCommand, sessionId, chan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 return fRemoveCommand;
4234}
4235
4236static void
4237csr_scan_remove_dup_bss_description_from_interim_list(tpAniSirGlobal mac_ctx,
4238 tSirBssDescription *bss_dscp,
4239 tDot11fBeaconIEs *pIes)
4240{
4241 tListElem *pEntry;
4242 tCsrScanResult *scan_bss_dscp;
4243 int8_t scan_entry_rssi = 0;
4244 /*
4245 * Walk through all the chained BssDescriptions. If we find a chained
4246 * BssDescription that matches the BssID of the BssDescription passed
4247 * in, then these must be duplicate scan results for this Bss. In that
4248 * case, remove the 'old' Bss description from the linked list.
4249 */
4250 sms_log(mac_ctx, LOG4, FL(" for BSS " MAC_ADDRESS_STR " "),
4251 MAC_ADDR_ARRAY(bss_dscp->bssId));
4252 csr_ll_lock(&mac_ctx->scan.tempScanResults);
4253 pEntry = csr_ll_peek_head(&mac_ctx->scan.tempScanResults,
4254 LL_ACCESS_NOLOCK);
4255 while (pEntry) {
4256 scan_bss_dscp = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4257 /*
4258 * we have a duplicate scan results only when BSSID, SSID,
4259 * Channel and NetworkType matches
4260 */
4261 scan_entry_rssi = scan_bss_dscp->Result.BssDescriptor.rssi;
4262 if (csr_is_duplicate_bss_description(mac_ctx,
4263 &scan_bss_dscp->Result.BssDescriptor, bss_dscp,
4264 pIes, false)) {
4265 /*
4266 * Following is mathematically a = (aX + b(100-X))/100
4267 * where:
4268 * a = bss_dscp->rssi, b = scan_entry_rssi
4269 * and X = CSR_SCAN_RESULT_RSSI_WEIGHT
4270 */
4271 bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi *
4272 CSR_SCAN_RESULT_RSSI_WEIGHT) +
4273 ((int32_t) scan_entry_rssi *
4274 (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100);
4275 /* Remove the 'old' entry from the list */
4276 if (csr_ll_remove_entry(&mac_ctx->scan.tempScanResults,
4277 pEntry, LL_ACCESS_NOLOCK)) {
4278 csr_check_n_save_wsc_ie(mac_ctx, bss_dscp,
4279 &scan_bss_dscp->Result.
4280 BssDescriptor);
4281 /*
4282 * we need to free the memory associated with
4283 * this node
4284 */
4285 csr_free_scan_result_entry(mac_ctx,
4286 scan_bss_dscp);
4287 }
4288 /*
4289 * If we found a match, we can stop looking through
4290 * the list.
4291 */
4292 break;
4293 }
4294 pEntry = csr_ll_next(&mac_ctx->scan.tempScanResults, pEntry,
4295 LL_ACCESS_NOLOCK);
4296 }
4297
4298 csr_ll_unlock(&mac_ctx->scan.tempScanResults);
4299}
4300
4301/* Caller allocated memory pfNewBssForConn to return whether new candidate for */
4302/* current connection is found. Cannot be NULL */
4303tCsrScanResult *csr_scan_save_bss_description_to_interim_list(tpAniSirGlobal pMac,
4304 tSirBssDescription *
4305 pBSSDescription,
4306 tDot11fBeaconIEs *pIes)
4307{
4308 tCsrScanResult *pCsrBssDescription = NULL;
4309 uint32_t cbBSSDesc;
4310 uint32_t cbAllocated;
4311
4312 /* figure out how big the BSS description is (the BSSDesc->length does NOT */
4313 /* include the size of the length field itself). */
4314 cbBSSDesc = pBSSDescription->length + sizeof(pBSSDescription->length);
4315
4316 cbAllocated = sizeof(tCsrScanResult) + cbBSSDesc;
4317
4318 sms_log(pMac, LOG4, FL("new BSS description, length %d, cbBSSDesc %d"),
4319 cbAllocated, cbBSSDesc);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304320 pCsrBssDescription = qdf_mem_malloc(cbAllocated);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004321 if (NULL != pCsrBssDescription) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304322 qdf_mem_set(pCsrBssDescription, cbAllocated, 0);
4323 qdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 pBSSDescription, cbBSSDesc);
4325 pCsrBssDescription->AgingCount =
4326 (int32_t) pMac->roam.configParam.agingCount;
4327 sms_log(pMac, LOG4,
4328 FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "),
4329 pCsrBssDescription->AgingCount,
4330 MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.
4331 bssId));
4332 /* Save SSID separately for later use */
4333 if (pIes->SSID.present
4334 && !csr_is_nullssid(pIes->SSID.ssid, pIes->SSID.num_ssid)) {
4335 /* SSID not hidden */
4336 uint32_t len = pIes->SSID.num_ssid;
4337 if (len > SIR_MAC_MAX_SSID_LENGTH) {
4338 /* truncate to fit in our struct */
4339 len = SIR_MAC_MAX_SSID_LENGTH;
4340 }
4341 pCsrBssDescription->Result.ssId.length = len;
4342 pCsrBssDescription->Result.timer =
Anurag Chouhan210db072016-02-22 18:42:15 +05304343 qdf_mc_timer_get_system_time();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304344 qdf_mem_copy(pCsrBssDescription->Result.ssId.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 pIes->SSID.ssid, len);
4346 }
4347 csr_ll_insert_tail(&pMac->scan.tempScanResults,
4348 &pCsrBssDescription->Link, LL_ACCESS_LOCK);
4349 }
4350
4351 return pCsrBssDescription;
4352}
4353
4354bool csr_is_duplicate_bss_description(tpAniSirGlobal pMac,
4355 tSirBssDescription *pSirBssDesc1,
4356 tSirBssDescription *pSirBssDesc2,
4357 tDot11fBeaconIEs *pIes2, bool fForced)
4358{
4359 bool fMatch = false;
4360 tSirMacCapabilityInfo *pCap1, *pCap2;
4361 tDot11fBeaconIEs *pIes1 = NULL;
4362 tDot11fBeaconIEs *pIesTemp = pIes2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304363 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364
4365 pCap1 = (tSirMacCapabilityInfo *) &pSirBssDesc1->capabilityInfo;
4366 pCap2 = (tSirMacCapabilityInfo *) &pSirBssDesc2->capabilityInfo;
4367
4368 if (pCap1->ess != pCap2->ess)
4369 goto free_ies;
4370
4371 if (pCap1->ess &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05304372 qdf_is_macaddr_equal((struct qdf_mac_addr *) pSirBssDesc1->bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304373 (struct qdf_mac_addr *) pSirBssDesc2->bssId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 && (fForced
4375 || (cds_chan_to_band(pSirBssDesc1->channelId) ==
4376 cds_chan_to_band((pSirBssDesc2->channelId))))) {
4377 fMatch = true;
4378 /* Check for SSID match, if exists */
4379 status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1,
4380 &pIes1);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304381 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 goto free_ies;
4383
4384 if (NULL == pIesTemp) {
4385 status = csr_get_parsed_bss_description_ies(pMac,
4386 pSirBssDesc2, &pIesTemp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304387 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 goto free_ies;
4389 }
4390 if (pIes1->SSID.present && pIesTemp->SSID.present) {
4391 fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid,
4392 pIes1->SSID.num_ssid,
4393 pIesTemp->SSID.ssid,
4394 pIesTemp->SSID.num_ssid,
4395 true);
4396 }
4397 } else if (pCap1->ibss && (pSirBssDesc1->channelId ==
4398 pSirBssDesc2->channelId)) {
4399 status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1,
4400 &pIes1);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304401 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402 goto free_ies;
4403
4404 if (NULL == pIesTemp) {
4405 status = csr_get_parsed_bss_description_ies(pMac,
4406 pSirBssDesc2, &pIesTemp);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304407 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 goto free_ies;
4409 }
4410
4411 /* Same channel cannot have same SSID for different IBSS */
4412 if (pIes1->SSID.present && pIesTemp->SSID.present) {
4413 fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid,
4414 pIes1->SSID.num_ssid,
4415 pIesTemp->SSID.ssid,
4416 pIesTemp->SSID.num_ssid,
4417 true);
4418 }
4419 }
4420 /* In case of P2P devices, ess and ibss will be set to zero */
4421 else if (!pCap1->ess &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05304422 qdf_is_macaddr_equal(
Anurag Chouhan6d760662016-02-20 16:05:43 +05304423 (struct qdf_mac_addr *) pSirBssDesc1->bssId,
4424 (struct qdf_mac_addr *) pSirBssDesc2->bssId)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 fMatch = true;
4426 }
4427
4428free_ies:
4429 if (pIes1)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304430 qdf_mem_free(pIes1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431 if ((NULL == pIes2) && pIesTemp)
4432 /* locally allocated */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304433 qdf_mem_free(pIesTemp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434 return fMatch;
4435}
4436
4437bool csr_is_network_type_equal(tSirBssDescription *pSirBssDesc1,
4438 tSirBssDescription *pSirBssDesc2)
4439{
4440 return pSirBssDesc1->nwType == pSirBssDesc2->nwType;
4441}
4442
4443/* to check whether the BSS matches the dot11Mode */
4444static bool csr_scan_is_bss_allowed(tpAniSirGlobal pMac,
4445 tSirBssDescription *pBssDesc,
4446 tDot11fBeaconIEs *pIes)
4447{
4448 bool fAllowed = false;
4449 eCsrPhyMode phyMode;
4450
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304451 if (QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004452 (csr_get_phy_mode_from_bss(pMac, pBssDesc, &phyMode, pIes))) {
4453 switch (pMac->roam.configParam.phyMode) {
4454 case eCSR_DOT11_MODE_11b:
4455 fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode);
4456 break;
4457 case eCSR_DOT11_MODE_11g:
4458 fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode);
4459 break;
4460 case eCSR_DOT11_MODE_11g_ONLY:
4461 fAllowed = (bool) (eCSR_DOT11_MODE_11g == phyMode);
4462 break;
4463 case eCSR_DOT11_MODE_11a:
4464 fAllowed = (bool) ((eCSR_DOT11_MODE_11b != phyMode)
4465 && (eCSR_DOT11_MODE_11g != phyMode));
4466 break;
4467 case eCSR_DOT11_MODE_11n_ONLY:
4468 fAllowed = (bool) ((eCSR_DOT11_MODE_11n == phyMode));
4469 break;
4470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004471 case eCSR_DOT11_MODE_11ac_ONLY:
4472 fAllowed = (bool) ((eCSR_DOT11_MODE_11ac == phyMode));
4473 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 case eCSR_DOT11_MODE_11b_ONLY:
4475 fAllowed = (bool) (eCSR_DOT11_MODE_11b == phyMode);
4476 break;
4477 case eCSR_DOT11_MODE_11n:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478 case eCSR_DOT11_MODE_11ac:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 default:
4480 fAllowed = true;
4481 break;
4482 }
4483 }
4484
4485 return fAllowed;
4486}
4487
4488/* Return pIes to caller for future use when returning true. */
4489static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac,
4490 uint8_t *pChannels,
4491 uint8_t numChn,
4492 tSirBssDescription *pBssDesc,
4493 tDot11fBeaconIEs **ppIes)
4494{
4495 bool valid = false;
4496 tDot11fBeaconIEs *pIes = NULL;
4497 uint8_t index;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304498 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499
4500 for (index = 0; index < numChn; index++) {
4501 /*
4502 * This check relies on the fact that a single BSS description
4503 * is returned in each ScanRsp call, which is the way LIM
4504 * implemented the scan req/rsp funtions. We changed to this
4505 * model when we ran with a large number of APs. If this were to
4506 * change, then this check would have to mess with removing the
4507 * bssDescription from somewhere in an arbitrary index in the
4508 * bssDescription array.
4509 */
4510 if (pChannels[index] == pBssDesc->channelId) {
4511 valid = true;
4512 break;
4513 }
4514 }
4515 *ppIes = NULL;
4516 if (valid) {
4517 status = csr_get_parsed_bss_description_ies(pMac, pBssDesc,
4518 &pIes);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304519 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004520 return false;
4521
4522 valid = csr_scan_is_bss_allowed(pMac, pBssDesc, pIes);
4523 if (valid)
4524 *ppIes = pIes;
4525 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304526 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 }
4528 return valid;
4529}
4530
4531static void csr_update_scantype(tpAniSirGlobal pMac, tDot11fBeaconIEs *pIes,
4532 uint8_t channelId)
4533{
4534 if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)
4535 return;
4536
4537 if (csr_is11d_supported(pMac)) {
4538 /* Check whether the BSS is acceptable based on
4539 * 11d info and our config.
4540 */
4541 if (!csr_match_country_code(pMac, NULL, pIes))
4542 return;
4543
4544 /* check if channel is acceptable by config */
4545 if (csr_is_supported_channel(pMac, channelId))
4546 pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
4547
4548 } else
4549 pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
4550
4551}
4552
4553/* Return whether last scan result is received */
4554static bool csr_scan_process_scan_results(tpAniSirGlobal pMac, tSmeCmd *pCommand,
4555 tSirSmeScanRsp *pScanRsp,
4556 bool *pfRemoveCommand)
4557{
4558 bool fRet = false, fRemoveCommand = false;
Amar Singhal83a047a2016-05-19 15:56:11 -07004559 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004560
4561 sms_log(pMac, LOG1, FL("scan reason = %d, response status code = %d"),
4562 pCommand->u.scanCmd.reason, pScanRsp->statusCode);
4563 fRemoveCommand = csr_scan_complete(pMac, pScanRsp);
4564 fRet = true;
4565 if (pfRemoveCommand) {
4566 *pfRemoveCommand = fRemoveCommand;
4567 }
Amar Singhal83a047a2016-05-19 15:56:11 -07004568
4569 /*
4570 * Currently SET_FCC_CHANNEL issues updated channel list to fw.
4571 * At the time of driver load, if scan is issued followed with
4572 * SET_FCC_CHANNEL, driver will send update channel list to fw.
4573 * Fw will stop ongoing scan because of that GUI will have very less
4574 * scan list.
4575 * Update channel list should be sent to fw once scan is done
4576 */
4577 if (pMac->scan.defer_update_channel_list) {
4578 status = csr_update_channel_list(pMac);
4579 if (!QDF_IS_STATUS_SUCCESS(status))
4580 sms_log(pMac, LOGE,
4581 FL("failed to update the supported channel list"));
4582 pMac->scan.defer_update_channel_list = false;
4583 }
4584
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 return fRet;
4586}
4587
4588/* csr_scan_process_single_bssdescr() - Add a bssdescriptor to scan table
4589 *
4590 * @mac_ctx - MAC context
4591 * @bssdescr - Pointer to BSS description structure that contains
4592 * everything from beacon/probe response frame and additional
4593 * information.
4594 * @scan_id - Scan identifier of the scan request that was running
4595 * when this beacon was received. Reserved for future when
4596 * firmware provides that information.
4597 * @flags - Reserved for future use.
4598 *
4599 * Callback routine called by LIM when it receives a beacon or probe response
4600 * from the device. 802.11 frame is already converted to internal
4601 * tSirBssDescription data structure.
4602 *
4603 * Return: 0 or other error codes.
4604 */
4605
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304606QDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 tSirBssDescription *bssdescr,
4608 uint32_t scan_id, uint32_t flags)
4609{
4610 tDot11fBeaconIEs *ies = NULL;
4611 uint8_t *chanlist = NULL;
4612 uint8_t cnt_channels = 0;
4613 uint32_t len = sizeof(mac_ctx->roam.validChannelList);
4614
4615 sms_log(mac_ctx, LOG4, "CSR: Processing single bssdescr");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304616 if (QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617 csr_get_cfg_valid_channels(mac_ctx,
4618 (uint8_t *) mac_ctx->roam.validChannelList,
4619 &len))) {
4620 chanlist = mac_ctx->roam.validChannelList;
4621 cnt_channels = (uint8_t) len;
4622 } else {
4623 /* Cannot continue */
4624 sms_log(mac_ctx, LOGW,
4625 FL("Received results on invalid channel"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304626 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 }
4628
4629 if (csr_scan_validate_scan_result(mac_ctx, chanlist,
4630 cnt_channels, bssdescr, &ies)) {
4631 csr_scan_remove_dup_bss_description_from_interim_list
4632 (mac_ctx, bssdescr, ies);
4633 csr_scan_save_bss_description_to_interim_list
4634 (mac_ctx, bssdescr, ies);
4635 csr_update_scantype(mac_ctx, ies, bssdescr->channelId);
4636 /* Free the resource */
4637 if (ies != NULL)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304638 qdf_mem_free(ies);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304640 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004641}
4642
4643
4644bool csr_scan_is_wild_card_scan(tpAniSirGlobal pMac, tSmeCmd *pCommand)
4645{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304646 uint8_t bssid[QDF_MAC_ADDR_SIZE] = {0};
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304647 bool f = qdf_mem_cmp(pCommand->u.scanCmd.u.scanRequest.bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304648 bssid, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 /*
4650 * It is not a wild card scan if the bssid is not broadcast and
4651 * the number of SSID is 1.
4652 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304653 return ((!f) || (0xff == pCommand->u.scanCmd.u.scanRequest.bssid.bytes[0]))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 && (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs != 1);
4655}
4656
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304657QDF_STATUS csr_scan_sme_scan_response(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 void *pMsgBuf)
4659{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304660 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661 tListElem *pEntry = NULL;
4662 tSmeCmd *pCommand;
4663 eCsrScanStatus scanStatus;
4664 tSirSmeScanRsp *pScanRsp = (tSirSmeScanRsp *)pMsgBuf;
4665 bool fRemoveCommand = true;
4666 eCsrScanReason reason = eCsrScanOther;
4667
4668 csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry);
4669 if (!pEntry)
4670 goto error_handling;
4671
4672 sms_log(pMac, LOG1, FL("Scan completion called:scan_id %d, entry = %p"),
4673 pScanRsp->scan_id, pEntry);
4674
4675 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
4676 if (eSmeCommandScan != pCommand->command)
4677 goto error_handling;
4678
4679 scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ?
4680 eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE;
4681 reason = pCommand->u.scanCmd.reason;
4682 switch (pCommand->u.scanCmd.reason) {
4683 case eCsrScanAbortNormalScan:
4684 break;
4685 case eCsrScanP2PFindPeer:
4686 scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ?
4687 eCSR_SCAN_FOUND_PEER : eCSR_SCAN_FAILURE;
4688 csr_scan_process_scan_results(pMac, pCommand, pScanRsp, NULL);
4689 break;
4690 default:
4691 if (csr_scan_process_scan_results(pMac, pCommand, pScanRsp,
4692 &fRemoveCommand)
4693 && csr_scan_is_wild_card_scan(pMac, pCommand)
4694 && !pCommand->u.scanCmd.u.scanRequest.p2pSearch) {
4695
4696 /* Age out logic will be taken care by the age out timer */
4697 }
4698 break;
4699 }
4700 if (fRemoveCommand)
4701 csr_release_scan_command(pMac, pCommand, scanStatus);
4702 sme_process_pending_queue(pMac);
4703 return status;
4704
4705error_handling:
4706#ifdef FEATURE_WLAN_SCAN_PNO
4707 if (pMac->pnoOffload && pScanRsp->statusCode == eSIR_PNO_SCAN_SUCCESS) {
Sandeep Puligilla707386e2016-05-31 15:48:37 -07004708 sms_log(pMac, LOG1, FL("PNO Scan completion called"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709 csr_save_scan_results(pMac, eCsrScanCandidateFound,
4710 pScanRsp->sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304711 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712 } else {
4713 /*
4714 * Scan completion was called, PNO is active, but scan
4715 * response was not PNO
4716 */
4717 sms_log(pMac, LOGE,
4718 FL("Scan completion called, scan rsp was not PNO."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304719 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 }
4721#endif
4722 sms_log(pMac, LOGE, FL("Scan completion called, but no active SCAN command."));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724}
4725
4726tCsrScanResultInfo *csr_scan_result_get_first(tpAniSirGlobal pMac,
4727 tScanResultHandle hScanResult)
4728{
4729 tListElem *pEntry;
4730 tCsrScanResult *pResult;
4731 tCsrScanResultInfo *pRet = NULL;
4732 tScanResultList *pResultList = (tScanResultList *) hScanResult;
4733
4734 if (pResultList) {
4735 csr_ll_lock(&pResultList->List);
4736 pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
4737 if (pEntry) {
4738 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4739 pRet = &pResult->Result;
4740 }
4741 pResultList->pCurEntry = pEntry;
4742 csr_ll_unlock(&pResultList->List);
4743 }
4744
4745 return pRet;
4746}
4747
4748tCsrScanResultInfo *csr_scan_result_get_next(tpAniSirGlobal pMac,
4749 tScanResultHandle hScanResult)
4750{
4751 tListElem *pEntry = NULL;
4752 tCsrScanResult *pResult = NULL;
4753 tCsrScanResultInfo *pRet = NULL;
4754 tScanResultList *pResultList = (tScanResultList *) hScanResult;
4755
4756 if (!pResultList)
4757 return NULL;
4758
4759 csr_ll_lock(&pResultList->List);
4760 if (NULL == pResultList->pCurEntry) {
4761 pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
4762 } else {
4763 pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry,
4764 LL_ACCESS_NOLOCK);
4765 }
4766 if (pEntry) {
4767 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4768 pRet = &pResult->Result;
4769 }
4770 pResultList->pCurEntry = pEntry;
4771 csr_ll_unlock(&pResultList->List);
4772 return pRet;
4773}
4774
4775/*
4776 * This function moves the first BSS that matches the bssid to the
4777 * head of the result
4778 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304779QDF_STATUS csr_move_bss_to_head_from_bssid(tpAniSirGlobal pMac,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304780 struct qdf_mac_addr *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781 tScanResultHandle hScanResult)
4782{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304783 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004784 tScanResultList *pResultList = (tScanResultList *) hScanResult;
4785 tCsrScanResult *pResult = NULL;
4786 tListElem *pEntry = NULL;
4787
4788 if (!(pResultList && bssid))
4789 return status;
4790
4791 csr_ll_lock(&pResultList->List);
4792 pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
4793 while (pEntry) {
4794 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304795 if (!qdf_mem_cmp(bssid, pResult->Result.BssDescriptor.bssId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304796 sizeof(struct qdf_mac_addr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304797 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 csr_ll_remove_entry(&pResultList->List, pEntry,
4799 LL_ACCESS_NOLOCK);
4800 csr_ll_insert_head(&pResultList->List, pEntry,
4801 LL_ACCESS_NOLOCK);
4802 break;
4803 }
4804 pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry,
4805 LL_ACCESS_NOLOCK);
4806 }
4807 csr_ll_unlock(&pResultList->List);
4808 return status;
4809}
4810
4811/* Remove the BSS if possible. */
4812/* Return -- true == the BSS is remove. False == Fail to remove it */
4813/* This function is called when list lock is held. Be caution what functions it can call. */
4814bool csr_scan_age_out_bss(tpAniSirGlobal pMac, tCsrScanResult *pResult)
4815{
4816 bool fRet = false;
4817 uint32_t i;
4818 tCsrRoamSession *pSession;
4819 bool isConnBssfound = false;
4820
4821 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4822 if (!CSR_IS_SESSION_VALID(pMac, i))
4823 continue;
4824 pSession = CSR_GET_SESSION(pMac, i);
4825 /* Not to remove the BSS we are connected to. */
4826 if (csr_is_conn_state_connected_infra(pMac, i)
4827 && (NULL != pSession->pConnectBssDesc)
4828 && (csr_is_duplicate_bss_description(pMac,
4829 &pResult->Result.BssDescriptor,
4830 pSession->pConnectBssDesc, NULL, false))) {
4831 isConnBssfound = true;
4832 break;
4833 }
4834 }
4835 if (isConnBssfound) {
4836 /*
4837 * Reset the counter so that aging out of connected BSS won't
4838 * hapeen too soon
4839 */
4840 pResult->AgingCount =
4841 (int32_t) pMac->roam.configParam.agingCount;
4842 sms_log(pMac, LOGW,
4843 FL("Connected BSS, Set Aging Count=%d for BSS "
4844 MAC_ADDRESS_STR), pResult->AgingCount,
4845 MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId));
4846 pResult->Result.BssDescriptor.nReceivedTime =
Anurag Chouhan210db072016-02-22 18:42:15 +05304847 (uint32_t) qdf_mc_timer_get_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 return fRet;
4849 }
4850 sms_log(pMac, LOGW,
4851 "Aging out BSS " MAC_ADDRESS_STR " Channel %d",
4852 MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId),
4853 pResult->Result.BssDescriptor.channelId);
4854 /*
4855 * No need to hold the spin lock because caller should hold the lock for
4856 * pMac->scan.scanResultList
4857 */
4858 if (csr_ll_remove_entry(&pMac->scan.scanResultList, &pResult->Link,
4859 LL_ACCESS_NOLOCK)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05304860 if (qdf_is_macaddr_equal(
Anurag Chouhan6d760662016-02-20 16:05:43 +05304861 (struct qdf_mac_addr *) &pResult->Result.BssDescriptor.bssId,
4862 (struct qdf_mac_addr *) &pMac->scan.currentCountryBssid)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863 sms_log(pMac, LOGW,
4864 FL("Aging out 11d BSS " MAC_ADDRESS_STR),
4865 MAC_ADDR_ARRAY(
4866 pResult->Result.BssDescriptor.bssId));
4867 pMac->scan.currentCountryRSSI = -128;
4868 }
4869 csr_free_scan_result_entry(pMac, pResult);
4870 fRet = true;
4871 }
4872 return fRet;
4873}
4874
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304875QDF_STATUS csr_scan_age_results(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004876 tSmeGetScanChnRsp *pScanChnInfo)
4877{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304878 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004879 tListElem *pEntry, *tmpEntry;
4880 tCsrScanResult *pResult;
4881 tLimScanChn *pChnInfo;
4882 uint8_t i;
4883
4884 csr_ll_lock(&pMac->scan.scanResultList);
4885 for (i = 0; i < pScanChnInfo->numChn; i++) {
4886 pChnInfo = &pScanChnInfo->scanChn[i];
4887 pEntry =
4888 csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
4889 while (pEntry) {
4890 tmpEntry =
4891 csr_ll_next(&pMac->scan.scanResultList, pEntry,
4892 LL_ACCESS_NOLOCK);
4893 pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
4894 if (pResult->Result.BssDescriptor.channelId ==
4895 pChnInfo->channelId) {
4896 if (pResult->AgingCount <= 0) {
4897 sms_log(pMac, LOGW,
4898 " age out due to ref count");
4899 csr_scan_age_out_bss(pMac, pResult);
4900 } else {
4901 pResult->AgingCount--;
4902 sms_log(pMac, LOGW,
4903 FL
4904 ("Decremented AgingCount=%d for BSS "
4905 MAC_ADDRESS_STR ""),
4906 pResult->AgingCount,
4907 MAC_ADDR_ARRAY(pResult->Result.
4908 BssDescriptor.
4909 bssId));
4910 }
4911 }
4912 pEntry = tmpEntry;
4913 }
4914 }
4915 csr_ll_unlock(&pMac->scan.scanResultList);
4916
4917 return status;
4918}
4919
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304920QDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 tCsrScanRequest *pScanReq,
4922 tScanReqParam *pScanReqParam)
4923{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304924 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925 tSirSmeScanReq *pMsg;
4926 uint16_t msgLen;
4927 tSirScanType scanType = pScanReq->scanType;
4928 uint32_t minChnTime; /* in units of milliseconds */
4929 uint32_t maxChnTime; /* in units of milliseconds */
4930 uint32_t i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304931 struct qdf_mac_addr selfmac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932
4933 msgLen = (uint16_t) (sizeof(tSirSmeScanReq) -
4934 sizeof(pMsg->channelList.channelNumber) +
4935 (sizeof(pMsg->channelList.channelNumber) *
4936 pScanReq->ChannelInfo.numOfChannels)) +
4937 (pScanReq->uIEFieldLen);
4938
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304939 pMsg = qdf_mem_malloc(msgLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 if (NULL == pMsg) {
4941 sms_log(pMac, LOGE, FL("memory allocation failed"));
4942 sms_log(pMac, LOG1, FL("Failed: SId: %d FirstMatch = %d"
4943 " UniqueResult = %d freshScan = %d hiddenSsid = %d"),
4944 sessionId, pScanReqParam->bReturnAfter1stMatch,
4945 pScanReqParam->fUniqueResult, pScanReqParam->freshScan,
4946 pScanReqParam->hiddenSsid);
4947 sms_log(pMac, LOG1,
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05304948 FL("scanType = %s (%u) BSSType = %s (%u) numOfSSIDs = %d"
Rajeev Kumar43e25b12016-04-15 16:26:36 -07004949 " numOfChannels = %d requestType = %s (%d) p2pSearch = %d\n"),
4950 sme_scan_type_to_string(pScanReq->scanType),
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05304951 pScanReq->scanType,
Rajeev Kumar43e25b12016-04-15 16:26:36 -07004952 sme_bss_type_to_string(pScanReq->BSSType),
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05304953 pScanReq->BSSType,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954 pScanReq->SSIDs.numOfSSIDs,
4955 pScanReq->ChannelInfo.numOfChannels,
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05304956 sme_request_type_to_string(pScanReq->requestType),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 pScanReq->requestType, pScanReq->p2pSearch);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304958 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 }
4960
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304961 qdf_mem_set(pMsg, msgLen, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962 pMsg->messageType = eWNI_SME_SCAN_REQ;
4963 pMsg->length = msgLen;
4964 /* ToDO: Fill in session info when we need to do scan base on session */
4965 if ((sessionId != CSR_SESSION_ID_INVALID)) {
4966 pMsg->sessionId = sessionId;
4967 } else {
4968 /* if sessionId == CSR_SESSION_ID_INVALID, then send the scan
4969 request on first available session */
4970 pMsg->sessionId = 0;
4971 }
4972 if (pMsg->sessionId >= CSR_ROAM_SESSION_MAX)
4973 sms_log(pMac, LOGE, FL(" Invalid Sme Session ID = %d"),
4974 pMsg->sessionId);
4975 pMsg->transactionId = 0;
4976 pMsg->dot11mode = (uint8_t) csr_translate_to_wni_cfg_dot11_mode(pMac,
4977 csr_find_best_phy_mode(pMac,
4978 pMac->roam.configParam.phyMode));
4979 pMsg->bssType = csr_translate_bsstype_to_mac_type(pScanReq->BSSType);
4980
4981 if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05304982 qdf_copy_macaddr(&selfmac,
Srinivas Girigowda2c6bf002015-09-24 11:43:31 -07004983 &pMac->roam.roamSession[sessionId].selfMacAddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984 } else {
4985 /*
4986 * Since we don't have session for the scanning, we find a valid
4987 * session. In case we fail to do so, get the WNI_CFG_STA_ID
4988 */
4989 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4990 if (CSR_IS_SESSION_VALID(pMac, i)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05304991 qdf_copy_macaddr(&selfmac,
Srinivas Girigowda2c6bf002015-09-24 11:43:31 -07004992 &pMac->roam.roamSession[i].selfMacAddr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993 break;
4994 }
4995 }
4996 if (CSR_ROAM_SESSION_MAX == i) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05304997 uint32_t len = QDF_MAC_ADDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004998 status = wlan_cfg_get_str(pMac, WNI_CFG_STA_ID,
Srinivas Girigowda2c6bf002015-09-24 11:43:31 -07004999 selfmac.bytes, &len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305000 if (!QDF_IS_STATUS_SUCCESS(status)
Anurag Chouhan6d760662016-02-20 16:05:43 +05305001 || (len < QDF_MAC_ADDR_SIZE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 sms_log(pMac, LOGE,
5003 FL("Can't get self MAC address = %d"),
5004 status);
5005 /* Force failed status */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305006 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 goto send_scan_req;
5008 }
5009 }
5010 }
Anurag Chouhanc5548422016-02-24 18:33:27 +05305011 qdf_copy_macaddr(&pMsg->selfMacAddr, &selfmac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012
Anurag Chouhanc5548422016-02-24 18:33:27 +05305013 qdf_copy_macaddr(&pMsg->bssId, &pScanReq->bssid);
5014 if (qdf_is_macaddr_zero(&pScanReq->bssid))
5015 qdf_set_macaddr_broadcast(&pMsg->bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016 else
Anurag Chouhanc5548422016-02-24 18:33:27 +05305017 qdf_copy_macaddr(&pMsg->bssId, &pScanReq->bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 minChnTime = pScanReq->minChnTime;
5019 maxChnTime = pScanReq->maxChnTime;
5020
5021 /*
5022 * Verify the scan type first, if the scan is active scan, we need to
5023 * make sure we are allowed to do so. if 11d is enabled & we don't see
5024 * any beacon around, scan type falls back to passive. But in BT AMP STA
5025 * mode we need to send out a directed probe
5026 */
5027 if ((eSIR_PASSIVE_SCAN != scanType)
Sandeep Puligillaee029ad2015-10-26 18:58:00 -07005028 && (eCSR_SCAN_P2P_DISCOVERY != pScanReq->requestType)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 && (false == pMac->scan.fEnableBypass11d)) {
5030 scanType = pMac->scan.curScanType;
5031 if (eSIR_PASSIVE_SCAN == pMac->scan.curScanType) {
5032 if (minChnTime <
5033 pMac->roam.configParam.nPassiveMinChnTime) {
5034 minChnTime =
5035 pMac->roam.configParam.nPassiveMinChnTime;
5036 }
5037 if (maxChnTime <
5038 pMac->roam.configParam.nPassiveMaxChnTime) {
5039 maxChnTime =
5040 pMac->roam.configParam.nPassiveMaxChnTime;
5041 }
5042 }
5043 }
5044 pMsg->scanType = scanType;
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05305045 pMsg->scan_adaptive_dwell_mode = pScanReq->scan_adaptive_dwell_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005046
5047 pMsg->numSsid = (pScanReq->SSIDs.numOfSSIDs < SIR_SCAN_MAX_NUM_SSID) ?
5048 pScanReq->SSIDs.numOfSSIDs : SIR_SCAN_MAX_NUM_SSID;
5049 if ((pScanReq->SSIDs.numOfSSIDs != 0)
5050 && (eSIR_PASSIVE_SCAN != scanType)) {
5051 for (i = 0; i < pMsg->numSsid; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305052 qdf_mem_copy(&pMsg->ssId[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053 &pScanReq->SSIDs.SSIDList[i].SSID,
5054 sizeof(tSirMacSSid));
5055 }
5056 } else {
5057 /* Otherwise we scan all SSID and let the result filter later */
5058 for (i = 0; i < SIR_SCAN_MAX_NUM_SSID; i++)
5059 pMsg->ssId[i].length = 0;
5060 }
5061
5062 pMsg->minChannelTime = minChnTime;
5063 pMsg->maxChannelTime = maxChnTime;
5064 /* hidden SSID option */
5065 pMsg->hiddenSsid = pScanReqParam->hiddenSsid;
Agrawal Ashish17bb3902016-05-05 13:29:40 +05305066 /* maximum rest time */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005067 pMsg->restTime = pScanReq->restTime;
Agrawal Ashish17bb3902016-05-05 13:29:40 +05305068 /* Minimum rest time */
5069 pMsg->min_rest_time = pScanReq->min_rest_time;
5070 /* Idle time */
5071 pMsg->idle_time = pScanReq->idle_time;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072 pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch;
5073 /* All the scan results caching will be done by Roaming */
5074 /* We do not want LIM to do any caching of scan results, */
5075 /* so delete the LIM cache on all scan requests */
5076 pMsg->returnFreshResults = pScanReqParam->freshScan;
5077 /* Always ask for unique result */
5078 pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
5079 pMsg->channelList.numChannels =
5080 (uint8_t) pScanReq->ChannelInfo.numOfChannels;
5081 if (pScanReq->ChannelInfo.numOfChannels) {
5082 /* Assuming the channelNumber is uint8_t (1 byte) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305083 qdf_mem_copy(pMsg->channelList.channelNumber,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005084 pScanReq->ChannelInfo.ChannelList,
5085 pScanReq->ChannelInfo.numOfChannels);
5086 }
5087
5088 pMsg->uIEFieldLen = (uint16_t) pScanReq->uIEFieldLen;
5089 pMsg->uIEFieldOffset = (uint16_t) (sizeof(tSirSmeScanReq) -
5090 sizeof(pMsg->channelList.channelNumber) +
5091 (sizeof(pMsg->channelList.channelNumber) *
5092 pScanReq->ChannelInfo.numOfChannels));
5093 if (pScanReq->uIEFieldLen != 0) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305094 qdf_mem_copy((uint8_t *) pMsg + pMsg->uIEFieldOffset,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005095 pScanReq->pIEField, pScanReq->uIEFieldLen);
5096 }
5097 pMsg->p2pSearch = pScanReq->p2pSearch;
5098 pMsg->scan_id = pScanReq->scan_id;
5099
5100send_scan_req:
5101 sms_log(pMac, LOG1,
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05305102 FL("scanId %d domainIdCurrent %d scanType %s (%d) bssType %s (%d) requestType %s (%d) numChannels %d"),
5103 pMsg->scan_id, pMac->scan.domainIdCurrent,
Rajeev Kumar43e25b12016-04-15 16:26:36 -07005104 sme_scan_type_to_string(pMsg->scanType), pMsg->scanType,
5105 sme_bss_type_to_string(pMsg->bssType), pMsg->bssType,
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05305106 sme_request_type_to_string(pScanReq->requestType),
5107 pScanReq->requestType, pMsg->channelList.numChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005108
5109 for (i = 0; i < pMsg->channelList.numChannels; i++) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305110 sms_log(pMac, LOG2, FL("channelNumber[%d]= %d"), i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005111 pMsg->channelList.channelNumber[i]);
5112 }
5113
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305114 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005115 status = cds_send_mb_message_to_mac(pMsg);
5116 } else {
5117 sms_log(pMac, LOGE,
5118 FL("failed to send down scan req with status = %d"),
5119 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305120 qdf_mem_free(pMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121 }
5122 return status;
5123}
5124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305125QDF_STATUS csr_send_mb_scan_result_req(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005126 uint32_t sessionId,
5127 tScanReqParam *pScanReqParam)
5128{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305129 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005130 tSirSmeScanReq *pMsg;
5131 uint16_t msgLen;
5132
5133 msgLen = (uint16_t) (sizeof(tSirSmeScanReq));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305134 pMsg = qdf_mem_malloc(msgLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005135 if (NULL == pMsg)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305136 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305138 qdf_mem_set(pMsg, msgLen, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005139 pMsg->messageType = eWNI_SME_SCAN_REQ;
5140 pMsg->length = msgLen;
5141 pMsg->sessionId = sessionId;
5142 pMsg->transactionId = 0;
5143 pMsg->returnFreshResults = pScanReqParam->freshScan;
5144 /* Always ask for unique result */
5145 pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
5146 pMsg->returnAfterFirstMatch =
5147 pScanReqParam->bReturnAfter1stMatch;
5148 status = cds_send_mb_message_to_mac(pMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305149 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 sms_log(pMac, LOGE,
5151 FL("Failed to send down scan req with status = %d\n"),
5152 status);
5153 }
5154 return status;
5155}
5156
5157#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
5158static void csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand)
5159{
5160 host_log_scan_pkt_type *pScanLog = NULL;
5161
5162 WLAN_HOST_DIAG_LOG_ALLOC(pScanLog,
5163 host_log_scan_pkt_type,
5164 LOG_WLAN_SCAN_C);
5165 if (!pScanLog)
5166 return;
5167
5168 if (eCsrScanProbeBss == pCommand->u.scanCmd.reason) {
5169 pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ;
5170 } else {
5171 if ((eSIR_PASSIVE_SCAN !=
5172 pCommand->u.scanCmd.u.scanRequest.scanType)
5173 && (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)) {
5174 pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ;
5175 } else {
5176 pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ;
5177 }
5178 }
5179 pScanLog->minChnTime =
5180 (uint8_t) pCommand->u.scanCmd.u.scanRequest.minChnTime;
5181 pScanLog->maxChnTime =
5182 (uint8_t) pCommand->u.scanCmd.u.scanRequest.maxChnTime;
5183 pScanLog->numChannel =
5184 (uint8_t) pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
5185 if (pScanLog->numChannel &&
5186 (pScanLog->numChannel < HOST_LOG_MAX_NUM_CHANNEL)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305187 qdf_mem_copy(pScanLog->channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005188 pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
5189 pScanLog->numChannel);
5190 }
5191 WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
5192}
5193#else
5194#define csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand) (void)0;
5195#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
5196
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305197QDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005198{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305199 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 tScanReqParam scanReq;
5201
5202 /*
5203 * Don't delete cached results. Rome rssi based scan candidates may land
5204 * up in scan cache instead of LFR cache. They will be deleted upon
5205 * query
5206 */
5207 scanReq.freshScan = SIR_BG_SCAN_RETURN_FRESH_RESULTS;
5208 scanReq.fUniqueResult = true;
5209 scanReq.hiddenSsid = SIR_SCAN_NO_HIDDEN_SSID;
5210 if (eCsrScanForSsid == pCommand->u.scanCmd.reason) {
5211 scanReq.bReturnAfter1stMatch =
5212 CSR_SCAN_RETURN_AFTER_FIRST_MATCH;
5213 } else {
5214 /*
5215 * Basically do scan on all channels even for 11D 1st scan case
5216 */
5217 scanReq.bReturnAfter1stMatch =
5218 CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
5219 }
5220 if (eCsrScanProbeBss == pCommand->u.scanCmd.reason)
5221 scanReq.hiddenSsid = SIR_SCAN_HIDDEN_SSID_PE_DECISION;
5222 csr_diag_scan_channels(pMac, pCommand);
5223 csr_clear_votes_for_country_info(pMac);
5224 status = csr_send_mb_scan_req(pMac, pCommand->sessionId,
5225 &pCommand->u.scanCmd.u.scanRequest,
5226 &scanReq);
5227 return status;
5228}
5229
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305230static QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231csr_issue_user_scan(tpAniSirGlobal mac_ctx, tSmeCmd *cmd)
5232{
5233 int i, j;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305234 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 uint32_t len = 0;
5236 uint8_t *ch_lst = NULL;
5237 tCsrChannelInfo new_ch_info = { 0, NULL };
5238
5239 if (!mac_ctx->roam.configParam.fScanTwice)
5240 return csr_scan_channels(mac_ctx, cmd);
5241
5242 /* We scan 2.4 channel twice */
5243 if (cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels
5244 && (NULL != cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)) {
5245 len = cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
5246 /* allocate twice the channel */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305247 new_ch_info.ChannelList = (uint8_t *) qdf_mem_malloc(len * 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248 ch_lst = cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList;
5249 } else {
5250 /* get the valid channel list to scan all. */
5251 len = sizeof(mac_ctx->roam.validChannelList);
5252 status = csr_get_cfg_valid_channels(mac_ctx,
5253 (uint8_t *) mac_ctx->roam.validChannelList, &len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305254 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 /* allocate twice the channel */
5256 new_ch_info.ChannelList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305257 (uint8_t *) qdf_mem_malloc(len * 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 ch_lst = mac_ctx->roam.validChannelList;
5259 }
5260 }
5261 if (NULL == new_ch_info.ChannelList) {
5262 new_ch_info.numOfChannels = 0;
5263 } else {
5264 j = 0;
5265 for (i = 0; i < len; i++) {
5266 new_ch_info.ChannelList[j++] = ch_lst[i];
Amar Singhal7a1726a2015-10-14 16:28:11 -07005267 if (CDS_MAX_24GHZ_CHANNEL_NUMBER >= ch_lst[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268 new_ch_info.ChannelList[j++] = ch_lst[i];
5269 }
5270 if (NULL !=
5271 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) {
5272 /*
5273 * ch_lst points to the channellist from the command,
5274 * free it.
5275 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305276 qdf_mem_free(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005277 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList);
5278 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList =
5279 NULL;
5280 }
5281 cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = j;
5282 cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList =
5283 new_ch_info.ChannelList;
5284 }
5285
5286 return csr_scan_channels(mac_ctx, cmd);
5287}
5288
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305289QDF_STATUS csr_process_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005290{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305291 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292
5293 sms_log(pMac, LOG3,
5294 FL("starting SCAN cmd in %d state. reason %d"),
5295 pCommand->u.scanCmd.lastRoamState[pCommand->sessionId],
5296 pCommand->u.scanCmd.reason);
5297
5298 switch (pCommand->u.scanCmd.reason) {
5299 case eCsrScanUserRequest:
5300 status = csr_issue_user_scan(pMac, pCommand);
5301 break;
5302 default:
5303 status = csr_scan_channels(pMac, pCommand);
5304 break;
5305 }
5306
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305307 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005308 csr_release_scan_command(pMac, pCommand, eCSR_SCAN_FAILURE);
5309 }
5310
5311 return status;
5312}
5313
5314/**
5315 * csr_scan_copy_request_valid_channels_only() - scan request of valid channels
5316 * @mac_ctx : pointer to Global Mac Structure
5317 * @dst_req: pointer to tCsrScanRequest
5318 * @skip_dfs_chnl: 1 - skip dfs channel, 0 - don't skip dfs channel
5319 * @src_req: pointer to tCsrScanRequest
5320 *
5321 * This function makes a copy of scan request with valid channels
5322 *
5323 * Return: none
5324 */
5325static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx,
5326 tCsrScanRequest *dst_req, uint8_t skip_dfs_chnl,
5327 tCsrScanRequest *src_req)
5328{
5329 uint32_t index = 0;
5330 uint32_t new_index = 0;
5331
5332 for (index = 0; index < src_req->ChannelInfo.numOfChannels; index++) {
5333 /* Allow scan on valid channels only.
5334 * If it is p2p scan and valid channel list doesnt contain
5335 * social channels, enforce scan on social channels because
5336 * that is the only way to find p2p peers.
5337 * This can happen only if band is set to 5Ghz mode.
5338 */
Amar Singhal7a1726a2015-10-14 16:28:11 -07005339 if (src_req->ChannelInfo.ChannelList[index] <
5340 CDS_MIN_11P_CHANNEL &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341 ((csr_roam_is_valid_channel(mac_ctx,
5342 src_req->ChannelInfo.ChannelList[index])) ||
5343 ((eCSR_SCAN_P2P_DISCOVERY == src_req->requestType) &&
5344 CSR_IS_SOCIAL_CHANNEL(
5345 src_req->ChannelInfo.ChannelList[index])))) {
5346 if (((src_req->skipDfsChnlInP2pSearch || skip_dfs_chnl)
5347 && (CHANNEL_STATE_DFS ==
5348 cds_get_channel_state(src_req->
5349 ChannelInfo.
5350 ChannelList
5351 [index])))
5352 ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353 sms_log(mac_ctx, LOG2,
Sreelakshmi Konamki39acb132015-12-16 13:06:22 +05305354 FL(" reqType= %s (%d), numOfChannels=%d, ignoring DFS channel %d"),
5355 sme_request_type_to_string(
5356 src_req->requestType),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 src_req->requestType,
5358 src_req->ChannelInfo.numOfChannels,
5359 src_req->ChannelInfo.ChannelList
5360 [index]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361 continue;
5362 }
5363
5364 dst_req->ChannelInfo.ChannelList[new_index] =
5365 src_req->ChannelInfo.ChannelList[index];
5366 new_index++;
5367 }
5368 }
5369 dst_req->ChannelInfo.numOfChannels = new_index;
5370}
5371
5372/**
Krunal Soni80aabd42015-12-21 12:17:16 -08005373 * csr_scan_filter_ibss_chnl_band() - filter all channels which matches IBSS
5374 * channel's band
5375 * @mac_ctx: pointer to mac context
5376 * @ibss_channel: Given IBSS channel
5377 * @dst_req: destination scan request
5378 *
5379 * when ever IBSS connection already exist, STA should not scan the channels
5380 * which fall under same band as IBSS channel's band. this routine will filter
5381 * out those channels
5382 *
5383 * Return: true if success otherwise false for any failure
5384 */
5385static bool csr_scan_filter_ibss_chnl_band(tpAniSirGlobal mac_ctx,
5386 uint8_t ibss_channel, tCsrScanRequest *dst_req) {
5387 uint8_t valid_chnl_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Krunal Soni80aabd42015-12-21 12:17:16 -08005388 uint32_t filter_chnl_len = 0, i = 0;
5389 uint32_t valid_chnl_len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5390
5391 if (ibss_channel == 0) {
5392 sms_log(mac_ctx, LOG1,
5393 FL("Nothing to filter as no IBSS session"));
5394 return true;
5395 }
5396
5397 if (!dst_req) {
5398 sms_log(mac_ctx, LOGE,
5399 FL("No valid scan requests"));
5400 return false;
5401 }
5402 /*
5403 * In case of concurrent IBSS session exist, scan only
5404 * those channels which are not in IBSS channel's band.
5405 * In case if no-concurrent IBSS session exist then scan
5406 * full band
5407 */
5408 if ((dst_req->ChannelInfo.numOfChannels == 0)) {
5409 csr_get_cfg_valid_channels(mac_ctx, valid_chnl_list,
5410 &valid_chnl_len);
5411 } else {
5412 valid_chnl_len = (WNI_CFG_VALID_CHANNEL_LIST_LEN >
5413 dst_req->ChannelInfo.numOfChannels) ?
5414 dst_req->ChannelInfo.numOfChannels :
5415 WNI_CFG_VALID_CHANNEL_LIST_LEN;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305416 qdf_mem_copy(valid_chnl_list, dst_req->ChannelInfo.ChannelList,
Krunal Soni80aabd42015-12-21 12:17:16 -08005417 valid_chnl_len);
5418 }
5419 for (i = 0; i < valid_chnl_len; i++) {
5420 /*
5421 * Don't allow DSRC channel when IBSS concurrent connection
5422 * is up
5423 */
Amar Singhal7a1726a2015-10-14 16:28:11 -07005424 if (valid_chnl_list[i] >= CDS_MIN_11P_CHANNEL)
Krunal Soni80aabd42015-12-21 12:17:16 -08005425 continue;
5426 if (CDS_IS_CHANNEL_5GHZ(ibss_channel) &&
5427 CDS_IS_CHANNEL_24GHZ(valid_chnl_list[i])) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005428 valid_chnl_list[filter_chnl_len] =
Krunal Soni80aabd42015-12-21 12:17:16 -08005429 valid_chnl_list[i];
5430 filter_chnl_len++;
5431 } else if (CDS_IS_CHANNEL_24GHZ(ibss_channel) &&
5432 CDS_IS_CHANNEL_5GHZ(valid_chnl_list[i])) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005433 valid_chnl_list[filter_chnl_len] =
Krunal Soni80aabd42015-12-21 12:17:16 -08005434 valid_chnl_list[i];
5435 filter_chnl_len++;
5436 }
5437 }
5438 if (filter_chnl_len == 0) {
5439 sms_log(mac_ctx, LOGE,
5440 FL("there no channels to scan due to IBSS session"));
5441 return false;
5442 }
5443
5444 if (dst_req->ChannelInfo.ChannelList) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305445 qdf_mem_free(dst_req->ChannelInfo.ChannelList);
Krunal Soni80aabd42015-12-21 12:17:16 -08005446 dst_req->ChannelInfo.ChannelList = NULL;
5447 dst_req->ChannelInfo.numOfChannels = 0;
5448 }
5449
5450 dst_req->ChannelInfo.ChannelList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305451 qdf_mem_malloc(filter_chnl_len *
Krunal Soni80aabd42015-12-21 12:17:16 -08005452 sizeof(*dst_req->ChannelInfo.ChannelList));
5453 dst_req->ChannelInfo.numOfChannels = filter_chnl_len;
5454 if (NULL == dst_req->ChannelInfo.ChannelList) {
5455 sms_log(mac_ctx, LOGE,
5456 FL("Memory allocation failed"));
5457 return false;
5458 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305459 qdf_mem_copy(dst_req->ChannelInfo.ChannelList, valid_chnl_list,
Krunal Soni80aabd42015-12-21 12:17:16 -08005460 filter_chnl_len);
5461 return true;
5462}
5463
5464/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 * csr_scan_copy_request() - Function to copy scan request
5466 * @mac_ctx : pointer to Global Mac Structure
5467 * @dst_req: pointer to tCsrScanRequest
5468 * @src_req: pointer to tCsrScanRequest
5469 *
5470 * This function makes a copy of scan request
5471 *
5472 * Return: 0 - Success, Error number - Failure
5473 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305474QDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 tCsrScanRequest *dst_req,
5476 tCsrScanRequest *src_req)
5477{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305478 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479 uint32_t len = sizeof(mac_ctx->roam.validChannelList);
5480 uint32_t index = 0;
5481 uint32_t new_index = 0;
Amar Singhala297bfa2015-10-15 15:07:29 -07005482 enum channel_state channel_state;
Krunal Soni80aabd42015-12-21 12:17:16 -08005483 uint8_t ibss_channel = 0;
Amar Singhala297bfa2015-10-15 15:07:29 -07005484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005485 bool skip_dfs_chnl =
5486 mac_ctx->roam.configParam.initial_scan_no_dfs_chnl ||
5487 !mac_ctx->scan.fEnableDFSChnlScan;
5488
5489 status = csr_scan_free_request(mac_ctx, dst_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305490 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005491 goto complete;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305492 qdf_mem_copy(dst_req, src_req, sizeof(tCsrScanRequest));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 /* Re-initialize the pointers to NULL since we did a copy */
5494 dst_req->pIEField = NULL;
5495 dst_req->ChannelInfo.ChannelList = NULL;
5496 dst_req->SSIDs.SSIDList = NULL;
5497
5498 if (src_req->uIEFieldLen) {
5499 dst_req->pIEField =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305500 qdf_mem_malloc(src_req->uIEFieldLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501 if (NULL == dst_req->pIEField) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305502 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005503 sms_log(mac_ctx, LOGE,
5504 FL("No memory for scanning IE fields"));
5505 goto complete;
5506 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305507 status = QDF_STATUS_SUCCESS;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305508 qdf_mem_copy(dst_req->pIEField, src_req->pIEField,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005509 src_req->uIEFieldLen);
5510 dst_req->uIEFieldLen = src_req->uIEFieldLen;
5511 }
5512 }
5513
5514 /* Allocate memory for IE field */
5515 if (src_req->ChannelInfo.numOfChannels == 0) {
5516 dst_req->ChannelInfo.ChannelList = NULL;
5517 dst_req->ChannelInfo.numOfChannels = 0;
5518 } else {
5519 dst_req->ChannelInfo.ChannelList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305520 qdf_mem_malloc(src_req->ChannelInfo.numOfChannels *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 sizeof(*dst_req->ChannelInfo.ChannelList));
5522 if (NULL == dst_req->ChannelInfo.ChannelList) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305523 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524 dst_req->ChannelInfo.numOfChannels = 0;
5525 sms_log(mac_ctx, LOGE,
5526 FL("No memory for scanning Channel List"));
5527 goto complete;
5528 }
5529
5530 if ((src_req->scanType == eSIR_PASSIVE_SCAN) &&
5531 (src_req->requestType == eCSR_SCAN_REQUEST_11D_SCAN)) {
5532 for (index = 0; index < src_req->ChannelInfo.
5533 numOfChannels; index++) {
5534 channel_state =
5535 cds_get_channel_state(src_req->
5536 ChannelInfo.
5537 ChannelList[index]);
5538 if (src_req->ChannelInfo.ChannelList[index] <
Amar Singhal7a1726a2015-10-14 16:28:11 -07005539 CDS_MIN_11P_CHANNEL &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 ((CHANNEL_STATE_ENABLE ==
5541 channel_state) ||
5542 ((CHANNEL_STATE_DFS == channel_state) &&
5543 !skip_dfs_chnl))) {
5544 dst_req->ChannelInfo.ChannelList
5545 [new_index] =
5546 src_req->
5547 ChannelInfo.
5548 ChannelList
5549 [index];
5550 new_index++;
5551 }
5552 }
5553 dst_req->ChannelInfo.numOfChannels = new_index;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305554 } else if (QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 csr_get_cfg_valid_channels(mac_ctx,
5556 mac_ctx->roam.validChannelList,
5557 &len))) {
5558 new_index = 0;
5559 mac_ctx->roam.numValidChannels = len;
5560 csr_scan_copy_request_valid_channels_only(mac_ctx,
5561 dst_req, skip_dfs_chnl,
5562 src_req);
5563 } else {
5564 sms_log(mac_ctx, LOGE,
5565 FL("Couldn't get the valid Channel List, keeping requester's list"));
5566 new_index = 0;
5567 for (index = 0; index < src_req->ChannelInfo.
5568 numOfChannels; index++) {
5569 if (src_req->ChannelInfo.ChannelList[index] <
Amar Singhal7a1726a2015-10-14 16:28:11 -07005570 CDS_MIN_11P_CHANNEL) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 dst_req->ChannelInfo.
5572 ChannelList[new_index] =
5573 src_req->ChannelInfo.
5574 ChannelList[index];
5575 new_index++;
5576 }
5577 }
5578 dst_req->ChannelInfo.numOfChannels =
5579 new_index;
5580 }
5581 } /* Allocate memory for Channel List */
Krunal Soni80aabd42015-12-21 12:17:16 -08005582
5583 /*
5584 * If IBSS concurrent connection exist, and if the scan
5585 * request comes from STA adapter then we need to filter
5586 * out IBSS channel's band otherwise it will cause issue
5587 * in IBSS+STA concurrency
5588 */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005589 if (true == cds_is_ibss_conn_exist(&ibss_channel)) {
Krunal Soni80aabd42015-12-21 12:17:16 -08005590 sms_log(mac_ctx, LOG1,
5591 FL("Conc IBSS exist, channel list will be modified"));
5592 }
5593
5594 if ((ibss_channel > 0) &&
5595 (false == csr_scan_filter_ibss_chnl_band(mac_ctx,
5596 ibss_channel, dst_req))) {
5597 sms_log(mac_ctx, LOGE,
5598 FL("Can't filter channels due to IBSS"));
5599 goto complete;
5600 }
5601
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 if (src_req->SSIDs.numOfSSIDs == 0) {
5603 dst_req->SSIDs.numOfSSIDs = 0;
5604 dst_req->SSIDs.SSIDList = NULL;
5605 } else {
5606 dst_req->SSIDs.SSIDList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305607 qdf_mem_malloc(src_req->SSIDs.numOfSSIDs *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005608 sizeof(*dst_req->SSIDs.SSIDList));
5609 if (NULL == dst_req->SSIDs.SSIDList)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305610 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305612 status = QDF_STATUS_SUCCESS;
5613 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614 dst_req->SSIDs.numOfSSIDs =
5615 src_req->SSIDs.numOfSSIDs;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305616 qdf_mem_copy(dst_req->SSIDs.SSIDList,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005617 src_req->SSIDs.SSIDList,
5618 src_req->SSIDs.numOfSSIDs *
5619 sizeof(*dst_req->SSIDs.SSIDList));
5620 } else {
5621 dst_req->SSIDs.numOfSSIDs = 0;
5622 sms_log(mac_ctx, LOGE,
5623 FL("No memory for scanning SSID List"));
5624 goto complete;
5625 }
5626 } /* Allocate memory for SSID List */
5627 dst_req->p2pSearch = src_req->p2pSearch;
5628 dst_req->skipDfsChnlInP2pSearch =
5629 src_req->skipDfsChnlInP2pSearch;
5630 dst_req->scan_id = src_req->scan_id;
5631 dst_req->timestamp = src_req->timestamp;
5632
5633complete:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305634 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635 csr_scan_free_request(mac_ctx, dst_req);
5636 }
5637
5638 return status;
5639}
5640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305641QDF_STATUS csr_scan_free_request(tpAniSirGlobal pMac, tCsrScanRequest *pReq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642{
5643
5644 if (pReq->ChannelInfo.ChannelList) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305645 qdf_mem_free(pReq->ChannelInfo.ChannelList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646 pReq->ChannelInfo.ChannelList = NULL;
5647 }
5648 pReq->ChannelInfo.numOfChannels = 0;
5649 if (pReq->pIEField) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305650 qdf_mem_free(pReq->pIEField);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005651 pReq->pIEField = NULL;
5652 }
5653 pReq->uIEFieldLen = 0;
5654 if (pReq->SSIDs.SSIDList) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305655 qdf_mem_free(pReq->SSIDs.SSIDList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656 pReq->SSIDs.SSIDList = NULL;
5657 }
5658 pReq->SSIDs.numOfSSIDs = 0;
5659
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305660 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661}
5662
5663void csr_scan_call_callback(tpAniSirGlobal pMac, tSmeCmd *pCommand,
5664 eCsrScanStatus scanStatus)
5665{
5666 if (pCommand->u.scanCmd.callback) {
5667 pCommand->u.scanCmd.callback(pMac, pCommand->u.scanCmd.pContext,
5668 pCommand->sessionId,
5669 pCommand->u.scanCmd.scanID,
5670 scanStatus);
5671 } else {
5672 sms_log(pMac, LOG2, "%s:%d - Callback NULL!!!", __func__,
5673 __LINE__);
5674 }
5675}
5676
5677void csr_scan_stop_timers(tpAniSirGlobal pMac)
5678{
5679 if (0 != pMac->scan.scanResultCfgAgingTime) {
5680 csr_scan_stop_result_cfg_aging_timer(pMac);
5681 }
5682
5683}
5684
5685#ifdef WLAN_AP_STA_CONCURRENCY
5686/**
5687 * csr_sta_ap_conc_timer_handler - Function to handle STA,AP concurrency timer
5688 * @pv: pointer variable
5689 *
5690 * Function handles STA,AP concurrency timer
5691 *
5692 * Return: none
5693 */
5694static void csr_sta_ap_conc_timer_handler(void *pv)
5695{
5696 tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv);
5697 tListElem *entry;
5698 tSmeCmd *scan_cmd;
5699 uint32_t session_id = CSR_SESSION_ID_INVALID;
5700 tCsrScanRequest scan_req;
5701 tSmeCmd *send_scancmd = NULL;
5702 uint8_t num_chn = 0;
5703 uint8_t numchan_combinedconc = 0;
5704 uint8_t i, j;
5705 tCsrChannelInfo *chn_info = NULL;
5706 uint8_t channel_to_scan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305707 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005708
5709 csr_ll_lock(&mac_ctx->scan.scanCmdPendingList);
5710
5711 entry = csr_ll_peek_head(&mac_ctx->scan.scanCmdPendingList,
5712 LL_ACCESS_NOLOCK);
5713
5714 if (NULL == entry) {
5715 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5716 return;
5717 }
5718
5719
5720 chn_info = &scan_req.ChannelInfo;
5721 scan_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
5722 num_chn =
5723 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
5724 session_id = scan_cmd->sessionId;
5725
5726 /*
5727 * if any session is connected and the number of channels to scan is
5728 * greater than 1 then split the scan into multiple scan operations
5729 * on each individual channel else continue to perform scan on all
5730 * specified channels */
5731
5732 /*
5733 * split scan if number of channels to scan is greater than 1 and
5734 * any one of the following:
5735 * - STA session is connected and the scan is not a P2P search
5736 * - any P2P session is connected
5737 * Do not split scans if no concurrent infra connections are
5738 * active and if the scan is a BG scan triggered by LFR (OR)
5739 * any scan if LFR is in the middle of a BG scan. Splitting
5740 * the scan is delaying the time it takes for LFR to find
5741 * candidates and resulting in disconnects.
5742 */
5743
5744 if ((csr_is_sta_session_connected(mac_ctx) &&
5745 !csr_is_p2p_session_connected(mac_ctx)))
5746 numchan_combinedconc =
5747 mac_ctx->roam.configParam.nNumStaChanCombinedConc;
5748 else if (csr_is_p2p_session_connected(mac_ctx))
5749 numchan_combinedconc =
5750 mac_ctx->roam.configParam.nNumP2PChanCombinedConc;
5751
5752 if ((num_chn > numchan_combinedconc) &&
5753 ((csr_is_sta_session_connected(mac_ctx) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 (csr_is_concurrent_infra_connected(mac_ctx)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755 (scan_cmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) ||
5756 (csr_is_p2p_session_connected(mac_ctx)))) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305757 qdf_mem_set(&scan_req, sizeof(tCsrScanRequest), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005758
5759 /* optimize this to use 2 command buffer only */
5760 send_scancmd = csr_get_command_buffer(mac_ctx);
5761 if (!send_scancmd) {
5762 sms_log(mac_ctx, LOGE,
5763 FL(" Failed to get Queue command buffer"));
5764 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5765 return;
5766 }
5767 send_scancmd->command = scan_cmd->command;
5768 send_scancmd->sessionId = scan_cmd->sessionId;
5769 send_scancmd->u.scanCmd.callback = NULL;
5770 send_scancmd->u.scanCmd.pContext =
5771 scan_cmd->u.scanCmd.pContext;
5772 send_scancmd->u.scanCmd.reason =
5773 scan_cmd->u.scanCmd.reason;
5774 /* let it wrap around */
5775 wma_get_scan_id(&send_scancmd->u.scanCmd.scanID);
5776
5777 /*
5778 * First copy all the parameters to local variable of scan
5779 * request
5780 */
5781 csr_scan_copy_request(mac_ctx, &scan_req,
5782 &scan_cmd->u.scanCmd.u.scanRequest);
5783
5784 /*
5785 * Now modify the elements of local var scan request required
5786 * to be modified for split scan
5787 */
5788 if (scan_req.ChannelInfo.ChannelList != NULL) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305789 qdf_mem_free(scan_req.ChannelInfo.ChannelList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790 scan_req.ChannelInfo.ChannelList = NULL;
5791 }
5792
5793 chn_info->numOfChannels = numchan_combinedconc;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305794 qdf_mem_copy(&channel_to_scan[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 &scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.
5796 ChannelList[0], chn_info->numOfChannels
5797 * sizeof(uint8_t));
5798 chn_info->ChannelList = &channel_to_scan[0];
5799
5800 for (i = 0, j = numchan_combinedconc;
5801 i < (num_chn - numchan_combinedconc);
5802 i++, j++) {
5803 /* Move all the channels one step */
5804 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.
5805 ChannelList[i] =
5806 scan_cmd->u.scanCmd.u.scanRequest.
5807 ChannelInfo.ChannelList[j];
5808 }
5809
5810 /* reduce outstanding # of channels to be scanned */
5811 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels =
5812 num_chn - numchan_combinedconc;
5813
5814 scan_req.BSSType = eCSR_BSS_TYPE_ANY;
5815 /* Modify callers parameters in case of concurrency */
5816 scan_req.scanType = eSIR_ACTIVE_SCAN;
5817 /* Use concurrency values for min/maxChnTime. */
5818 csr_set_default_scan_timing(mac_ctx, scan_req.scanType,
5819 &scan_req);
5820
5821 status = csr_scan_copy_request(mac_ctx,
5822 &send_scancmd->u.scanCmd.u.
5823 scanRequest, &scan_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305824 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825 sms_log(mac_ctx, LOGE,
5826 FL(" Failed to get copy csr_scan_request = %d"),
5827 status);
5828 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5829 return;
5830 }
5831 /* Clean the local scan variable */
5832 scan_req.ChannelInfo.ChannelList = NULL;
5833 scan_req.ChannelInfo.numOfChannels = 0;
5834 csr_scan_free_request(mac_ctx, &scan_req);
5835 } else {
5836 /*
5837 * no active connected session present or numChn == 1
5838 * scan all remaining channels
5839 */
5840 send_scancmd = scan_cmd;
5841 /* remove this command from pending list */
5842 if (csr_ll_remove_head(&mac_ctx->scan.scanCmdPendingList,
5843 /*
5844 * In case between PeekHead and here, the entry
5845 * got removed by another thread.
5846 */
5847 LL_ACCESS_NOLOCK) == NULL) {
5848 sms_log(mac_ctx, LOGE,
5849 FL(" Failed to remove entry from scanCmdPendingList"));
5850 }
5851
5852 }
5853 csr_queue_sme_command(mac_ctx, send_scancmd, false);
5854
5855
5856 csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
5857
5858}
5859#endif
5860
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305861QDF_STATUS csr_scan_start_result_cfg_aging_timer(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305863 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864
5865 if (pMac->scan.fScanEnable) {
5866 status =
Anurag Chouhan210db072016-02-22 18:42:15 +05305867 qdf_mc_timer_start(&pMac->scan.hTimerResultCfgAging,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005868 CSR_SCAN_RESULT_CFG_AGING_INTERVAL /
Anurag Chouhan210db072016-02-22 18:42:15 +05305869 QDF_MC_TIMER_TO_MS_UNIT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870 }
5871 return status;
5872}
5873
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305874QDF_STATUS csr_scan_stop_result_cfg_aging_timer(tpAniSirGlobal pMac)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005875{
Anurag Chouhan210db072016-02-22 18:42:15 +05305876 return qdf_mc_timer_stop(&pMac->scan.hTimerResultCfgAging);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005877}
5878
5879/**
5880 * csr_scan_result_cfg_aging_timer_handler() - Time based scan aging handler
5881 * @pv: Global context
5882 *
5883 * This routine is to handle scan aging based on user configured timer value.
5884 *
5885 * Return: None
5886 */
5887static void csr_scan_result_cfg_aging_timer_handler(void *pv)
5888{
5889 tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv);
5890 tListElem *entry, *tmp_entry;
5891 tCsrScanResult *result;
5892 uint32_t ageout_time =
Anurag Chouhan6d760662016-02-20 16:05:43 +05305893 mac_ctx->scan.scanResultCfgAgingTime * QDF_TICKS_PER_SECOND/10;
Anurag Chouhan210db072016-02-22 18:42:15 +05305894 uint32_t cur_time = (uint32_t) qdf_mc_timer_get_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 uint8_t *bssId;
5896
5897 csr_ll_lock(&mac_ctx->scan.scanResultList);
5898 entry = csr_ll_peek_head(&mac_ctx->scan.scanResultList, LL_ACCESS_NOLOCK);
5899 while (entry) {
5900 tmp_entry = csr_ll_next(&mac_ctx->scan.scanResultList, entry,
5901 LL_ACCESS_NOLOCK);
5902 result = GET_BASE_ADDR(entry, tCsrScanResult, Link);
5903 /*
Anurag Chouhan210db072016-02-22 18:42:15 +05305904 * qdf_mc_timer_get_system_ticks() returns in 10ms interval.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 * so ageout time value also updated to 10ms interval value.
5906 */
5907 if ((cur_time - result->Result.BssDescriptor.nReceivedTime) >
5908 ageout_time) {
5909 bssId = result->Result.BssDescriptor.bssId;
5910 sms_log(mac_ctx, LOGW,
5911 FL("age out due to time out"MAC_ADDRESS_STR),
5912 MAC_ADDR_ARRAY(bssId));
5913 csr_scan_age_out_bss(mac_ctx, result);
5914 }
5915 entry = tmp_entry;
5916 }
5917 csr_ll_unlock(&mac_ctx->scan.scanResultList);
Anurag Chouhan210db072016-02-22 18:42:15 +05305918 qdf_mc_timer_start(&mac_ctx->scan.hTimerResultCfgAging,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 CSR_SCAN_RESULT_CFG_AGING_INTERVAL /
Anurag Chouhan210db072016-02-22 18:42:15 +05305920 QDF_MC_TIMER_TO_MS_UNIT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921}
5922
5923bool csr_scan_remove_fresh_scan_command(tpAniSirGlobal pMac, uint8_t sessionId)
5924{
5925 bool fRet = false;
5926 tListElem *pEntry, *pEntryTmp;
5927 tSmeCmd *pCommand;
5928 tDblLinkList localList;
5929 tDblLinkList *pCmdList;
5930
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305931 qdf_mem_zero(&localList, sizeof(tDblLinkList));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305932 if (!QDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005933 sms_log(pMac, LOGE, FL(" failed to open list"));
5934 return fRet;
5935 }
5936
5937 pCmdList = &pMac->sme.smeScanCmdPendingList;
5938
5939 csr_ll_lock(pCmdList);
5940 pEntry = csr_ll_peek_head(pCmdList, LL_ACCESS_NOLOCK);
5941 while (pEntry) {
5942 pEntryTmp = csr_ll_next(pCmdList, pEntry, LL_ACCESS_NOLOCK);
5943 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
5944 if (!((eSmeCommandScan == pCommand->command)
5945 && (sessionId == pCommand->sessionId))) {
5946 pEntry = pEntryTmp;
5947 continue;
5948 }
5949 sms_log(pMac, LOGW,
5950 FL("-------- abort scan command reason = %d"),
5951 pCommand->u.scanCmd.reason);
5952 /* The rest are fresh scan requests */
5953 if (csr_ll_remove_entry(pCmdList, pEntry,
5954 LL_ACCESS_NOLOCK)) {
5955 csr_ll_insert_tail(&localList, pEntry,
5956 LL_ACCESS_NOLOCK);
5957 }
5958 fRet = true;
5959 pEntry = pEntryTmp;
5960 }
5961
5962 csr_ll_unlock(pCmdList);
5963
5964 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
5965 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
5966 if (pCommand->u.scanCmd.callback) {
5967 /*
5968 * User scan request is pending, send response with
5969 * status eCSR_SCAN_ABORT
5970 */
5971 pCommand->u.scanCmd.callback(pMac,
5972 pCommand->u.scanCmd.pContext, sessionId,
5973 pCommand->u.scanCmd.scanID, eCSR_SCAN_ABORT);
5974 }
5975 csr_release_command_scan(pMac, pCommand);
5976 }
5977 csr_ll_close(&localList);
5978
5979 return fRet;
5980}
5981
5982void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
5983 eCsrScanStatus scanStatus)
5984{
5985 eCsrScanReason reason = pCommand->u.scanCmd.reason;
5986 bool status;
5987 tDblLinkList *cmd_list = NULL;
5988
5989 csr_scan_call_callback(pMac, pCommand, scanStatus);
5990 sms_log(pMac, LOG1, FL("Remove Scan command reason = %d, scan_id %d"),
5991 reason, pCommand->u.scanCmd.scanID);
5992 cmd_list = &pMac->sme.smeScanCmdActiveList;
5993 status = csr_ll_remove_entry(cmd_list, &pCommand->Link, LL_ACCESS_LOCK);
5994 if (!status) {
5995 sms_log(pMac, LOGE,
5996 FL("cannot release command reason %d scan_id %d"),
5997 pCommand->u.scanCmd.reason,
5998 pCommand->u.scanCmd.scanID);
5999 return;
6000 }
6001 csr_release_command_scan(pMac, pCommand);
6002}
6003
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306004QDF_STATUS csr_scan_get_pmkid_candidate_list(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006005 uint32_t sessionId,
6006 tPmkidCandidateInfo *pPmkidList,
6007 uint32_t *pNumItems)
6008{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306009 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
6011 tCsrScanResultFilter *pScanFilter;
6012 tCsrScanResultInfo *pScanResult;
6013 tScanResultHandle hBSSList;
6014 uint32_t nItems = *pNumItems;
6015
6016 if (!pSession) {
6017 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306018 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006019 }
6020
6021 sms_log(pMac, LOGW, FL("pMac->scan.NumPmkidCandidate = %d"),
6022 pSession->NumPmkidCandidate);
6023 csr_reset_pmkid_candidate_list(pMac, sessionId);
6024 if (!(csr_is_conn_state_connected(pMac, sessionId)
6025 && pSession->pCurRoamProfile))
6026 return status;
6027
6028 *pNumItems = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306029 pScanFilter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030 if (NULL == pScanFilter)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306031 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006032
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306033 qdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034 /* Here is the profile we need to connect to */
6035 status = csr_roam_prepare_filter_from_profile(pMac,
6036 pSession->pCurRoamProfile, pScanFilter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306037 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306038 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006039 return status;
6040 }
6041
6042 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306043 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044 csr_free_scan_filter(pMac, pScanFilter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306045 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 return status;
6047 }
6048
6049 if (pSession->NumPmkidCandidate < nItems) {
6050 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
6051 while (pScanResult != NULL) {
6052 /* NumPmkidCandidate adds up here */
6053 csr_process_bss_desc_for_pmkid_list(pMac,
6054 &pScanResult->BssDescriptor,
6055 (tDot11fBeaconIEs *)(pScanResult->pvIes),
6056 sessionId);
6057 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
6058 }
6059 }
6060
6061 if (pSession->NumPmkidCandidate) {
6062 *pNumItems = pSession->NumPmkidCandidate;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306063 qdf_mem_copy(pPmkidList, pSession->PmkidCandidateInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006064 pSession->NumPmkidCandidate *
6065 sizeof(tPmkidCandidateInfo));
6066 }
6067
6068 csr_scan_result_purge(pMac, hBSSList);
6069 csr_free_scan_filter(pMac, pScanFilter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306070 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006071 return status;
6072}
6073
6074#ifdef FEATURE_WLAN_WAPI
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306075QDF_STATUS csr_scan_get_bkid_candidate_list(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076 uint32_t sessionId,
6077 tBkidCandidateInfo *pBkidList,
6078 uint32_t *pNumItems)
6079{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306080 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
6082 tCsrScanResultFilter *pScanFilter;
6083 tCsrScanResultInfo *pScanResult;
6084 tScanResultHandle hBSSList;
6085 uint32_t nItems = *pNumItems;
6086
6087 if (!pSession) {
6088 sms_log(pMac, LOGE, FL(" session %d not found "), sessionId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306089 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006090 }
6091
6092 sms_log(pMac, LOGW, FL("pMac->scan.NumBkidCandidate = %d"),
6093 pSession->NumBkidCandidate);
6094 csr_reset_bkid_candidate_list(pMac, sessionId);
6095 if (!(csr_is_conn_state_connected(pMac, sessionId)
6096 && pSession->pCurRoamProfile))
6097 return status;
6098
6099 *pNumItems = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306100 pScanFilter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101 if (NULL == pScanFilter)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306102 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306104 qdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006105 /* Here is the profile we need to connect to */
6106 status = csr_roam_prepare_filter_from_profile(pMac,
6107 pSession->pCurRoamProfile, pScanFilter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306108 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306109 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006110 return status;
6111 }
6112
6113 status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306114 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006115 csr_free_scan_filter(pMac, pScanFilter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306116 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006117 return status;
6118 }
6119
6120 if (pSession->NumBkidCandidate < nItems) {
6121 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
6122 while (pScanResult != NULL) {
6123 /* pMac->scan.NumBkidCandidate adds up here */
6124 csr_process_bss_desc_for_bkid_list(pMac,
6125 &pScanResult->BssDescriptor,
6126 (tDot11fBeaconIEs *)(pScanResult->pvIes));
6127 pScanResult = csr_scan_result_get_next(pMac, hBSSList);
6128 }
6129 }
6130
6131 if (pSession->NumBkidCandidate) {
6132 *pNumItems = pSession->NumBkidCandidate;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306133 qdf_mem_copy(pBkidList, pSession->BkidCandidateInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006134 pSession->NumBkidCandidate *
6135 sizeof(tBkidCandidateInfo));
6136 }
6137
6138 csr_scan_result_purge(pMac, hBSSList);
6139 csr_free_scan_filter(pMac, pScanFilter);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306140 qdf_mem_free(pScanFilter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006141 return status;
6142}
6143#endif /* FEATURE_WLAN_WAPI */
6144
6145/**
6146 * csr_roam_copy_channellist() - Function to copy channel list
6147 * @mac_ctx: pointer to Global Mac structure
6148 * @profile: pointer to tCsrRoamProfile
6149 * @scan_cmd: pointer to tSmeCmd
6150 * @index: index for channellist
6151 *
6152 * Function copies channel list
6153 *
6154 * Return: none
6155 */
6156static void csr_roam_copy_channellist(tpAniSirGlobal mac_ctx,
6157 tCsrRoamProfile *profile,
6158 tSmeCmd *scan_cmd, uint8_t index)
6159{
6160 tCsrChannelInfo *channel_info =
6161 &scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo;
6162
6163 for (index = 0; index < profile->ChannelInfo.numOfChannels;
6164 index++) {
6165 if (!csr_roam_is_valid_channel(mac_ctx,
6166 profile->ChannelInfo.ChannelList[index])) {
6167 sms_log(mac_ctx, LOGW,
6168 FL("process a channel (%d) that is invalid"),
6169 profile->ChannelInfo.ChannelList[index]);
6170 continue;
6171 }
6172 channel_info->ChannelList[channel_info->numOfChannels] =
6173 profile->ChannelInfo.ChannelList[index];
6174 scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels++;
6175 }
6176}
6177
6178/**
6179 * csr_scan_for_ssid() - Function usually used for BSSs that suppresses SSID
6180 * @mac_ctx: Pointer to Global Mac structure
6181 * @profile: pointer to tCsrRoamProfile
6182 * @roam_id: variable representing roam id
6183 * @notify: boolean variable
6184 *
6185 * Function is usually used for BSSs that suppresses SSID so the profile
6186 * shall have one and only one SSID.
6187 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306188 * Return: Success - QDF_STATUS_SUCCESS, Failure - error number
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006189 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306190QDF_STATUS csr_scan_for_ssid(tpAniSirGlobal mac_ctx, uint32_t session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006191 tCsrRoamProfile *profile, uint32_t roam_id,
6192 bool notify)
6193{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306194 QDF_STATUS status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006195 tSmeCmd *scan_cmd = NULL;
6196 tCsrScanRequest *scan_req = NULL;
6197 uint8_t index = 0;
6198 uint32_t num_ssid = profile->SSIDs.numOfSSIDs;
6199 tpCsrNeighborRoamControlInfo neighbor_roaminfo =
6200 &mac_ctx->roam.neighborRoamInfo[session_id];
6201 tCsrSSIDs *ssids = NULL;
6202
6203 sms_log(mac_ctx, LOG2, FL("called"));
6204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006205 if (!(mac_ctx->scan.fScanEnable) && (num_ssid != 1)) {
6206 sms_log(mac_ctx, LOGE,
6207 FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid"),
6208 mac_ctx->scan.fScanEnable, profile->SSIDs.numOfSSIDs);
6209 return status;
6210 }
6211
6212 scan_cmd = csr_get_command_buffer(mac_ctx);
6213
6214 if (!scan_cmd) {
6215 sms_log(mac_ctx, LOGE,
6216 FL("failed to allocate command buffer"));
6217 goto error;
6218 }
6219
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306220 qdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006221 scan_cmd->u.scanCmd.pToRoamProfile =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306222 qdf_mem_malloc(sizeof(tCsrRoamProfile));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006223
6224 if (NULL == scan_cmd->u.scanCmd.pToRoamProfile)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306225 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 else
6227 status = csr_roam_copy_profile(mac_ctx,
6228 scan_cmd->u.scanCmd.pToRoamProfile,
6229 profile);
6230
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306231 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006232 goto error;
6233
6234 scan_cmd->u.scanCmd.roamId = roam_id;
6235 scan_cmd->command = eSmeCommandScan;
6236 scan_cmd->sessionId = (uint8_t) session_id;
6237 scan_cmd->u.scanCmd.callback = NULL;
6238 scan_cmd->u.scanCmd.pContext = NULL;
6239 scan_cmd->u.scanCmd.reason = eCsrScanForSsid;
6240
6241 /* let it wrap around */
6242 wma_get_scan_id(&scan_cmd->u.scanCmd.scanID);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306243 qdf_mem_set(&scan_cmd->u.scanCmd.u.scanRequest,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006244 sizeof(tCsrScanRequest), 0);
Anurag Chouhan210db072016-02-22 18:42:15 +05306245 status = qdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306246 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 csr_scan_active_list_timeout_handle, &scan_cmd);
6248 scan_req = &scan_cmd->u.scanCmd.u.scanRequest;
6249 scan_req->scanType = eSIR_ACTIVE_SCAN;
6250 scan_req->BSSType = profile->BSSType;
6251 scan_req->scan_id = scan_cmd->u.scanCmd.scanID;
6252 /*
6253 * To avoid 11b rate in probe request Set p2pSearch
6254 * flag as 1 for P2P Client Mode
6255 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306256 if (QDF_P2P_CLIENT_MODE == profile->csrPersona)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006257 scan_req->p2pSearch = 1;
6258
6259 /* Allocate memory for IE field */
6260 if (profile->pAddIEScan) {
6261 scan_req->pIEField =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306262 qdf_mem_malloc(profile->nAddIEScanLength);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006263
6264 if (NULL == scan_req->pIEField)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306265 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006266 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306267 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006268
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306269 qdf_mem_set(scan_req->pIEField,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270 profile->nAddIEScanLength, 0);
6271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306272 if (QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306273 qdf_mem_copy(scan_req->pIEField,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006274 profile->pAddIEScan,
6275 profile->nAddIEScanLength);
6276 scan_req->uIEFieldLen = profile->nAddIEScanLength;
6277 } else {
6278 sms_log(mac_ctx, LOGE,
6279 "No memory for scanning IE fields");
6280 }
6281 } else
6282 scan_req->uIEFieldLen = 0;
6283
6284 /*
6285 * For one channel be good enpugh time to receive beacon
6286 * atleast
6287 */
6288 if (1 == profile->ChannelInfo.numOfChannels) {
6289 if (neighbor_roaminfo->handoffReqInfo.src ==
6290 FASTREASSOC) {
6291 scan_req->maxChnTime =
6292 MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC;
6293 scan_req->minChnTime =
6294 MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC;
6295 /* Reset this value */
6296 neighbor_roaminfo->handoffReqInfo.src = 0;
6297 } else {
6298 scan_req->maxChnTime =
6299 MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL;
6300 scan_req->minChnTime =
6301 MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL;
6302 }
6303 } else {
6304 scan_req->maxChnTime =
6305 mac_ctx->roam.configParam.nActiveMaxChnTime;
6306 scan_req->minChnTime =
6307 mac_ctx->roam.configParam.nActiveMinChnTime;
6308 }
6309
6310 if (profile->BSSIDs.numOfBSSIDs == 1)
Anurag Chouhanc5548422016-02-24 18:33:27 +05306311 qdf_copy_macaddr(&scan_req->bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006312 profile->BSSIDs.bssid);
6313 else
Anurag Chouhanc5548422016-02-24 18:33:27 +05306314 qdf_set_macaddr_broadcast(&scan_req->bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315
6316 if (profile->ChannelInfo.numOfChannels) {
6317 scan_req->ChannelInfo.ChannelList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306318 qdf_mem_malloc(sizeof(*scan_req->ChannelInfo.ChannelList) *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006319 profile->ChannelInfo.numOfChannels);
6320
6321 if (NULL == scan_req->ChannelInfo.ChannelList)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306322 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306324 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006325
6326 scan_req->ChannelInfo.numOfChannels = 0;
6327
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306328 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006329 csr_roam_is_channel_valid(mac_ctx,
6330 profile->ChannelInfo.ChannelList[0]);
6331 csr_roam_copy_channellist(mac_ctx,
6332 profile, scan_cmd, index);
6333 } else {
6334 goto error;
6335 }
6336 } else {
6337 scan_req->ChannelInfo.numOfChannels = 0;
6338 }
6339
6340 if (profile->SSIDs.numOfSSIDs) {
6341 scan_req->SSIDs.SSIDList =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306342 qdf_mem_malloc(profile->SSIDs.numOfSSIDs *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006343 sizeof(tCsrSSIDInfo));
6344
6345 if (NULL == scan_req->SSIDs.SSIDList)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306346 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347 else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306348 status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006349
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306350 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006351 goto error;
6352
6353 ssids = &scan_req->SSIDs;
6354 ssids->numOfSSIDs = 1;
6355
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306356 qdf_mem_copy(scan_req->SSIDs.SSIDList,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006357 profile->SSIDs.SSIDList,
6358 sizeof(tCsrSSIDInfo));
6359 }
6360
6361 /* Start process the command */
6362 status = csr_queue_sme_command(mac_ctx, scan_cmd, false);
6363error:
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306364 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006365 sms_log(mac_ctx, LOGE,
6366 FL(" failed to iniate scan with status = %d"), status);
6367 if (scan_cmd)
6368 csr_release_command_scan(mac_ctx, scan_cmd);
6369 if (notify)
6370 csr_roam_call_callback(mac_ctx, session_id, NULL,
6371 roam_id, eCSR_ROAM_FAILED,
6372 eCSR_ROAM_RESULT_FAILURE);
6373 }
6374 return status;
6375}
6376
6377void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList,
6378 uint8_t NumChannels)
6379{
6380 uint32_t dataLen = sizeof(uint8_t) * NumChannels;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306381 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006382
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306383 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006384 "%s: dump valid channel list(NumChannels(%d))",
6385 __func__, NumChannels);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306386 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006387 pChannelList, NumChannels);
6388 cfg_set_str(pMac, WNI_CFG_VALID_CHANNEL_LIST, pChannelList,
6389 dataLen);
6390
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306391 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006392 "Scan offload is enabled, update default chan list");
6393 /*
6394 * disable fcc constraint since new country code
6395 * is being set
6396 */
6397 pMac->scan.fcc_constraint = false;
6398 status = csr_update_channel_list(pMac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306399 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306400 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006401 "failed to update the supported channel list");
6402 }
6403 return;
6404}
6405
6406/*
6407 * The Tx power limits are saved in the cfg for future usage.
6408 */
6409void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList,
6410 uint32_t cfgId)
6411{
6412 tListElem *pEntry;
6413 uint32_t cbLen = 0, dataLen, tmp_len;
6414 tCsrChannelPowerInfo *ch_set;
6415 uint32_t idx;
6416 tSirMacChanInfo *ch_pwr_set;
6417 uint8_t *pBuf = NULL;
6418
6419 /* allocate maximum space for all channels */
6420 dataLen = WNI_CFG_VALID_CHANNEL_LIST_LEN * sizeof(tSirMacChanInfo);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306421 pBuf = qdf_mem_malloc(dataLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006422 if (pBuf == NULL)
6423 return;
6424
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306425 qdf_mem_set(pBuf, dataLen, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006426 ch_pwr_set = (tSirMacChanInfo *) (pBuf);
6427 pEntry = csr_ll_peek_head(pList, LL_ACCESS_LOCK);
6428 /*
6429 * write the tuples (startChan, numChan, txPower) for each channel found
6430 * in the channel power list.
6431 */
6432 while (pEntry) {
6433 ch_set = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link);
6434 if (1 != ch_set->interChannelOffset) {
6435 /*
6436 * we keep the 5G channel sets internally with an
6437 * interchannel offset of 4. Expand these to the right
6438 * format. (inter channel offset of 1 is the only option
6439 * for the triplets that 11d advertises.
6440 */
6441 tmp_len = cbLen + (ch_set->numChannels *
6442 sizeof(tSirMacChanInfo));
6443 if (tmp_len >= dataLen) {
6444 /*
6445 * expanding this entry will overflow our
6446 * allocation
6447 */
6448 sms_log(pMac, LOGE,
6449 FL("Buffer overflow, start %d, num %d, offset %d"),
6450 ch_set->firstChannel,
6451 ch_set->numChannels,
6452 ch_set->interChannelOffset);
6453 break;
6454 }
6455
6456 for (idx = 0; idx < ch_set->numChannels; idx++) {
6457 ch_pwr_set->firstChanNum = (tSirMacChanNum)
6458 (ch_set->firstChannel + (idx *
6459 ch_set->interChannelOffset));
6460 sms_log(pMac, LOG3,
6461 FL("Setting Channel Number %d"),
6462 ch_pwr_set->firstChanNum);
6463 ch_pwr_set->numChannels = 1;
6464 ch_pwr_set->maxTxPower =
Anurag Chouhan6d760662016-02-20 16:05:43 +05306465 QDF_MIN(ch_set->txPower,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006466 pMac->roam.configParam.nTxPowerCap);
6467 sms_log(pMac, LOG3,
6468 FL("Setting Max Transmit Power %d"),
6469 ch_pwr_set->maxTxPower);
6470 cbLen += sizeof(tSirMacChanInfo);
6471 ch_pwr_set++;
6472 }
6473 } else {
6474 if (cbLen >= dataLen) {
6475 /* this entry will overflow our allocation */
6476 sms_log(pMac, LOGE,
6477 FL("Buffer overflow, start %d, num %d, offset %d"),
6478 ch_set->firstChannel,
6479 ch_set->numChannels,
6480 ch_set->interChannelOffset);
6481 break;
6482 }
6483 ch_pwr_set->firstChanNum = ch_set->firstChannel;
6484 sms_log(pMac, LOG3, FL("Setting Channel Number %d"),
6485 ch_pwr_set->firstChanNum);
6486 ch_pwr_set->numChannels = ch_set->numChannels;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306487 ch_pwr_set->maxTxPower = QDF_MIN(ch_set->txPower,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006488 pMac->roam.configParam.nTxPowerCap);
6489 sms_log(pMac, LOG3,
6490 FL("Setting Max Tx Power %d, nTxPower %d"),
6491 ch_pwr_set->maxTxPower,
6492 pMac->roam.configParam.nTxPowerCap);
6493 cbLen += sizeof(tSirMacChanInfo);
6494 ch_pwr_set++;
6495 }
6496 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_LOCK);
6497 }
6498 if (cbLen)
6499 cfg_set_str(pMac, cfgId, (uint8_t *) pBuf, cbLen);
6500
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306501 qdf_mem_free(pBuf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006502}
6503
6504void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode)
6505{
6506 uint8_t cc[WNI_CFG_COUNTRY_CODE_LEN];
6507 /* v_REGDOMAIN_t DomainId */
6508
6509 sms_log(pMac, LOG3, FL("Setting Country Code in Cfg %s"), countryCode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306510 qdf_mem_copy(cc, countryCode, WNI_CFG_COUNTRY_CODE_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006511
6512 /*
6513 * don't program the bogus country codes that we created for Korea in the
6514 * MAC. if we see the bogus country codes, program the MAC with the right
6515 * country code.
6516 */
6517 if (('K' == countryCode[0] && '1' == countryCode[1]) ||
6518 ('K' == countryCode[0] && '2' == countryCode[1]) ||
6519 ('K' == countryCode[0] && '3' == countryCode[1]) ||
6520 ('K' == countryCode[0] && '4' == countryCode[1])) {
6521 /*
6522 * replace the alternate Korea country codes, 'K1', 'K2', ..
6523 * with 'KR' for Korea
6524 */
6525 cc[1] = 'R';
6526 }
6527 cfg_set_str(pMac, WNI_CFG_COUNTRY_CODE, cc, WNI_CFG_COUNTRY_CODE_LEN);
6528
6529 /*
6530 * Need to let HALPHY know about the current domain so it can apply some
6531 * domain-specific settings (TX filter...)
6532 */
6533 /*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306534 if(QDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006535 pMac, cc, &DomainId))) {
6536 halPhySetRegDomain(pMac, DomainId);
6537 } */
6538}
6539
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306540QDF_STATUS csr_get_country_code(tpAniSirGlobal pMac, uint8_t *pBuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006541 uint8_t *pbLen)
6542{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306543 QDF_STATUS status = QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006544 uint32_t len;
6545
6546 if (pBuf && pbLen && (*pbLen >= WNI_CFG_COUNTRY_CODE_LEN)) {
6547 len = *pbLen;
6548 status = wlan_cfg_get_str(pMac, WNI_CFG_COUNTRY_CODE, pBuf, &len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306549 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006550 *pbLen = (uint8_t) len;
6551 }
6552 }
6553
6554 return status;
6555}
6556
6557void csr_set_cfg_scan_control_list(tpAniSirGlobal pMac, uint8_t *countryCode,
6558 tCsrChannel *pChannelList)
6559{
6560 uint8_t i, j;
6561 bool found = false;
6562 uint8_t *pControlList = NULL;
6563 uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
6564
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306565 pControlList = qdf_mem_malloc(WNI_CFG_SCAN_CONTROL_LIST_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006566 if (pControlList != NULL) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306567 qdf_mem_set((void *)pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006568 0);
6569 if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_str(pMac,
6570 WNI_CFG_SCAN_CONTROL_LIST,
6571 pControlList, &len))) {
6572 for (i = 0; i < pChannelList->numChannels; i++) {
6573 for (j = 0; j < len; j += 2) {
6574 if (pControlList[j] ==
6575 pChannelList->channelList[i]) {
6576 found = true;
6577 break;
6578 }
6579 }
6580
6581 if (found) {
6582 /* insert a pair(channel#, flag) */
6583 pControlList[j + 1] =
6584 csr_get_scan_type(pMac,
6585 pControlList[j]);
6586 found = false; /* reset the flag */
6587 }
6588
6589 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306590 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006591 "%s: dump scan control list", __func__);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306592 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_SME,
6593 QDF_TRACE_LEVEL_INFO, pControlList,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006594 len);
6595
6596 cfg_set_str(pMac, WNI_CFG_SCAN_CONTROL_LIST,
6597 pControlList, len);
6598 } /* Successfully getting scan control list */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306599 qdf_mem_free(pControlList);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006600 } /* AllocateMemory */
6601}
6602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306603QDF_STATUS csr_scan_abort_mac_scan(tpAniSirGlobal pMac, uint8_t sessionId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006604 eCsrAbortReason reason)
6605{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306606 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006607
6608 pMac->scan.fDropScanCmd = true;
6609 csr_remove_cmd_with_session_id_from_pending_list(pMac,
6610 sessionId, &pMac->sme.smeScanCmdPendingList,
6611 eSmeCommandScan);
6612 pMac->scan.fDropScanCmd = false;
6613 csr_abort_scan_from_active_list(pMac,
6614 &pMac->sme.smeScanCmdActiveList, sessionId,
6615 eSmeCommandScan, reason);
6616
6617 return status;
6618}
6619
6620void csr_remove_cmd_with_session_id_from_pending_list(tpAniSirGlobal pMac,
6621 uint8_t sessionId,
6622 tDblLinkList *pList,
6623 eSmeCommandType commandType)
6624{
6625 tDblLinkList localList;
6626 tListElem *pEntry;
6627 tSmeCmd *pCommand;
6628 tListElem *pEntryToRemove;
6629
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306630 qdf_mem_zero(&localList, sizeof(tDblLinkList));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306631 if (!QDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006632 sms_log(pMac, LOGE, FL("failed to open list"));
6633 return;
6634 }
6635
6636 csr_ll_lock(pList);
6637 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
6638 if (pEntry) {
6639 /*
6640 * Have to make sure we don't loop back to the head of the list,
6641 * which will happen if the entry is NOT on the list
6642 */
6643 while (pEntry) {
6644 pEntryToRemove = pEntry;
6645 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
6646 pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
6647
6648 if (!((pCommand->command == commandType) &&
6649 (pCommand->sessionId == sessionId)))
6650 continue;
6651 /* Remove that entry only */
6652 if (csr_ll_remove_entry(pList, pEntryToRemove,
6653 LL_ACCESS_NOLOCK)) {
6654 csr_ll_insert_tail(&localList, pEntryToRemove,
6655 LL_ACCESS_NOLOCK);
6656 }
6657 }
6658 }
6659 csr_ll_unlock(pList);
6660
6661 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
6662 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
6663 sms_log(pMac, LOG1, FL("Sending abort for scan command ID %d"),
6664 pCommand->u.scanCmd.scanID);
6665 csr_abort_command(pMac, pCommand, false);
6666 }
6667
6668 csr_ll_close(&localList);
6669}
6670
6671void csr_remove_cmd_from_pending_list(tpAniSirGlobal pMac,
6672 tDblLinkList *pList,
6673 eSmeCommandType commandType)
6674{
6675 tDblLinkList localList;
6676 tListElem *pEntry;
6677 tSmeCmd *pCommand;
6678 tListElem *pEntryToRemove;
6679
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306680 qdf_mem_zero(&localList, sizeof(tDblLinkList));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306681 if (!QDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006682 sms_log(pMac, LOGE, FL(" failed to open list"));
6683 return;
6684 }
6685
6686 csr_ll_lock(pList);
6687 if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) {
6688 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
6689 /*
6690 * Have to make sure we don't loop back to the head of the list,
6691 * which will happen if the entry is NOT on the list...
6692 */
6693 while (pEntry) {
6694 pEntryToRemove = pEntry;
6695 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
6696 pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
6697 /* Remove that entry only that matches cmd type */
6698 if (pCommand->command == commandType &&
6699 csr_ll_remove_entry(pList, pEntryToRemove,
6700 LL_ACCESS_NOLOCK)) {
6701 csr_ll_insert_tail(&localList, pEntryToRemove,
6702 LL_ACCESS_NOLOCK);
6703 }
6704 }
6705 }
6706 csr_ll_unlock(pList);
6707
6708 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
6709 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
6710 csr_abort_command(pMac, pCommand, false);
6711 }
6712 csr_ll_close(&localList);
6713
6714}
6715
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306716QDF_STATUS csr_scan_abort_scan_for_ssid(tpAniSirGlobal pMac, uint32_t sessionId)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006717{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306718 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006719
6720 pMac->scan.fDropScanCmd = true;
6721 csr_remove_scan_for_ssid_from_pending_list(pMac,
6722 &pMac->sme.smeScanCmdPendingList, sessionId);
6723 pMac->scan.fDropScanCmd = false;
6724 csr_abort_scan_from_active_list(pMac, &pMac->sme.smeScanCmdActiveList,
6725 sessionId, eSmeCommandScan, eCSR_SCAN_ABORT_SSID_ONLY);
6726 return status;
6727}
6728
6729void csr_remove_scan_for_ssid_from_pending_list(tpAniSirGlobal pMac,
6730 tDblLinkList *pList,
6731 uint32_t sessionId)
6732{
6733 tDblLinkList localList;
6734 tListElem *pEntry;
6735 tSmeCmd *pCommand;
6736 tListElem *pEntryToRemove;
6737
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306738 qdf_mem_zero(&localList, sizeof(tDblLinkList));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306739 if (!QDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 sms_log(pMac, LOGE, FL(" failed to open list"));
6741 return;
6742 }
6743 csr_ll_lock(pList);
6744 if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) {
6745 pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
6746 /*
6747 * Have to make sure we don't loop back to the head of the list,
6748 * which will happen if the entry is NOT on the list...
6749 */
6750 while (pEntry) {
6751 pEntryToRemove = pEntry;
6752 pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
6753 pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
6754
6755 if (!((eSmeCommandScan == pCommand->command) &&
6756 (sessionId == pCommand->sessionId)))
6757 continue;
6758 if (eCsrScanForSsid != pCommand->u.scanCmd.reason)
6759 continue;
6760 /* Remove that entry only */
6761 if (csr_ll_remove_entry(pList, pEntryToRemove,
6762 LL_ACCESS_NOLOCK)) {
6763 csr_ll_insert_tail(&localList, pEntryToRemove,
6764 LL_ACCESS_NOLOCK);
6765 }
6766 }
6767 }
6768 csr_ll_unlock(pList);
6769 while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
6770 pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
6771 csr_abort_command(pMac, pCommand, false);
6772 }
6773 csr_ll_close(&localList);
6774}
6775
6776
6777/**
6778 * csr_send_scan_abort() - Sends scan abort command to firmware
6779 * @mac_ctx: Pointer to Global Mac structure
6780 * @session_id: CSR session identification
6781 * @scan_id: scan identifier
6782 *
6783 * .Sends scan abort command to firmware
6784 *
6785 * Return: None
6786 */
6787static void csr_send_scan_abort(tpAniSirGlobal mac_ctx,
6788 uint32_t session_id, uint32_t scan_id)
6789{
6790 tSirSmeScanAbortReq *msg;
6791 uint16_t msg_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306792 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006793
6794 msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306795 msg = qdf_mem_malloc(msg_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006796 if (NULL == msg) {
6797 sms_log(mac_ctx, LOGE,
6798 FL("Failed to alloc memory for SmeScanAbortReq"));
6799 return;
6800 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306801 qdf_mem_zero((void *)msg, msg_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802 msg->type = eWNI_SME_SCAN_ABORT_IND;
6803 msg->msgLen = msg_len;
6804 msg->sessionId = session_id;
6805 msg->scan_id = scan_id;
6806 sms_log(mac_ctx, LOG2,
6807 FL("Abort scan sent to Firmware scan_id %d session %d"),
6808 scan_id, session_id);
6809 status = cds_send_mb_message_to_mac(msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306810 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306811 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006812 sms_log(mac_ctx, LOGE,
6813 FL("Failed to send abort scan.scan_id %d session %d"),
6814 scan_id, session_id);
6815 }
6816 return;
6817}
6818
6819/**
6820 * csr_abort_scan_from_active_list() - Remove Scan command from active list
6821 * @mac_ctx: Pointer to Global Mac structure
6822 * @list: pointer to scan active list
6823 * @session_id: CSR session identification
6824 * @scan_cmd_type: scan command type
6825 * @abort_reason: abort reason
6826 *
6827 * .Remove Scan command from active scan list
6828 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306829 * Return: Success - QDF_STATUS_SUCCESS, Failure - error number
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006830 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306831QDF_STATUS csr_abort_scan_from_active_list(tpAniSirGlobal mac_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006832 tDblLinkList *list, uint32_t session_id,
6833 eSmeCommandType scan_cmd_type, eCsrAbortReason abort_reason)
6834{
6835 tListElem *entry;
6836 tSmeCmd *cmd;
6837 tListElem *entry_remove;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306838 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006839
6840 csr_ll_lock(list);
6841 if (!csr_ll_is_list_empty(list, LL_ACCESS_NOLOCK)) {
6842 entry = csr_ll_peek_head(list, LL_ACCESS_NOLOCK);
6843 while (entry) {
6844 entry_remove = entry;
6845 entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
6846 cmd = GET_BASE_ADDR(entry_remove, tSmeCmd, Link);
6847
6848 /* Skip if command and session id not matched */
6849 if (!((scan_cmd_type == cmd->command) &&
6850 (session_id == cmd->sessionId)))
6851 continue;
6852 /*skip if abort reason is for SSID*/
6853 if ((abort_reason == eCSR_SCAN_ABORT_SSID_ONLY) &&
6854 (eCsrScanForSsid != cmd->u.scanCmd.reason))
6855 continue;
6856 if (abort_reason == eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE)
6857 cmd->u.scanCmd.abortScanDueToBandChange =
6858 true;
6859 csr_send_scan_abort(mac_ctx, cmd->sessionId,
6860 cmd->u.scanCmd.scanID);
6861 }
6862 }
6863 csr_ll_unlock(list);
6864
6865 return status;
6866}
6867
6868
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306869QDF_STATUS csr_scan_abort_mac_scan_not_for_connect(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006870 uint8_t sessionId)
6871{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306872 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873 if (!csr_is_scan_for_roam_command_active(pMac)) {
6874 /*
6875 * Only abort the scan if it is not used for other roam/connect
6876 * purpose
6877 */
6878 status = csr_scan_abort_mac_scan(pMac, sessionId,
6879 eCSR_SCAN_ABORT_DEFAULT);
6880 }
6881 return status;
6882}
6883bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel)
6884{
6885 bool fValid = false;
6886 uint32_t idx_valid_ch;
6887 uint32_t len = pMac->roam.numValidChannels;
6888
6889 for (idx_valid_ch = 0; (idx_valid_ch < len); idx_valid_ch++) {
6890 if (channel == pMac->roam.validChannelList[idx_valid_ch]) {
6891 fValid = true;
6892 break;
6893 }
6894 }
6895 return fValid;
6896}
6897
6898#ifdef FEATURE_WLAN_SCAN_PNO
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306899QDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006900 tSirPrefNetworkFoundInd *
6901 pPrefNetworkFoundInd)
6902{
6903 uint32_t uLen = 0;
6904 tpSirProbeRespBeacon parsed_frm;
6905 tCsrScanResult *pScanResult = NULL;
6906 tSirBssDescription *pBssDescr = NULL;
6907 bool fDupBss;
6908 tDot11fBeaconIEs *local_ie = NULL;
6909 tAniSSID tmpSsid;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306910 unsigned long timer = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306911 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006912
6913 tpSirMacMgmtHdr macHeader =
6914 (tpSirMacMgmtHdr) pPrefNetworkFoundInd->data;
6915 parsed_frm =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306916 (tpSirProbeRespBeacon) qdf_mem_malloc(sizeof(tSirProbeRespBeacon));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006917
6918 if (NULL == parsed_frm) {
6919 sms_log(pMac, LOGE, FL("fail to allocate memory for frame"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306920 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006921 }
6922 if (pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A) {
6923 sms_log(pMac, LOGE,
6924 FL("Incorrect len(%d)"),
6925 pPrefNetworkFoundInd->frameLength);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306926 qdf_mem_free(parsed_frm);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306927 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006928 }
6929 if (sir_convert_probe_frame2_struct(pMac,
6930 &pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A],
6931 pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A,
6932 parsed_frm) != eSIR_SUCCESS
6933 || !parsed_frm->ssidPresent) {
6934 sms_log(pMac, LOGE, FL("Parse error ProbeResponse, length=%d"),
6935 pPrefNetworkFoundInd->frameLength);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306936 qdf_mem_free(parsed_frm);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306937 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006938 }
6939 /* 24 byte MAC header and 12 byte to ssid IE */
6940 if (pPrefNetworkFoundInd->frameLength >
6941 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) {
6942 uLen = pPrefNetworkFoundInd->frameLength -
6943 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
6944 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306945 pScanResult = qdf_mem_malloc(sizeof(tCsrScanResult) + uLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006946 if (NULL == pScanResult) {
6947 sms_log(pMac, LOGE, FL("fail to allocate memory for frame"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306948 qdf_mem_free(parsed_frm);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306949 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006950 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306951 qdf_mem_set(pScanResult, sizeof(tCsrScanResult) + uLen, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006952 pBssDescr = &pScanResult->Result.BssDescriptor;
6953 /*
6954 * Length of BSS desription is without length of length itself and
6955 * length of pointer that holds the next BSS description
6956 */
6957 pBssDescr->length = (uint16_t) (sizeof(tSirBssDescription) -
6958 sizeof(uint16_t) - sizeof(uint32_t) + uLen);
6959 if (parsed_frm->dsParamsPresent)
6960 pBssDescr->channelId = parsed_frm->channelNumber;
6961 else if (parsed_frm->HTInfo.present)
6962 pBssDescr->channelId = parsed_frm->HTInfo.primaryChannel;
6963 else
6964 pBssDescr->channelId = parsed_frm->channelNumber;
6965
6966 if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) {
6967 int i;
6968 /* 11b or 11g packet */
6969 /* 11g iff extended Rate IE is present or */
6970 /* if there is an A rate in suppRate IE */
6971 for (i = 0; i < parsed_frm->supportedRates.numRates; i++) {
6972 if (sirIsArate(parsed_frm->supportedRates.rate[i]
6973 & 0x7f)) {
6974 pBssDescr->nwType = eSIR_11G_NW_TYPE;
6975 break;
6976 }
6977 }
6978 if (parsed_frm->extendedRatesPresent)
6979 pBssDescr->nwType = eSIR_11G_NW_TYPE;
6980 } else {
6981 /* 11a packet */
6982 pBssDescr->nwType = eSIR_11A_NW_TYPE;
6983 }
6984 pBssDescr->sinr = 0;
6985 pBssDescr->rssi = -1 * pPrefNetworkFoundInd->rssi;
6986 pBssDescr->beaconInterval = parsed_frm->beaconInterval;
6987 if (!pBssDescr->beaconInterval) {
6988 sms_log(pMac, LOGW, FL("Bcn Interval is Zero , default to 100"
6989 MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pBssDescr->bssId));
6990 pBssDescr->beaconInterval = 100;
6991 }
6992 pBssDescr->timeStamp[0] = parsed_frm->timeStamp[0];
6993 pBssDescr->timeStamp[1] = parsed_frm->timeStamp[1];
6994 pBssDescr->capabilityInfo = *((uint16_t *)&parsed_frm->capabilityInfo);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306995 qdf_mem_copy((uint8_t *) &pBssDescr->bssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006996 (uint8_t *) macHeader->bssId, sizeof(tSirMacAddr));
Anurag Chouhan210db072016-02-22 18:42:15 +05306997 pBssDescr->nReceivedTime = (uint32_t) qdf_mc_timer_get_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006998 sms_log(pMac, LOG2, FL("Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = %d"),
6999 MAC_ADDR_ARRAY(pBssDescr->bssId), pBssDescr->channelId,
7000 pBssDescr->rssi);
7001 /* IEs */
7002 if (uLen) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307003 qdf_mem_copy(&pBssDescr->ieFields,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007004 pPrefNetworkFoundInd->data + (SIR_MAC_HDR_LEN_3A +
7005 SIR_MAC_B_PR_SSID_OFFSET), uLen);
7006 }
7007 local_ie = (tDot11fBeaconIEs *) (pScanResult->Result.pvIes);
7008 status = csr_get_parsed_bss_description_ies(pMac,
7009 &pScanResult->Result.BssDescriptor, &local_ie);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307010 if (!(local_ie || QDF_IS_STATUS_SUCCESS(status))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007011 sms_log(pMac, LOGE, FL("Cannot parse IEs"));
7012 csr_free_scan_result_entry(pMac, pScanResult);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307013 qdf_mem_free(parsed_frm);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307014 return QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007015 }
7016
7017 fDupBss = csr_remove_dup_bss_description(pMac,
7018 &pScanResult->Result.BssDescriptor,
7019 local_ie, &tmpSsid, &timer, false);
7020 /* Check whether we have reach out limit */
7021 if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) {
7022 /* Limit reach */
7023 sms_log(pMac, LOGE, FL("BSS limit reached"));
7024 /* Free the resources */
7025 if ((pScanResult->Result.pvIes == NULL) && local_ie)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307026 qdf_mem_free(local_ie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007027 csr_free_scan_result_entry(pMac, pScanResult);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307028 qdf_mem_free(parsed_frm);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307029 return QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007030 }
Nalla Kartheek4fc57152016-09-05 15:57:49 +05307031
7032 if ((SIR_MAC_MGMT_FRAME == macHeader->fc.type) &&
7033 (SIR_MAC_MGMT_PROBE_RSP == macHeader->fc.subType))
7034 pScanResult->Result.BssDescriptor.fProbeRsp = 1;
7035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007036 /* Add to scan cache */
7037 csr_scan_add_result(pMac, pScanResult, local_ie,
7038 pPrefNetworkFoundInd->sessionId);
7039
7040 if ((pScanResult->Result.pvIes == NULL) && local_ie)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307041 qdf_mem_free(local_ie);
7042 qdf_mem_free(parsed_frm);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307043 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007044}
7045#endif /* FEATURE_WLAN_SCAN_PNO */
7046
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007047void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId)
7048{
7049 tListElem *pEntry = NULL;
7050 tCsrScanResult *pBssDesc = NULL;
7051 tDot11fBeaconIEs *pIes = NULL;
7052 tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
7053 &pMac->roam.neighborRoamInfo[sessionId];
7054
7055 if (0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) {
7056 /*
7057 * Ini file contains neighbor scan channel list, hence NO need
7058 * to build occupied channel list"
7059 */
7060 sms_log(pMac, LOG1, FL("Ini contains neighbor scan ch list"));
7061 return;
7062 }
7063
7064 if (!csr_neighbor_roam_is_new_connected_profile(pMac, sessionId)) {
7065 /*
7066 * Do not flush occupied list since current roam profile matches
7067 * previous
7068 */
7069 sms_log(pMac, LOG2, FL("Current roam profile matches prev"));
7070 return;
7071 }
7072
7073 /* Empty occupied channels here */
7074 pMac->scan.occupiedChannels[sessionId].numChannels = 0;
Kapil Gupta0a2477b2016-08-23 18:00:34 +05307075 pMac->scan.roam_candidate_count[sessionId] = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007076
7077 csr_ll_lock(&pMac->scan.scanResultList);
7078 pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
7079 while (pEntry) {
7080 pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
7081 pIes = (tDot11fBeaconIEs *) (pBssDesc->Result.pvIes);
7082 /* At this time, pBssDescription->Result.pvIes may be NULL */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307083 if (!pIes && !QDF_IS_STATUS_SUCCESS(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007084 csr_get_parsed_bss_description_ies(pMac,
7085 &pBssDesc->Result.BssDescriptor, &pIes)))
7086 continue;
7087 csr_scan_add_to_occupied_channels(pMac, pBssDesc, sessionId,
Kapil Gupta0a2477b2016-08-23 18:00:34 +05307088 &pMac->scan.occupiedChannels[sessionId], pIes,
7089 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007090 /*
7091 * Free the memory allocated for pIes in
7092 * csr_get_parsed_bss_description_ies
7093 */
7094 if ((pBssDesc->Result.pvIes == NULL) && pIes)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307095 qdf_mem_free(pIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007096 pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
7097 LL_ACCESS_NOLOCK);
7098 } /* while */
7099 csr_ll_unlock(&pMac->scan.scanResultList);
7100}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007101
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307102QDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007103 uint32_t sessionId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307104 struct qdf_mac_addr bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007105 uint8_t channel)
7106{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307107 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007108 tDot11fBeaconIEs *pNewIes = NULL;
7109 tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
7110 tSirBssDescription *pNewBssDescriptor = NULL;
7111 uint32_t size = 0;
7112
7113 if (NULL == pSession) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307114 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007115 return status;
7116 }
7117 sms_log(pMac, LOG2, FL("Current bssid::"MAC_ADDRESS_STR),
7118 MAC_ADDR_ARRAY(pSession->pConnectBssDesc->bssId));
7119 sms_log(pMac, LOG2, FL("My bssid::"MAC_ADDRESS_STR" channel %d"),
7120 MAC_ADDR_ARRAY(bssid.bytes), channel);
7121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307122 if (!QDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007123 pMac, pSession->pConnectBssDesc,
7124 &pNewIes))) {
7125 sms_log(pMac, LOGE, FL("Failed to parse IEs"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307126 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007127 goto free_mem;
7128 }
7129 size = pSession->pConnectBssDesc->length +
7130 sizeof(pSession->pConnectBssDesc->length);
7131 if (!size) {
7132 sms_log(pMac, LOGE, FL("length of bss descriptor is 0"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307133 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007134 goto free_mem;
7135 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307136 pNewBssDescriptor = qdf_mem_malloc(size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007137 if (NULL == pNewBssDescriptor) {
7138 sms_log(pMac, LOGE, FL("memory allocation failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307139 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007140 goto free_mem;
7141 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307142 qdf_mem_copy(pNewBssDescriptor, pSession->pConnectBssDesc, size);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007143 /* change the BSSID & channel as passed */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307144 qdf_mem_copy(pNewBssDescriptor->bssId, bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007145 sizeof(tSirMacAddr));
7146 pNewBssDescriptor->channelId = channel;
7147 if (NULL == csr_scan_append_bss_description(pMac, pNewBssDescriptor,
7148 pNewIes, true, sessionId)) {
7149 sms_log(pMac, LOGE,
7150 FL("csr_scan_append_bss_description failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307151 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007152 goto free_mem;
7153 }
7154 sms_log(pMac, LOGE, FL("entry successfully added in scan cache"));
7155
7156free_mem:
7157 if (pNewIes) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307158 qdf_mem_free(pNewIes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007159 }
7160 if (pNewBssDescriptor) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307161 qdf_mem_free(pNewBssDescriptor);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007162 }
7163 return status;
7164}
7165
7166#ifdef FEATURE_WLAN_ESE
7167/* Update the TSF with the difference in system time */
7168void update_cckmtsf(uint32_t *timeStamp0, uint32_t *timeStamp1,
7169 uint32_t *incr)
7170{
7171 uint64_t timeStamp64 = ((uint64_t) *timeStamp1 << 32) | (*timeStamp0);
7172 timeStamp64 = (uint64_t) (timeStamp64 + (uint64_t) *incr);
7173 *timeStamp0 = (uint32_t) (timeStamp64 & 0xffffffff);
7174 *timeStamp1 = (uint32_t) ((timeStamp64 >> 32) & 0xffffffff);
7175}
7176#endif
7177
7178/**
7179 * csr_scan_save_roam_offload_ap_to_scan_cache
7180 * This function parses the received beacon/probe response
7181 * from the firmware as part of the roam synch indication.
7182 * The beacon or the probe response is parsed and is also
7183 * saved into the scan cache
7184 *
7185 * @param pMac Pointer to Global Mac
7186 * @param roam_sync_ind_ptr Roam Synch Indication from
7187 * firmware which also contains the beacon/probe
7188 * response
7189 * @return Status
7190 */
7191#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307192QDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08007193 roam_offload_synch_ind *roam_sync_ind_ptr,
7194 tpSirBssDescription bss_desc_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007195{
7196 uint32_t length = 0;
7197 bool dup_bss;
7198 tDot11fBeaconIEs *ies_local_ptr = NULL;
7199 tAniSSID tmpSsid;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307200 unsigned long timer = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007201 tCsrScanResult *scan_res_ptr = NULL;
7202 uint8_t session_id = roam_sync_ind_ptr->roamedVdevId;
7203
7204 length = roam_sync_ind_ptr->beaconProbeRespLength -
7205 (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307206 scan_res_ptr = qdf_mem_malloc(sizeof(tCsrScanResult) + length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007207 if (scan_res_ptr == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307208 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007209 " fail to allocate memory for frame");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307210 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007211 }
7212
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307213 qdf_mem_zero(scan_res_ptr, sizeof(tCsrScanResult) + length);
7214 qdf_mem_copy(&scan_res_ptr->Result.BssDescriptor,
Varun Reddy Yeturud5939f82015-12-24 18:14:02 -08007215 bss_desc_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007216 (sizeof(tSirBssDescription) + length));
7217 ies_local_ptr = (tDot11fBeaconIEs *)(scan_res_ptr->Result.pvIes);
7218 if (!ies_local_ptr &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307219 (!QDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007220 pMac, &scan_res_ptr->Result.
7221 BssDescriptor,
7222 &ies_local_ptr)))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307223 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007224 "%s:Cannot Parse IEs", __func__);
7225 csr_free_scan_result_entry(pMac, scan_res_ptr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307226 return QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007227 }
7228
7229 dup_bss = csr_remove_dup_bss_description(pMac,
7230 &scan_res_ptr->Result.BssDescriptor,
7231 ies_local_ptr, &tmpSsid, &timer, true);
7232 if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307233 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007234 "%s:BSS Limit Exceed", __func__);
7235 if ((scan_res_ptr->Result.pvIes == NULL) && ies_local_ptr)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307236 qdf_mem_free(ies_local_ptr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007237
7238 csr_free_scan_result_entry(pMac, scan_res_ptr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307239 return QDF_STATUS_E_RESOURCES;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007240 }
7241 csr_scan_add_result(pMac, scan_res_ptr, ies_local_ptr, session_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307242 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007243}
7244#endif
7245
7246/**
7247 * csr_get_bssdescr_from_scan_handle() - This function to extract
7248 * first bss description from scan handle
7249 * @result_handle: an object for the result.
7250 *
7251 * This function is written to extract first bss from scan handle.
7252 *
7253 * Return: first bss descriptor from the scan handle.
7254 */
7255tSirBssDescription*
7256csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle,
7257 tSirBssDescription *bss_descr)
7258{
7259 tListElem *first_element = NULL;
7260 tCsrScanResult *scan_result = NULL;
7261 tScanResultList *bss_list = (tScanResultList *)result_handle;
7262
7263 if (NULL == bss_list) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307264 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007265 FL("Empty bss_list"));
7266 return NULL;
7267 }
7268 if (csr_ll_is_list_empty(&bss_list->List, LL_ACCESS_NOLOCK)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307269 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007270 FL("bss_list->List is empty"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307271 qdf_mem_free(bss_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007272 return NULL;
7273 }
7274 first_element = csr_ll_peek_head(&bss_list->List, LL_ACCESS_NOLOCK);
7275 if (first_element) {
7276 scan_result = GET_BASE_ADDR(first_element,
7277 tCsrScanResult,
7278 Link);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307279 qdf_mem_copy(bss_descr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007280 &scan_result->Result.BssDescriptor,
7281 sizeof(tSirBssDescription));
7282 }
7283 return bss_descr;
7284}
7285
7286/**
7287 * scan_active_list_cmd_timeout_handle() - To handle scan active command timeout
7288 * @userData: scan context
7289 *
7290 * This routine is to handle scan active command timeout
7291 *
7292 * Return: None
7293 */
7294void csr_scan_active_list_timeout_handle(void *userData)
7295{
7296 tSmeCmd *scan_cmd = (tSmeCmd *) userData;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307297 tHalHandle *hal_ctx = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007298 tpAniSirGlobal mac_ctx;
7299 uint16_t scan_id;
7300 tSirSmeScanAbortReq *msg;
7301 uint16_t msg_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307302 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007303
7304 if (scan_cmd == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307305 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007306 FL("Scan Timeout: Scan command is NULL"));
7307 return;
7308 }
Varun Reddy Yeturuf76f6de2015-11-17 21:33:53 -08007309 if (hal_ctx == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307310 QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
Varun Reddy Yeturuf76f6de2015-11-17 21:33:53 -08007311 FL("HAL Context is NULL"));
7312 return;
7313 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007314 mac_ctx = PMAC_STRUCT(hal_ctx);
7315 scan_id = scan_cmd->u.scanCmd.scanID;
7316 sms_log(mac_ctx, LOGE,
7317 FL("Scan Timeout:Sending abort to Firmware ID %d session %d "),
7318 scan_id, scan_cmd->sessionId);
7319 msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307320 msg = qdf_mem_malloc(msg_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007321 if (NULL == msg) {
7322 sms_log(mac_ctx, LOGE,
7323 FL("Failed to alloc memory for SmeScanAbortReq"));
7324 return;
7325 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307326 qdf_mem_zero((void *)msg, msg_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007327 msg->type = eWNI_SME_SCAN_ABORT_IND;
7328 msg->msgLen = msg_len;
7329 msg->sessionId = scan_cmd->sessionId;
7330 msg->scan_id = scan_id;
7331 status = cds_send_mb_message_to_mac(msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307332 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007333 sms_log(mac_ctx, LOGE,
7334 FL(" Failed to post message to LIM"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307335 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007336 }
Sandeep puligillabf3280a2016-04-25 18:43:51 -07007337 csr_save_scan_results(mac_ctx, scan_cmd->u.scanCmd.reason,
7338 scan_cmd->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007339 csr_release_scan_command(mac_ctx, scan_cmd, eCSR_SCAN_FAILURE);
7340 return;
7341}