qcacld-3.0: Initial snapshot of ihelium wlan driver

qcacld-3.0: Initial snapshot of ihelium wlan driver
to match code-scanned SU Release 5.0.0.139. This is
open-source version of wlan for next Android release.

Change-Id: Icf598ca97da74f84bea607e4e902d1889806f507
diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c
new file mode 100644
index 0000000..68f0aee
--- /dev/null
+++ b/core/sme/src/csr/csr_api_scan.c
@@ -0,0 +1,6941 @@
+/*
+ * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+/** ------------------------------------------------------------------------- *
+    ------------------------------------------------------------------------- *
+
+    \file csr_api_scan.c
+
+    Implementation for the Common Scan interfaces.
+   ========================================================================== */
+
+#include "ani_global.h"
+
+#include "cds_mq.h"
+#include "csr_inside_api.h"
+#include "sme_inside.h"
+#include "sms_debug.h"
+
+#include "csr_support.h"
+
+#include "host_diag_core_log.h"
+#include "host_diag_core_event.h"
+
+#include "cds_reg_service.h"
+#include "wma_types.h"
+#include "cds_utils.h"
+#include "cfg_api.h"
+#include "lim_api.h"
+#include "wma.h"
+
+#include "cds_concurrency.h"
+#include "wlan_hdd_main.h"
+
+#define MIN_CHN_TIME_TO_FIND_GO 100
+#define MAX_CHN_TIME_TO_FIND_GO 100
+#define DIRECT_SSID_LEN 7
+
+/* Purpose of HIDDEN_TIMER
+** When we remove hidden ssid from the profile i.e., forget the SSID via GUI that SSID shouldn't see in the profile
+** For above requirement we used timer limit, logic is explained below
+** Timer value is initialsed to current time  when it receives corresponding probe response of hidden SSID (The probe request is
+** received regularly till SSID in the profile. Once it is removed from profile probe request is not sent.) when we receive probe response
+** 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
+** then we are not updating with old one
+*/
+
+#define HIDDEN_TIMER (1*60*1000)
+#define CSR_SCAN_RESULT_RSSI_WEIGHT     80      /* must be less than 100, represent the persentage of new RSSI */
+
+#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL 140
+#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL 120
+
+#define MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 30
+#define MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC 20
+
+#define PCL_ADVANTAGE 30
+#define PCL_RSSI_THRESHOLD -75
+
+#define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)  \
+	((pMac)->scan.nBssLimit <= (csr_ll_count(&(pMac)->scan.scanResultList)))
+
+void csr_scan_get_result_timer_handler(void *);
+static void csr_scan_result_cfg_aging_timer_handler(void *pv);
+static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType,
+					tCsrScanRequest *pScanRequest);
+#ifdef WLAN_AP_STA_CONCURRENCY
+static void csr_sta_ap_conc_timer_handler(void *);
+#endif
+bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId);
+CDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList,
+				    uint8_t NumChannels);
+void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList,
+			      uint32_t cfgId);
+void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode);
+void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList);
+void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
+			      eCsrScanStatus scanStatus);
+static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac, uint8_t *pChannels,
+					  uint8_t numChn,
+					  tSirBssDescription *pBssDesc,
+					  tDot11fBeaconIEs **ppIes);
+bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel);
+void csr_prune_channel_list_for_mode(tpAniSirGlobal pMac,
+				     tCsrChannel *pChannelList);
+
+#define CSR_IS_SOCIAL_CHANNEL(channel) \
+	(((channel) == 1) || ((channel) == 6) || ((channel) == 11))
+
+static void csr_release_scan_cmd_pending_list(tpAniSirGlobal pMac)
+{
+	tListElem *pEntry;
+	tSmeCmd *pCommand;
+
+	while ((pEntry =
+			csr_ll_remove_head(&pMac->scan.scanCmdPendingList,
+					   LL_ACCESS_LOCK)) != NULL) {
+		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+		if (eSmeCsrCommandMask & pCommand->command) {
+			csr_abort_command(pMac, pCommand, true);
+		} else {
+			sms_log(pMac, LOGE, FL("Error: Received command : %d"),
+				pCommand->command);
+		}
+	}
+}
+
+/* pResult is invalid calling this function. */
+void csr_free_scan_result_entry(tpAniSirGlobal pMac, tCsrScanResult *pResult)
+{
+	if (NULL != pResult->Result.pvIes) {
+		cdf_mem_free(pResult->Result.pvIes);
+	}
+	cdf_mem_free(pResult);
+}
+
+static CDF_STATUS csr_ll_scan_purge_result(tpAniSirGlobal pMac,
+					   tDblLinkList *pList)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tListElem *pEntry;
+	tCsrScanResult *pBssDesc;
+
+	csr_ll_lock(pList);
+
+	while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_NOLOCK)) != NULL) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		csr_free_scan_result_entry(pMac, pBssDesc);
+	}
+
+	csr_ll_unlock(pList);
+
+	return status;
+}
+
+CDF_STATUS csr_scan_open(tpAniSirGlobal mac_ctx)
+{
+	CDF_STATUS status;
+
+	csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanResultList);
+	csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.tempScanResults);
+	csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList24);
+	csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.channelPowerInfoList5G);
+#ifdef WLAN_AP_STA_CONCURRENCY
+	csr_ll_open(mac_ctx->hHdd, &mac_ctx->scan.scanCmdPendingList);
+#endif
+	mac_ctx->scan.fFullScanIssued = false;
+	mac_ctx->scan.nBssLimit = CSR_MAX_BSS_SUPPORT;
+#ifdef WLAN_AP_STA_CONCURRENCY
+	status = cdf_mc_timer_init(&mac_ctx->scan.hTimerStaApConcTimer,
+				   CDF_TIMER_TYPE_SW,
+				   csr_sta_ap_conc_timer_handler,
+				   mac_ctx);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE,
+			FL("Mem Alloc failed for hTimerStaApConcTimer timer"));
+		return status;
+	}
+#endif
+	status = cdf_mc_timer_init(&mac_ctx->scan.hTimerResultCfgAging,
+				   CDF_TIMER_TYPE_SW,
+				   csr_scan_result_cfg_aging_timer_handler,
+				   mac_ctx);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		sms_log(mac_ctx, LOGE,
+			FL("Mem Alloc failed for CFG ResultAging timer"));
+
+	return status;
+}
+
+CDF_STATUS csr_scan_close(tpAniSirGlobal pMac)
+{
+	csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults);
+	csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList);
+#ifdef WLAN_AP_STA_CONCURRENCY
+	csr_release_scan_cmd_pending_list(pMac);
+#endif
+	csr_ll_close(&pMac->scan.scanResultList);
+	csr_ll_close(&pMac->scan.tempScanResults);
+#ifdef WLAN_AP_STA_CONCURRENCY
+	csr_ll_close(&pMac->scan.scanCmdPendingList);
+#endif
+	csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList24);
+	csr_purge_channel_power(pMac, &pMac->scan.channelPowerInfoList5G);
+	csr_ll_close(&pMac->scan.channelPowerInfoList24);
+	csr_ll_close(&pMac->scan.channelPowerInfoList5G);
+	csr_scan_disable(pMac);
+	cdf_mc_timer_destroy(&pMac->scan.hTimerResultCfgAging);
+#ifdef WLAN_AP_STA_CONCURRENCY
+	cdf_mc_timer_destroy(&pMac->scan.hTimerStaApConcTimer);
+#endif
+	return CDF_STATUS_SUCCESS;
+}
+
+CDF_STATUS csr_scan_enable(tpAniSirGlobal pMac)
+{
+
+	pMac->scan.fScanEnable = true;
+
+	return CDF_STATUS_SUCCESS;
+}
+
+CDF_STATUS csr_scan_disable(tpAniSirGlobal pMac)
+{
+
+	csr_scan_stop_timers(pMac);
+	pMac->scan.fScanEnable = false;
+
+	return CDF_STATUS_SUCCESS;
+}
+
+/* Set scan timing parameters according to state of other driver sessions */
+/* No validation of the parameters is performed. */
+static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanType,
+					tCsrScanRequest *pScanRequest)
+{
+#ifdef WLAN_AP_STA_CONCURRENCY
+	if (csr_is_any_session_connected(pMac)) {
+		/* Reset passive scan time as per ini parameter. */
+		cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
+			    pMac->roam.configParam.nPassiveMaxChnTimeConc);
+		/* If multi-session, use the appropriate default scan times */
+		if (scanType == eSIR_ACTIVE_SCAN) {
+			pScanRequest->maxChnTime =
+				pMac->roam.configParam.nActiveMaxChnTimeConc;
+			pScanRequest->minChnTime =
+				pMac->roam.configParam.nActiveMinChnTimeConc;
+		} else {
+			pScanRequest->maxChnTime =
+				pMac->roam.configParam.nPassiveMaxChnTimeConc;
+			pScanRequest->minChnTime =
+				pMac->roam.configParam.nPassiveMinChnTimeConc;
+		}
+		pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc;
+
+		/* Return so that fields set above will not be overwritten. */
+		return;
+	}
+#endif
+
+	/* This portion of the code executed if multi-session not supported */
+	/* (WLAN_AP_STA_CONCURRENCY not defined) or no multi-session. */
+	/* Use the "regular" (non-concurrency) default scan timing. */
+	cfg_set_int(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
+		    pMac->roam.configParam.nPassiveMaxChnTime);
+	if (pScanRequest->scanType == eSIR_ACTIVE_SCAN) {
+		pScanRequest->maxChnTime =
+			pMac->roam.configParam.nActiveMaxChnTime;
+		pScanRequest->minChnTime =
+			pMac->roam.configParam.nActiveMinChnTime;
+	} else {
+		pScanRequest->maxChnTime =
+			pMac->roam.configParam.nPassiveMaxChnTime;
+		pScanRequest->minChnTime =
+			pMac->roam.configParam.nPassiveMinChnTime;
+	}
+#ifdef WLAN_AP_STA_CONCURRENCY
+	/* No rest time if no sessions are connected. */
+	pScanRequest->restTime = 0;
+#endif
+}
+
+/**
+ * csr_scan_2g_only_request() - This function will update the scan request with
+ * only 2.4GHz valid channel list.
+ * @mac_ctx:      Pointer to Global MAC structure
+ * @scan_cmd      scan cmd
+ * @scan_req      scan req
+ *
+ * This function will update the scan request with  only 2.4GHz valid channel
+ * list.
+ *
+ * @Return: status of operation
+ */
+static CDF_STATUS
+csr_scan_2g_only_request(tpAniSirGlobal mac_ctx,
+			 tSmeCmd *scan_cmd,
+			 tCsrScanRequest *scan_req)
+{
+	uint8_t idx, lst_sz = 0;
+
+	CDF_ASSERT(scan_cmd && scan_req);
+	/* To silence the KW tool null check is added */
+	if ((scan_cmd == NULL) || (scan_req == NULL)) {
+		sms_log(mac_ctx, LOGE,
+			FL(" Scan Cmd or Scan Request is NULL "));
+		return CDF_STATUS_E_INVAL;
+	}
+
+	if (eCSR_SCAN_REQUEST_FULL_SCAN != scan_req->requestType)
+		return CDF_STATUS_SUCCESS;
+
+	sms_log(mac_ctx, LOG1,
+		FL("Scanning only 2G Channels during first scan"));
+
+	/* Contsruct valid Supported 2.4 GHz Channel List */
+	if (NULL == scan_req->ChannelInfo.ChannelList) {
+		scan_req->ChannelInfo.ChannelList =
+			cdf_mem_malloc(NUM_24GHZ_CHANNELS);
+		if (NULL == scan_req->ChannelInfo.ChannelList) {
+			sms_log(mac_ctx, LOGE, FL("Memory allocation failed."));
+			return CDF_STATUS_E_NOMEM;
+		}
+		for (idx = 1; idx <= NUM_24GHZ_CHANNELS; idx++) {
+			if (csr_is_supported_channel(mac_ctx, idx)) {
+				scan_req->ChannelInfo.ChannelList[lst_sz] = idx;
+				lst_sz++;
+			}
+		}
+	} else {
+		for (idx = 0;
+		     idx < scan_req->ChannelInfo.numOfChannels;
+		     idx++) {
+			if (scan_req->ChannelInfo.ChannelList[idx] <=
+				CDS_24_GHZ_CHANNEL_14
+			    && csr_is_supported_channel(mac_ctx,
+				scan_req->ChannelInfo.ChannelList[idx])) {
+				scan_req->ChannelInfo.ChannelList[lst_sz] =
+					scan_req->ChannelInfo.ChannelList[idx];
+				lst_sz++;
+			}
+		}
+	}
+	scan_req->ChannelInfo.numOfChannels = lst_sz;
+	return CDF_STATUS_SUCCESS;
+}
+
+static void
+csr_set_scan_reason(tSmeCmd *scan_cmd, eCsrRequestType req_type)
+{
+	switch (req_type) {
+	case eCSR_SCAN_REQUEST_11D_SCAN:
+		scan_cmd->u.scanCmd.reason = eCsrScan11d1;
+		break;
+#ifdef SOFTAP_CHANNEL_RANGE
+	case eCSR_SCAN_SOFTAP_CHANNEL_RANGE:
+#endif
+	case eCSR_SCAN_REQUEST_FULL_SCAN:
+	case eCSR_SCAN_P2P_DISCOVERY:
+		scan_cmd->u.scanCmd.reason = eCsrScanUserRequest;
+		break;
+	case eCSR_SCAN_HO_PROBE_SCAN:
+		scan_cmd->u.scanCmd.reason = eCsrScanProbeBss;
+		break;
+	case eCSR_SCAN_P2P_FIND_PEER:
+		scan_cmd->u.scanCmd.reason = eCsrScanP2PFindPeer;
+		break;
+	default:
+		break;
+	}
+}
+
+static CDF_STATUS
+csr_issue_11d_scan(tpAniSirGlobal mac_ctx, tSmeCmd *scan_cmd,
+		   tCsrScanRequest *scan_req, uint16_t session_id)
+{
+	CDF_STATUS status;
+	tSmeCmd *scan_11d_cmd = NULL;
+	tCsrScanRequest tmp_rq;
+	tCsrChannelInfo *pChnInfo = &tmp_rq.ChannelInfo;
+	uint32_t numChn = mac_ctx->scan.base_channels.numChannels;
+	tCsrRoamSession *csr_session = CSR_GET_SESSION(mac_ctx, session_id);
+
+	if (csr_session == NULL) {
+		sms_log(mac_ctx, LOGE, FL("session %d not found"),
+			session_id);
+		CDF_ASSERT(0);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	if (!(((false == mac_ctx->first_scan_done)
+	     && (eCSR_SCAN_REQUEST_11D_SCAN != scan_req->requestType))
+#ifdef SOFTAP_CHANNEL_RANGE
+	    && (eCSR_SCAN_SOFTAP_CHANNEL_RANGE != scan_req->requestType)
+#endif
+	    && (false == mac_ctx->scan.fEnableBypass11d)))
+		return CDF_STATUS_SUCCESS;
+
+	cdf_mem_set(&tmp_rq, sizeof(tCsrScanRequest), 0);
+	scan_11d_cmd = csr_get_command_buffer(mac_ctx);
+	if (!scan_11d_cmd) {
+		sms_log(mac_ctx, LOGE, FL("scan_11d_cmd failed"));
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	cdf_mem_set(&scan_11d_cmd->u.scanCmd, sizeof(tScanCmd), 0);
+	pChnInfo->ChannelList = cdf_mem_malloc(numChn);
+	if (NULL == pChnInfo->ChannelList) {
+		sms_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
+		return CDF_STATUS_E_NOMEM;
+	}
+	cdf_mem_copy(pChnInfo->ChannelList,
+		     mac_ctx->scan.base_channels.channelList, numChn);
+
+	pChnInfo->numOfChannels = (uint8_t) numChn;
+	scan_11d_cmd->command = eSmeCommandScan;
+	scan_11d_cmd->u.scanCmd.callback = mac_ctx->scan.callback11dScanDone;
+	scan_11d_cmd->u.scanCmd.pContext = NULL;
+	wma_get_scan_id(&scan_11d_cmd->u.scanCmd.scanID);
+	tmp_rq.BSSType = eCSR_BSS_TYPE_ANY;
+	tmp_rq.scan_id = scan_11d_cmd->u.scanCmd.scanID;
+
+	status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
+			CDF_TIMER_TYPE_SW,
+			csr_scan_active_list_timeout_handle, &scan_11d_cmd);
+
+	if (csr_is11d_supported(mac_ctx)) {
+		tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan;
+		if (scan_req->bcnRptReqScan)
+			tmp_rq.scanType = scan_req->scanType ?
+				eSIR_PASSIVE_SCAN : scan_req->scanType;
+		else
+			tmp_rq.scanType = eSIR_PASSIVE_SCAN;
+		tmp_rq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
+		scan_11d_cmd->u.scanCmd.reason = eCsrScan11d1;
+		tmp_rq.maxChnTime =
+			mac_ctx->roam.configParam.nPassiveMaxChnTime;
+		tmp_rq.minChnTime =
+			mac_ctx->roam.configParam.nPassiveMinChnTime;
+	} else {
+		tmp_rq.bcnRptReqScan = scan_req->bcnRptReqScan;
+		if (scan_req->bcnRptReqScan)
+			tmp_rq.scanType = scan_req->scanType;
+		else
+			tmp_rq.scanType = eSIR_ACTIVE_SCAN;
+		tmp_rq.requestType = scan_req->requestType;
+		scan_11d_cmd->u.scanCmd.reason = scan_cmd->u.scanCmd.reason;
+		tmp_rq.maxChnTime = mac_ctx->roam.configParam.nActiveMaxChnTime;
+		tmp_rq.minChnTime = mac_ctx->roam.configParam.nActiveMinChnTime;
+	}
+	if (mac_ctx->roam.configParam.nInitialDwellTime) {
+		tmp_rq.maxChnTime = mac_ctx->roam.configParam.nInitialDwellTime;
+		sms_log(mac_ctx, LOG1, FL("11d scan, updating dwell time for first scan %u"),
+			tmp_rq.maxChnTime);
+	}
+
+	status = csr_scan_copy_request(mac_ctx,
+			&scan_11d_cmd->u.scanCmd.u.scanRequest, &tmp_rq);
+	/* Free the channel list */
+	cdf_mem_free(pChnInfo->ChannelList);
+	pChnInfo->ChannelList = NULL;
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE, FL("csr_scan_copy_request failed"));
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	mac_ctx->scan.scanProfile.numOfChannels =
+		scan_11d_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+
+
+	status = csr_queue_sme_command(mac_ctx, scan_11d_cmd, false);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE, FL("Failed to send message status = %d"),
+			status);
+		return CDF_STATUS_E_FAILURE;
+	}
+	return CDF_STATUS_SUCCESS;
+}
+
+CDF_STATUS csr_scan_request(tpAniSirGlobal pMac, uint16_t sessionId,
+			    tCsrScanRequest *scan_req,
+			    csr_scan_completeCallback callback, void *pContext)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tSmeCmd *scan_cmd = NULL;
+	tCsrScanRequest *pTempScanReq = NULL;
+	tCsrConfig *cfg_prm = &pMac->roam.configParam;
+
+	if (scan_req == NULL) {
+		sms_log(pMac, LOGE, FL("scan_req is NULL"));
+		CDF_ASSERT(0);
+		return status;
+	}
+
+	/*
+	 * During group formation, the P2P client scans for GO with the specific
+	 * SSID. There will be chances of GO switching to other channels because
+	 * of scan or to STA channel in case of STA+GO MCC scenario. So to
+	 * increase the possibility of client to find the GO, the dwell time of
+	 * scan is increased to 100ms.
+	 * If the scan request is for specific SSId the length of SSID will be
+	 * greater than 7 as SSID for p2p search contains "DIRECT-")
+	 */
+	if (scan_req->p2pSearch
+	    && scan_req->SSIDs.numOfSSIDs
+	    && (NULL != scan_req->SSIDs.SSIDList)
+	    && (scan_req->SSIDs.SSIDList->SSID.length > DIRECT_SSID_LEN)) {
+		sms_log(pMac, LOG1, FL("P2P: Increasing the min and max Dwell time to %d for specific SSID scan %.*s"),
+			MAX_CHN_TIME_TO_FIND_GO,
+			scan_req->SSIDs.SSIDList->SSID.length,
+			scan_req->SSIDs.SSIDList->SSID.ssId);
+		scan_req->maxChnTime = MAX_CHN_TIME_TO_FIND_GO;
+		scan_req->minChnTime = MIN_CHN_TIME_TO_FIND_GO;
+	}
+
+	if (!pMac->scan.fScanEnable) {
+		sms_log(pMac, LOGE, FL("SId: %d Scanning not enabled Scan type=%u, numOfSSIDs=%d P2P search=%d"),
+			sessionId, scan_req->requestType,
+			scan_req->SSIDs.numOfSSIDs,
+			scan_req->p2pSearch);
+		goto release_cmd;
+	}
+
+	scan_cmd = csr_get_command_buffer(pMac);
+	if (!scan_cmd) {
+		sms_log(pMac, LOGE, FL("scan_cmd is NULL"));
+		goto release_cmd;
+	}
+
+	cdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0);
+	scan_cmd->command = eSmeCommandScan;
+	scan_cmd->sessionId = sessionId;
+	if (scan_cmd->sessionId >= CSR_ROAM_SESSION_MAX)
+		sms_log(pMac, LOGE, FL("Invalid Sme SessionID: %d"), sessionId);
+	scan_cmd->u.scanCmd.callback = callback;
+	scan_cmd->u.scanCmd.pContext = pContext;
+	csr_set_scan_reason(scan_cmd, scan_req->requestType);
+	if (scan_req->minChnTime == 0 && scan_req->maxChnTime == 0) {
+		/* The caller doesn't set the time correctly. Set it here */
+		csr_set_default_scan_timing(pMac, scan_req->scanType, scan_req);
+		sms_log(pMac, LOG1,
+			FL("Setting default min %d and max %d ChnTime"),
+			scan_req->minChnTime, scan_req->maxChnTime);
+	}
+#ifdef WLAN_AP_STA_CONCURRENCY
+	/* Need to set restTime only if at least one session is connected */
+	if (scan_req->restTime == 0 && csr_is_any_session_connected(pMac)) {
+		scan_req->restTime = cfg_prm->nRestTimeConc;
+		if (scan_req->scanType == eSIR_ACTIVE_SCAN) {
+			scan_req->maxChnTime = cfg_prm->nActiveMaxChnTimeConc;
+			scan_req->minChnTime = cfg_prm->nActiveMinChnTimeConc;
+		} else {
+			scan_req->maxChnTime = cfg_prm->nPassiveMaxChnTimeConc;
+			scan_req->minChnTime = cfg_prm->nPassiveMinChnTimeConc;
+		}
+	}
+#endif
+	/* Increase dwell time in case P2P Search and Miracast is not present */
+	if (scan_req->p2pSearch && scan_req->ChannelInfo.numOfChannels
+	    == P2P_SOCIAL_CHANNELS && (!(pMac->sme.miracast_value))) {
+		scan_req->maxChnTime += P2P_SEARCH_DWELL_TIME_INCREASE;
+	}
+	scan_cmd->u.scanCmd.scanID = scan_req->scan_id;
+	/*
+	 * If it is the first scan request from HDD, CSR checks if it is for 11d
+	 * If it is not, CSR will save the scan request in the pending cmd queue
+	 * & issue an 11d scan request to PE.
+	 */
+	status = csr_issue_11d_scan(pMac, scan_cmd, scan_req, sessionId);
+	if (status != CDF_STATUS_SUCCESS)
+		goto release_cmd;
+
+	/*
+	 * Scan only 2G Channels if set in ini file. This is mainly to reduce
+	 * the First Scan duration once we turn on Wifi
+	 */
+	if (pMac->scan.fFirstScanOnly2GChnl
+	    && false == pMac->first_scan_done) {
+		csr_scan_2g_only_request(pMac, scan_cmd, scan_req);
+		pMac->first_scan_done = true;
+	}
+
+
+	if (cfg_prm->nInitialDwellTime) {
+		scan_req->maxChnTime = cfg_prm->nInitialDwellTime;
+		cfg_prm->nInitialDwellTime = 0;
+		sms_log(pMac, LOG1, FL("updating dwell time for first scan %u"),
+			scan_req->maxChnTime);
+	}
+
+	status = csr_scan_copy_request(pMac, &scan_cmd->u.scanCmd.u.scanRequest,
+				       scan_req);
+	/*
+	 * Reset the variable after the first scan is  queued after loading the
+	 * driver. The purpose of this parameter is that DFS channels are
+	 * skipped during the first scan after loading the driver. The above API
+	 * builds the target scan request in which this variable is used.
+	 */
+	cfg_prm->initial_scan_no_dfs_chnl = 0;
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(pMac, LOGE,
+			FL("fail to copy request status = %d"), status);
+		goto release_cmd;
+	}
+
+	pTempScanReq = &scan_cmd->u.scanCmd.u.scanRequest;
+	pMac->scan.scanProfile.numOfChannels =
+		pTempScanReq->ChannelInfo.numOfChannels;
+	status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
+				CDF_TIMER_TYPE_SW,
+				csr_scan_active_list_timeout_handle, scan_cmd);
+	sms_log(pMac, LOG1,
+		FL("SId=%d scanId=%d Scan reason=%u numSSIDs=%d numChan=%d P2P search=%d minCT=%d maxCT=%d uIEFieldLen=%d"),
+		sessionId, scan_cmd->u.scanCmd.scanID,
+		scan_cmd->u.scanCmd.reason, pTempScanReq->SSIDs.numOfSSIDs,
+		pTempScanReq->ChannelInfo.numOfChannels,
+		pTempScanReq->p2pSearch, pTempScanReq->minChnTime,
+		pTempScanReq->maxChnTime, pTempScanReq->uIEFieldLen);
+
+	status = csr_queue_sme_command(pMac, scan_cmd, false);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(pMac, LOGE,
+			FL("fail to send message status = %d"), status);
+	}
+
+release_cmd:
+	if (!CDF_IS_STATUS_SUCCESS(status) && scan_cmd) {
+		sms_log(pMac, LOGE, FL(" SId: %d Failed with status=%d"
+				       " Scan reason=%u numOfSSIDs=%d"
+				       " P2P search=%d scanId=%d"),
+			sessionId, status, scan_cmd->u.scanCmd.reason,
+			scan_req->SSIDs.numOfSSIDs, scan_req->p2pSearch,
+			scan_cmd->u.scanCmd.scanID);
+		csr_release_command_scan(pMac, scan_cmd);
+	}
+
+	return status;
+}
+
+CDF_STATUS csr_issue_roam_after_lostlink_scan(tpAniSirGlobal pMac,
+					      uint32_t sessionId,
+					      eCsrRoamReason reason)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tScanResultHandle hBSSList = NULL;
+	tCsrScanResultFilter *pScanFilter = NULL;
+	uint32_t roamId = 0;
+	tCsrRoamProfile *pProfile = NULL;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOG1, FL("Entry"));
+	if (pSession->fCancelRoaming) {
+		sms_log(pMac, LOGW, FL("lost link roaming canceled"));
+		status = CDF_STATUS_SUCCESS;
+		goto free_filter;
+	}
+	/* Here is the profile we need to connect to */
+	pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
+	if (NULL == pScanFilter) {
+		status = CDF_STATUS_E_NOMEM;
+		goto free_filter;
+	}
+	cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
+	if (NULL == pSession->pCurRoamProfile) {
+		pScanFilter->EncryptionType.numEntries = 1;
+		pScanFilter->EncryptionType.encryptionType[0] =
+			eCSR_ENCRYPT_TYPE_NONE;
+	} else {
+		/*
+		 * We have to make a copy of pCurRoamProfile because it will
+		 * be free inside csr_roam_issue_connect
+		 */
+		pProfile = cdf_mem_malloc(sizeof(tCsrRoamProfile));
+		if (NULL == pProfile) {
+			status = CDF_STATUS_E_NOMEM;
+			goto free_filter;
+		}
+		cdf_mem_set(pProfile, sizeof(tCsrRoamProfile), 0);
+		status = csr_roam_copy_profile(pMac, pProfile,
+					       pSession->pCurRoamProfile);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			goto free_filter;
+		status = csr_roam_prepare_filter_from_profile(pMac, pProfile,
+							      pScanFilter);
+	} /* We have a profile */
+	roamId = GET_NEXT_ROAM_ID(&pMac->roam);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto free_filter;
+
+	status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto free_filter;
+
+	if (eCsrLostLink1 == reason) {
+		/* if possible put the last connected BSS in beginning */
+		csr_move_bss_to_head_from_bssid(pMac,
+				&pSession->connectedProfile.bssid, hBSSList);
+	}
+	status = csr_roam_issue_connect(pMac, sessionId, pProfile, hBSSList,
+					reason, roamId, true, true);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		csr_scan_result_purge(pMac, hBSSList);
+	}
+
+free_filter:
+	if (pScanFilter) {
+		/* we need to free memory for filter if profile exists */
+		csr_free_scan_filter(pMac, pScanFilter);
+		cdf_mem_free(pScanFilter);
+	}
+	if (NULL != pProfile) {
+		csr_release_profile(pMac, pProfile);
+		cdf_mem_free(pProfile);
+	}
+	return status;
+}
+
+CDF_STATUS csr_scan_handle_failed_lostlink1(tpAniSirGlobal pMac,
+					    uint32_t sessionId)
+{
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+	sms_log(pMac, LOGW, "Lost link scan 1 failed");
+	if (pSession->fCancelRoaming)
+		return CDF_STATUS_E_FAILURE;
+	if (!pSession->pCurRoamProfile)
+		return csr_scan_request_lost_link3(pMac, sessionId);
+	/*
+	 * We fail lostlink1 but there may be other BSS in the cached result
+	 * fit the profile. Give it a try first
+	 */
+	if (pSession->pCurRoamProfile->SSIDs.numOfSSIDs == 0 ||
+	    pSession->pCurRoamProfile->SSIDs.numOfSSIDs > 1)
+		/* try lostlink scan2 */
+		return csr_scan_request_lost_link2(pMac, sessionId);
+	if (!pSession->pCurRoamProfile->ChannelInfo.ChannelList
+	    || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) {
+		/* go straight to lostlink scan3 */
+		return csr_scan_request_lost_link3(pMac, sessionId);
+	}
+	return CDF_STATUS_SUCCESS;
+}
+
+CDF_STATUS csr_scan_handle_failed_lostlink2(tpAniSirGlobal pMac,
+					    uint32_t sessionId)
+{
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOGW, "Lost link scan 2 failed");
+	if (pSession->fCancelRoaming)
+		return CDF_STATUS_E_FAILURE;
+
+	if (!pSession->pCurRoamProfile
+	    || !pSession->pCurRoamProfile->ChannelInfo.ChannelList
+	    || pSession->pCurRoamProfile->ChannelInfo.ChannelList[0] == 0) {
+		/* try lostlink scan3 */
+		return csr_scan_request_lost_link3(pMac, sessionId);
+	}
+	return CDF_STATUS_E_FAILURE;
+}
+
+CDF_STATUS csr_scan_handle_failed_lostlink3(tpAniSirGlobal pMac,
+					    uint32_t sessionId)
+{
+	sms_log(pMac, LOGW, "Lost link scan 3 failed");
+	return CDF_STATUS_SUCCESS;
+}
+
+static CDF_STATUS
+csr_update_lost_link1_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
+			  tCsrRoamSession *pSession, uint32_t session_id)
+{
+	uint8_t i, num_ch = 0;
+	tScanResultHandle bss_lst = NULL;
+	tCsrScanResultInfo *scan_result = NULL;
+	tCsrScanResultFilter *scan_filter = NULL;
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tCsrSSIDs *ssid_list = &cmd->u.scanCmd.u.scanRequest.SSIDs;
+	tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo;
+
+	cmd->command = eSmeCommandScan;
+	cmd->sessionId = (uint8_t) session_id;
+	cmd->u.scanCmd.reason = eCsrScanLostLink1;
+	cmd->u.scanCmd.callback = NULL;
+	cmd->u.scanCmd.pContext = NULL;
+	cmd->u.scanCmd.u.scanRequest.maxChnTime =
+		mac_ctx->roam.configParam.nActiveMaxChnTime;
+	cmd->u.scanCmd.u.scanRequest.minChnTime =
+		mac_ctx->roam.configParam.nActiveMinChnTime;
+	cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+	wma_get_scan_id(&cmd->u.scanCmd.scanID);
+	status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
+			CDF_TIMER_TYPE_SW,
+			csr_scan_active_list_timeout_handle, &cmd);
+	cmd->u.scanCmd.u.scanRequest.scan_id =
+		cmd->u.scanCmd.scanID;
+
+	if (pSession->connectedProfile.SSID.length) {
+		/*
+		 * on error: following memory will be released by call to
+		 * csr_release_command_scan in the end
+		 */
+		ssid_list->SSIDList = cdf_mem_malloc(sizeof(tCsrSSIDInfo));
+		if (NULL == ssid_list->SSIDList)
+			return CDF_STATUS_E_NOMEM;
+		ssid_list->numOfSSIDs = 1;
+		cdf_mem_copy(&ssid_list->SSIDList[0].SSID,
+			     &pSession->connectedProfile.SSID,
+			     sizeof(tSirMacSSid));
+	} else {
+		ssid_list->numOfSSIDs = 0;
+	}
+
+	if (!pSession->pCurRoamProfile)
+		return CDF_STATUS_SUCCESS;
+
+	scan_filter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
+	if (NULL == scan_filter)
+		return CDF_STATUS_E_NOMEM;
+
+	cdf_mem_set(scan_filter, sizeof(tCsrScanResultFilter), 0);
+	status = csr_roam_prepare_filter_from_profile(mac_ctx,
+			pSession->pCurRoamProfile, scan_filter);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto free_lost_link1_local_mem;
+
+	if (!(CDF_IS_STATUS_SUCCESS(csr_scan_get_result(mac_ctx, scan_filter,
+		&bss_lst)) && bss_lst)) {
+		if (csr_roam_is_channel_valid(mac_ctx,
+			pSession->connectedProfile.operationChannel)) {
+			ch_info->ChannelList = cdf_mem_malloc(1);
+			if (NULL == ch_info->ChannelList) {
+				status = CDF_STATUS_E_NOMEM;
+				goto free_lost_link1_local_mem;
+			}
+			ch_info->ChannelList[0] =
+				pSession->connectedProfile.operationChannel;
+			ch_info->numOfChannels = 1;
+		}
+		return status;
+	}
+
+	/* on error: this mem will be released by csr_release_command_scan */
+	ch_info->ChannelList = cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN);
+	if (NULL == ch_info->ChannelList) {
+		status = CDF_STATUS_E_NOMEM;
+		goto free_lost_link1_local_mem;
+	}
+
+	scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
+	while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) {
+		for (i = 0; i < num_ch; i++) {
+			if (ch_info->ChannelList[i] ==
+				scan_result->BssDescriptor.channelId)
+				break;
+		}
+		if (i == num_ch)
+			ch_info->ChannelList[num_ch++] =
+				scan_result->BssDescriptor.channelId;
+		scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
+	}
+	/* Include the last connected BSS' channel */
+	if (csr_roam_is_channel_valid(mac_ctx,
+		pSession->connectedProfile.operationChannel)) {
+		for (i = 0; i < num_ch; i++) {
+			if (ch_info->ChannelList[i] ==
+				pSession->connectedProfile.operationChannel)
+				break;
+		}
+		if (i == num_ch)
+			ch_info->ChannelList[num_ch++] =
+				pSession->connectedProfile.operationChannel;
+	}
+	ch_info->numOfChannels = num_ch;
+free_lost_link1_local_mem:
+	if (scan_filter) {
+		csr_free_scan_filter(mac_ctx, scan_filter);
+		cdf_mem_free(scan_filter);
+	}
+	if (bss_lst)
+		csr_scan_result_purge(mac_ctx, bss_lst);
+	return status;
+}
+
+/**
+ * csr_scan_request_lost_link1() - start scan on link lost 1
+ * @mac_ctx:       mac global context
+ * @session_id:    session id
+ *
+ * Lostlink1 scan is to actively scan the last connected profile's SSID on all
+ * matched BSS channels. If no roam profile (it should not), it is like
+ * lostlinkscan3
+ *
+ * Return: status of operation
+ */
+CDF_STATUS
+csr_scan_request_lost_link1(tpAniSirGlobal mac_ctx, uint32_t session_id)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tSmeCmd *cmd = NULL;
+	tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
+
+	if (!session) {
+		sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(mac_ctx, LOGW, FL("Entry"));
+	cmd = csr_get_command_buffer(mac_ctx);
+	if (!cmd) {
+		status = CDF_STATUS_E_RESOURCES;
+		goto release_lost_link1_cmd;
+	}
+	cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
+	status = csr_update_lost_link1_cmd(mac_ctx, cmd, session, session_id);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto release_lost_link1_cmd;
+
+	cdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid,
+		    sizeof(struct cdf_mac_addr), 0xFF);
+	status = csr_queue_sme_command(mac_ctx, cmd, false);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE,
+			FL("fail to send message status = %d"), status);
+	}
+
+release_lost_link1_cmd:
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
+		if (cmd)
+			csr_release_command_scan(mac_ctx, cmd);
+		status = csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
+	}
+	return status;
+}
+
+static CDF_STATUS
+csr_update_lost_link2_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *cmd,
+			  uint32_t session_id, tCsrRoamSession *session)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	uint8_t i, num_ch = 0;
+	tScanResultHandle bss_lst = NULL;
+	tCsrScanResultInfo *scan_result = NULL;
+	tCsrScanResultFilter *scan_fltr = NULL;
+	tCsrChannelInfo *ch_info = &cmd->u.scanCmd.u.scanRequest.ChannelInfo;
+
+	cmd->command = eSmeCommandScan;
+	cmd->sessionId = (uint8_t) session_id;
+	cmd->u.scanCmd.reason = eCsrScanLostLink2;
+	cmd->u.scanCmd.callback = NULL;
+	cmd->u.scanCmd.pContext = NULL;
+	cmd->u.scanCmd.u.scanRequest.maxChnTime =
+		mac_ctx->roam.configParam.nActiveMaxChnTime;
+	cmd->u.scanCmd.u.scanRequest.minChnTime =
+		mac_ctx->roam.configParam.nActiveMinChnTime;
+	cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+	wma_get_scan_id(&cmd->u.scanCmd.scanID);
+	cmd->u.scanCmd.u.scanRequest.scan_id =
+		cmd->u.scanCmd.scanID;
+	if (!session->pCurRoamProfile)
+		return CDF_STATUS_SUCCESS;
+	status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
+			CDF_TIMER_TYPE_SW,
+			csr_scan_active_list_timeout_handle, &cmd);
+	scan_fltr = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
+	if (NULL == scan_fltr)
+		return CDF_STATUS_E_NOMEM;
+
+	cdf_mem_set(scan_fltr, sizeof(tCsrScanResultFilter), 0);
+	status = csr_roam_prepare_filter_from_profile(mac_ctx,
+				session->pCurRoamProfile, scan_fltr);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto free_lost_link2_local_mem;
+
+	status = csr_scan_get_result(mac_ctx, scan_fltr, &bss_lst);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto free_lost_link2_local_mem;
+
+	if (!bss_lst)
+		goto free_lost_link2_local_mem;
+
+	ch_info->ChannelList = cdf_mem_malloc(WNI_CFG_VALID_CHANNEL_LIST_LEN);
+	if (NULL == ch_info->ChannelList) {
+		status = CDF_STATUS_E_NOMEM;
+		goto free_lost_link2_local_mem;
+	}
+	scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
+	while (scan_result != NULL && num_ch < WNI_CFG_VALID_CHANNEL_LIST_LEN) {
+		for (i = 0; i < num_ch; i++) {
+			if (ch_info->ChannelList[i] ==
+				scan_result->BssDescriptor.channelId)
+				break;
+		}
+		if (i == num_ch)
+			ch_info->ChannelList[num_ch++] =
+				scan_result->BssDescriptor.channelId;
+		scan_result = csr_scan_result_get_next(mac_ctx, bss_lst);
+	}
+	ch_info->numOfChannels = num_ch;
+
+free_lost_link2_local_mem:
+	if (scan_fltr) {
+		csr_free_scan_filter(mac_ctx, scan_fltr);
+		cdf_mem_free(scan_fltr);
+	}
+	if (bss_lst)
+		csr_scan_result_purge(mac_ctx, bss_lst);
+	return status;
+}
+
+/**
+ * csr_scan_request_lost_link2() - start scan on link lost 2
+ * @mac_ctx:       mac global context
+ * @session_id:    session id
+ *
+ * Lostlink2 scan is to actively scan the all SSIDs of the last roaming
+ * profile's on all matched BSS channels. Since MAC doesn't support multiple
+ * SSID, we scan all SSIDs and filter them afterwards
+ *
+ * Return: status of operation
+ */
+CDF_STATUS
+csr_scan_request_lost_link2(tpAniSirGlobal mac_ctx, uint32_t session_id)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tSmeCmd *cmd = NULL;
+	tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
+
+	if (!session) {
+		sms_log(mac_ctx, LOGE, FL("session %d not found"), session_id);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(mac_ctx, LOGW, FL(" called"));
+	cmd = csr_get_command_buffer(mac_ctx);
+	if (!cmd) {
+		status = CDF_STATUS_E_RESOURCES;
+		goto release_lost_link2_cmd;
+	}
+	cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
+	status = csr_update_lost_link2_cmd(mac_ctx, cmd, session_id, session);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto release_lost_link2_cmd;
+
+	cdf_mem_set(&cmd->u.scanCmd.u.scanRequest.bssid,
+		    sizeof(struct cdf_mac_addr), 0xFF);
+	/* Put to the head in pending queue */
+	status = csr_queue_sme_command(mac_ctx, cmd, true);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE,
+			FL("fail to send message status = %d"), status);
+		goto release_lost_link2_cmd;
+	}
+
+release_lost_link2_cmd:
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
+		if (cmd)
+			csr_release_command_scan(mac_ctx, cmd);
+		status = csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
+	}
+	return status;
+}
+
+/**
+ * csr_scan_request_lost_link3() - To actively scan all valid channels
+ * @mac_ctx:       mac global context
+ * @session_id:    session id
+ *
+ * Return: status of operation
+ */
+CDF_STATUS
+csr_scan_request_lost_link3(tpAniSirGlobal mac_ctx, uint32_t session_id)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tSmeCmd *cmd;
+
+	sms_log(mac_ctx, LOGW, FL(" called"));
+	do {
+		cmd = csr_get_command_buffer(mac_ctx);
+		if (!cmd) {
+			status = CDF_STATUS_E_RESOURCES;
+			break;
+		}
+		cdf_mem_set(&cmd->u.scanCmd, sizeof(tScanCmd), 0);
+		cmd->command = eSmeCommandScan;
+		cmd->sessionId = (uint8_t) session_id;
+		cmd->u.scanCmd.reason = eCsrScanLostLink3;
+		cmd->u.scanCmd.callback = NULL;
+		cmd->u.scanCmd.pContext = NULL;
+		cmd->u.scanCmd.u.scanRequest.maxChnTime =
+			mac_ctx->roam.configParam.nActiveMaxChnTime;
+		cmd->u.scanCmd.u.scanRequest.minChnTime =
+			mac_ctx->roam.configParam.nActiveMinChnTime;
+		cmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN;
+		wma_get_scan_id(&cmd->u.scanCmd.scanID);
+		status = cdf_mc_timer_init(&cmd->u.scanCmd.csr_scan_timer,
+			CDF_TIMER_TYPE_SW,
+			csr_scan_active_list_timeout_handle, &cmd);
+		cmd->u.scanCmd.u.scanRequest.scan_id =
+			cmd->u.scanCmd.scanID;
+		cdf_set_macaddr_broadcast(&cmd->u.scanCmd.u.scanRequest.bssid);
+		/* Put to the head of pending queue */
+		status = csr_queue_sme_command(mac_ctx, cmd, true);
+		if (!CDF_IS_STATUS_SUCCESS(status)) {
+			sms_log(mac_ctx, LOGE,
+				FL("fail to send message status = %d"), status);
+			break;
+		}
+	} while (0);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGW, FL("failed with status %d"), status);
+		if (cmd)
+			csr_release_command_scan(mac_ctx, cmd);
+	}
+
+	return status;
+}
+
+CDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal pMac,
+					   tSmeCmd *pCommand)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tScanResultHandle hBSSList = CSR_INVALID_SCANRESULT_HANDLE;
+	tCsrScanResultFilter *pScanFilter = NULL;
+	tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
+	uint32_t sessionId = pCommand->sessionId;
+
+	do {
+		/* If this scan is for LFR */
+		if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) {
+			/* notify LFR state m/c */
+			status = csr_neighbor_roam_sssid_scan_done(pMac,
+						sessionId, CDF_STATUS_SUCCESS);
+			if (CDF_STATUS_SUCCESS != status)
+				csr_neighbor_roam_start_lfr_scan(pMac,
+								 sessionId);
+			status = CDF_STATUS_SUCCESS;
+			break;
+		}
+		/*
+		 * If there is roam command waiting, ignore this roam because
+		 * the newer roam command is the one to execute
+		 */
+		if (csr_is_roam_command_waiting_for_session(pMac, sessionId)) {
+			sms_log(pMac, LOGW,
+				FL("aborts because roam command waiting"));
+			break;
+		}
+		if (pProfile == NULL)
+			break;
+		pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
+		if (NULL == pScanFilter) {
+			status = CDF_STATUS_E_NOMEM;
+			break;
+		}
+		cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
+		status = csr_roam_prepare_filter_from_profile(pMac, pProfile,
+							      pScanFilter);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			break;
+		status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			break;
+		status = csr_roam_issue_connect(pMac, sessionId, pProfile,
+						hBSSList, eCsrHddIssued,
+						pCommand->u.scanCmd.roamId,
+						true, true);
+	} while (0);
+
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		if (CSR_INVALID_SCANRESULT_HANDLE != hBSSList) {
+			csr_scan_result_purge(pMac, hBSSList);
+		}
+		/* We haven't done anything to this profile */
+		csr_roam_call_callback(pMac, sessionId, NULL,
+				       pCommand->u.scanCmd.roamId,
+				       eCSR_ROAM_ASSOCIATION_FAILURE,
+				       eCSR_ROAM_RESULT_FAILURE);
+	}
+	if (pScanFilter) {
+		csr_free_scan_filter(pMac, pScanFilter);
+		cdf_mem_free(pScanFilter);
+	}
+	return status;
+}
+
+CDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal pMac,
+						   tSmeCmd *pCommand)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	uint32_t sessionId = pCommand->sessionId;
+	tCsrRoamProfile *pProfile = pCommand->u.scanCmd.pToRoamProfile;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+	eCsrRoamResult roam_result;
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+	/* If this scan is for LFR */
+	if (pMac->roam.neighborRoamInfo[sessionId].uOsRequestedHandoff) {
+		/* notify LFR state m/c */
+		status = csr_neighbor_roam_sssid_scan_done(pMac, sessionId,
+							CDF_STATUS_E_FAILURE);
+		if (CDF_STATUS_SUCCESS != status)
+			csr_neighbor_roam_start_lfr_scan(pMac, sessionId);
+		return CDF_STATUS_SUCCESS;
+	}
+#ifdef WLAN_DEBUG
+	if (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs == 1) {
+		char str[36];
+		tSirMacSSid *ptr_ssid =
+		&pCommand->u.scanCmd.u.scanRequest.SSIDs.SSIDList[0].SSID;
+		cdf_mem_copy(str, ptr_ssid->ssId, ptr_ssid->length);
+		str[ptr_ssid->length] = 0;
+		sms_log(pMac, LOGW, FL("SSID = %s"), str);
+	}
+#endif
+	/*
+	 * Check whether it is for start ibss. No need to do anything if it
+	 * is a JOIN request
+	 */
+	if (pProfile && CSR_IS_START_IBSS(pProfile)) {
+		status = csr_roam_issue_connect(pMac, sessionId, pProfile, NULL,
+				eCsrHddIssued, pCommand->u.scanCmd.roamId,
+				true, true);
+		if (!CDF_IS_STATUS_SUCCESS(status)) {
+			sms_log(pMac, LOGE,
+				FL("failed to issue startIBSS, status: 0x%08X"),
+				status);
+			csr_roam_call_callback(pMac, sessionId, NULL,
+				pCommand->u.scanCmd.roamId, eCSR_ROAM_FAILED,
+				eCSR_ROAM_RESULT_FAILURE);
+		}
+		return status;
+	}
+	roam_result = eCSR_ROAM_RESULT_FAILURE;
+	if (NULL != pProfile && csr_is_bss_type_ibss(pProfile->BSSType)) {
+		roam_result = eCSR_ROAM_RESULT_IBSS_START_FAILED;
+		goto roam_completion;
+	}
+	/* Only indicate assoc_completion if we indicate assoc_start. */
+	if (pSession->bRefAssocStartCnt > 0) {
+		tCsrRoamInfo *pRoamInfo = NULL, roamInfo;
+
+		cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
+		pRoamInfo = &roamInfo;
+		if (pCommand->u.roamCmd.pRoamBssEntry) {
+			tCsrScanResult *pScanResult = GET_BASE_ADDR(
+				pCommand->u.roamCmd.pRoamBssEntry,
+				tCsrScanResult, Link);
+			roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor;
+		}
+		roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
+		roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
+		pSession->bRefAssocStartCnt--;
+		csr_roam_call_callback(pMac, sessionId, pRoamInfo,
+				       pCommand->u.scanCmd.roamId,
+				       eCSR_ROAM_ASSOCIATION_COMPLETION,
+				       eCSR_ROAM_RESULT_FAILURE);
+	} else {
+		csr_roam_call_callback(pMac, sessionId, NULL,
+				       pCommand->u.scanCmd.roamId,
+				       eCSR_ROAM_ASSOCIATION_FAILURE,
+				       eCSR_ROAM_RESULT_FAILURE);
+	}
+roam_completion:
+	csr_roam_completion(pMac, sessionId, NULL, pCommand, roam_result,
+			    false);
+	return status;
+}
+
+CDF_STATUS csr_scan_result_purge(tpAniSirGlobal pMac,
+				 tScanResultHandle hScanList)
+{
+	CDF_STATUS status = CDF_STATUS_E_INVAL;
+	tScanResultList *pScanList = (tScanResultList *) hScanList;
+
+	if (pScanList) {
+		status = csr_ll_scan_purge_result(pMac, &pScanList->List);
+		csr_ll_close(&pScanList->List);
+		cdf_mem_free(pScanList);
+	}
+	return status;
+}
+
+/**
+ * csr_derive_prefer_value_from_rssi() - to derive prefer value
+ * @mac_ctx: Global MAC Context
+ * @rssi: RSSI of the BSS
+ *
+ * This routine will derive preferred value from given rssi
+ *
+ * Return: value between 0 to 14
+ */
+static int csr_derive_prefer_value_from_rssi(tpAniSirGlobal mac_ctx, int rssi)
+{
+	int i = CSR_NUM_RSSI_CAT - 1, pref_val = 0;
+	while (i >= 0) {
+		if (rssi >= mac_ctx->roam.configParam.RSSICat[i]) {
+			pref_val = mac_ctx->roam.configParam.BssPreferValue[i];
+			break;
+		}
+		i--;
+	};
+	return pref_val;
+}
+
+/**
+ * is_channel_found_in_pcl() - to check if channel is present in pcl
+ * @mac_ctx: Global MAC Context
+ * @channel_id: channel of bss
+ * @filter: pointer to filter created through profile
+ *
+ * to check if provided channel is present in pcl
+ *
+ * Return: true or false
+ */
+static bool is_channel_found_in_pcl(tpAniSirGlobal mac_ctx, int channel_id,
+		tCsrScanResultFilter *filter)
+{
+	int i;
+	bool status = false;
+
+	if (NULL == filter)
+		return status;
+
+	for (i = 0; i < filter->pcl_channels.numChannels; i++) {
+		if (filter->pcl_channels.channelList[i] == channel_id) {
+			status = true;
+			break;
+		}
+	}
+	return status;
+}
+/**
+ * csr_get_altered_rssi() - Artificially increase/decrease RSSI
+ * @mac_ctx:         Global MAC Context pointer.
+ * @rssi:            Actual RSSI of the AP.
+ * @channel_id:      Channel on which the AP is parked.
+ * @bssid:           BSSID of the AP to connect to.
+ *
+ * This routine will apply the boost and penalty parameters
+ * if the channel_id is of 5G band and it will also apply
+ * the preferred bssid score if there is a match between
+ * the bssid and the global preferred bssid list.
+ *
+ * Return:          The modified RSSI Value
+ */
+static int csr_get_altered_rssi(tpAniSirGlobal mac_ctx, int rssi,
+		uint8_t channel_id, struct cdf_mac_addr *bssid)
+{
+	int modified_rssi;
+	int boost_factor;
+	int penalty_factor;
+	int i;
+	struct roam_ext_params *roam_params;
+	struct cdf_mac_addr fav_bssid;
+	struct cdf_mac_addr local_bssid;
+
+	modified_rssi = rssi;
+	cdf_mem_zero(&local_bssid.bytes, CDF_MAC_ADDR_SIZE);
+	if (bssid)
+		cdf_mem_copy(local_bssid.bytes, bssid->bytes,
+				CDF_MAC_ADDR_SIZE);
+	roam_params = &mac_ctx->roam.configParam.roam_params;
+	/*
+	 * If the 5G pref feature is enabled, apply the roaming
+	 * parameters to boost or penalize the rssi.
+	 * Boost Factor = boost_factor * (Actual RSSI - boost Threshold)
+	 * Penalty Factor = penalty factor * (penalty threshold - Actual RSSI)
+	 */
+	if (CSR_IS_SELECT_5G_PREFERRED(mac_ctx) &&
+			CDS_IS_CHANNEL_5GHZ(channel_id)) {
+		if (rssi > roam_params->raise_rssi_thresh_5g) {
+			/* Check and boost the threshold*/
+			boost_factor = roam_params->raise_factor_5g *
+				(rssi - roam_params->raise_rssi_thresh_5g);
+			/* Check and penalize the threshold */
+			modified_rssi += CSR_MIN(roam_params->max_raise_rssi_5g,
+						boost_factor);
+		} else if (rssi < roam_params->drop_rssi_thresh_5g) {
+			penalty_factor = roam_params->drop_factor_5g *
+				(roam_params->drop_rssi_thresh_5g - rssi);
+			modified_rssi -= CSR_MAX(roam_params->max_drop_rssi_5g,
+						penalty_factor);
+		}
+		sms_log(mac_ctx, LOG2,
+			FL("5G BSSID"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"),
+			MAC_ADDR_ARRAY(local_bssid.bytes),
+			rssi, modified_rssi, channel_id);
+	}
+	/*
+	 * Check if there are preferred bssid and then apply the
+	 * preferred score
+	 */
+	cdf_mem_zero(&fav_bssid.bytes, CDF_MAC_ADDR_SIZE);
+	if (roam_params->num_bssid_favored) {
+		for (i = 0; i < roam_params->num_bssid_favored; i++) {
+			cdf_mem_copy(fav_bssid.bytes,
+					&roam_params->bssid_favored[i],
+					CDF_MAC_ADDR_SIZE);
+			if (!cdf_is_macaddr_equal(&fav_bssid, bssid))
+				continue;
+			modified_rssi += roam_params->bssid_favored_factor[i];
+			sms_log(mac_ctx, LOG2,
+				FL("Pref"MAC_ADDRESS_STR" AR=%d, MR=%d, ch=%d"),
+				MAC_ADDR_ARRAY(local_bssid.bytes),
+				rssi, modified_rssi, channel_id);
+		}
+	}
+	return modified_rssi;
+}
+
+/**
+ * csr_get_bss_prefer_value() - Get the preference value for BSS
+ * @mac_ctx:               Global MAC Context
+ * @rssi:                  RSSI of the BSS
+ * @bssid:                 BSSID to which the preference value is returned
+ * @channel_id:            Channel on which the AP is parked
+ *
+ * Each BSS descriptor should be assigned a preference value ranging from
+ * 14-0, which will be used as an RSSI bucket score while sorting the
+ * scan results.
+ *
+ * Return: Preference value for the BSSID
+ */
+static uint32_t csr_get_bss_prefer_value(tpAniSirGlobal mac_ctx, int rssi,
+		struct cdf_mac_addr *bssid, int channel_id)
+{
+	uint32_t ret = 0;
+	int modified_rssi;
+
+	/*
+	 * The RSSI does not get modified in case the 5G
+	 * preference or preferred BSSID is not applicable
+	 */
+	modified_rssi = csr_get_altered_rssi(mac_ctx, rssi, channel_id, bssid);
+	ret = csr_derive_prefer_value_from_rssi(mac_ctx, modified_rssi);
+
+	return ret;
+}
+
+/* Return a CapValue base on the capabilities of a BSS */
+static uint32_t csr_get_bss_cap_value(tpAniSirGlobal pMac,
+				      tSirBssDescription *pBssDesc,
+				      tDot11fBeaconIEs *pIes)
+{
+	uint32_t ret = CSR_BSS_CAP_VALUE_NONE;
+#if  defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+	if (CSR_IS_ROAM_PREFER_5GHZ(pMac) || CSR_IS_SELECT_5G_PREFERRED(pMac)) {
+		if ((pBssDesc) && CDS_IS_CHANNEL_5GHZ(pBssDesc->channelId)) {
+			ret += CSR_BSS_CAP_VALUE_5GHZ;
+		}
+	}
+#endif
+	/*
+	 * if strict select 5GHz is non-zero then ignore the capability checking
+	 */
+	if (pIes && !CSR_IS_SELECT_5GHZ_MARGIN(pMac)) {
+		/* We only care about 11N capability */
+		if (pIes->VHTCaps.present)
+			ret += CSR_BSS_CAP_VALUE_VHT;
+		else if (pIes->HTCaps.present)
+			ret += CSR_BSS_CAP_VALUE_HT;
+		if (CSR_IS_QOS_BSS(pIes)) {
+			ret += CSR_BSS_CAP_VALUE_WMM;
+			/* Give advantage to UAPSD */
+			if (CSR_IS_UAPSD_BSS(pIes)) {
+				ret += CSR_BSS_CAP_VALUE_UAPSD;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * csr_is_better_rssi() - Is bss1 better than bss2
+ * @mac_ctx:             Global MAC Context pointer.
+ * @bss1:                Pointer to the first BSS.
+ * @bss2:                Pointer to the second BSS.
+ *
+ * This routine helps in determining the preference value
+ * of a particular BSS in the scan result which is further
+ * used in the sorting logic of the final candidate AP's.
+ *
+ * Return:          true, if bss1 is better than bss2
+ *                  false, if bss2 is better than bss1.
+ */
+static bool csr_is_better_rssi(tpAniSirGlobal mac_ctx,
+		tCsrScanResult *bss1, tCsrScanResult *bss2)
+{
+	bool ret;
+	int rssi1, rssi2;
+	struct cdf_mac_addr local_mac;
+
+	rssi1 = bss1->Result.BssDescriptor.rssi;
+	rssi2 = bss2->Result.BssDescriptor.rssi;
+	/*
+	 * Apply the boost and penlty logic and check
+	 * which is the best RSSI
+	 */
+	cdf_mem_zero(&local_mac.bytes, CDF_MAC_ADDR_SIZE);
+	cdf_mem_copy(&local_mac.bytes,
+			&bss1->Result.BssDescriptor.bssId, CDF_MAC_ADDR_SIZE);
+	rssi1 = csr_get_altered_rssi(mac_ctx, rssi1,
+			bss1->Result.BssDescriptor.channelId,
+			&local_mac);
+	cdf_mem_copy(&local_mac.bytes,
+			&bss2->Result.BssDescriptor.bssId, CDF_MAC_ADDR_SIZE);
+	rssi2 = csr_get_altered_rssi(mac_ctx, rssi2,
+			bss2->Result.BssDescriptor.channelId,
+			&local_mac);
+	if (CSR_IS_BETTER_RSSI(rssi1, rssi2))
+		ret = true;
+	else
+		ret = false;
+	return ret;
+}
+
+/**
+ * csr_is_better_bss() - Is bss1 better than bss2
+ * @mac_ctx:             Global MAC Context pointer.
+ * @bss1:                Pointer to the first BSS.
+ * @bss2:                Pointer to the second BSS.
+ *
+ * This routine helps in determining the preference value
+ * of a particular BSS in the scan result which is further
+ * used in the sorting logic of the final candidate AP's.
+ *
+ * Return:          true, if bss1 is better than bss2
+ *                  false, if bss2 is better than bss1.
+ */
+static bool csr_is_better_bss(tpAniSirGlobal mac_ctx,
+	tCsrScanResult *bss1, tCsrScanResult *bss2)
+{
+	bool ret;
+
+	if (CSR_IS_BETTER_PREFER_VALUE(bss1->preferValue, bss2->preferValue)) {
+		ret = true;
+	} else if (CSR_IS_EQUAL_PREFER_VALUE
+			(bss1->preferValue, bss2->preferValue)) {
+		if (CSR_IS_BETTER_CAP_VALUE(bss1->capValue, bss2->capValue))
+			ret = true;
+		else if (CSR_IS_EQUAL_CAP_VALUE
+				(bss1->capValue, bss2->capValue)) {
+			if (csr_is_better_rssi(mac_ctx, bss1, bss2))
+				ret = true;
+			else
+				ret = false;
+		} else {
+			ret = false;
+		}
+	} else {
+		ret = false;
+	}
+
+	return ret;
+}
+
+#ifdef FEATURE_WLAN_LFR
+/* Add the channel to the occupiedChannels array */
+static void csr_scan_add_to_occupied_channels(tpAniSirGlobal pMac,
+					      tCsrScanResult *pResult,
+					      uint8_t sessionId,
+					      tCsrChannel *occupied_ch,
+					      tDot11fBeaconIEs *pIes)
+{
+	CDF_STATUS status;
+	uint8_t ch;
+	uint8_t num_occupied_ch = occupied_ch->numChannels;
+	uint8_t *occupied_ch_lst = occupied_ch->channelList;
+
+	ch = pResult->Result.BssDescriptor.channelId;
+	if (csr_is_channel_present_in_list(occupied_ch_lst, num_occupied_ch, ch)
+	    || !csr_neighbor_roam_connected_profile_match(pMac, sessionId,
+							  pResult, pIes))
+		return;
+
+	status = csr_add_to_channel_list_front(occupied_ch_lst,
+					       num_occupied_ch, ch);
+	if (CDF_IS_STATUS_SUCCESS(status)) {
+		occupied_ch->numChannels++;
+		sms_log(pMac, LOG2,
+			FL("Added channel %d to the list (count=%d)"),
+			ch, occupied_ch->numChannels);
+		if (occupied_ch->numChannels >
+		    CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN)
+			occupied_ch->numChannels =
+				CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN;
+	}
+}
+#endif
+
+/* Put the BSS into the scan result list */
+/* pIes can not be NULL */
+static void csr_scan_add_result(tpAniSirGlobal pMac, tCsrScanResult *pResult,
+				tDot11fBeaconIEs *pIes, uint32_t sessionId)
+{
+#ifdef FEATURE_WLAN_LFR
+	tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
+		&pMac->roam.neighborRoamInfo[sessionId];
+#endif
+
+	struct cdf_mac_addr bssid;
+	uint8_t channel_id = pResult->Result.BssDescriptor.channelId;
+	cdf_mem_zero(&bssid.bytes, CDF_MAC_ADDR_SIZE);
+	cdf_mem_copy(bssid.bytes, &pResult->Result.BssDescriptor.bssId,
+			CDF_MAC_ADDR_SIZE);
+	pResult->preferValue = csr_get_bss_prefer_value(pMac,
+				(int)pResult->Result.BssDescriptor.rssi,
+				&bssid, channel_id);
+	pResult->capValue = csr_get_bss_cap_value(pMac,
+				&pResult->Result.BssDescriptor, pIes);
+	csr_ll_insert_tail(&pMac->scan.scanResultList, &pResult->Link,
+			   LL_ACCESS_LOCK);
+#ifdef FEATURE_WLAN_LFR
+	if (0 == pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) {
+		/*
+		 * Build the occupied channel list, only if
+		 * "gNeighborScanChannelList" is NOT set in the cfg.ini file
+		 */
+		csr_scan_add_to_occupied_channels(pMac, pResult, sessionId,
+				&pMac->scan.occupiedChannels[sessionId], pIes);
+	}
+#endif
+}
+
+static void
+csr_parser_scan_result_for_5ghz_preference(tpAniSirGlobal pMac,
+					   tCsrScanResultFilter *pFilter)
+{
+	bool fMatch;
+	CDF_STATUS status;
+	tListElem *pEntry;
+	tDot11fBeaconIEs *pIes;
+	tCsrScanResult *pBssDesc;
+	uint8_t i = 0;
+
+	/* Find out the best AP Rssi going thru the scan results */
+	pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
+	while (NULL != pEntry) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		fMatch = false;
+
+		for (i = 0; pFilter && (i < pFilter->SSIDs.numOfSSIDs); i++) {
+			fMatch = csr_is_ssid_match(pMac,
+					pFilter->SSIDs.SSIDList[i].SSID.ssId,
+					pFilter->SSIDs.SSIDList[i].SSID.length,
+					pBssDesc->Result.ssId.ssId,
+					pBssDesc->Result.ssId.length, true);
+			if (!fMatch)
+				continue;
+
+			pIes = (tDot11fBeaconIEs *)(pBssDesc->Result.pvIes);
+			/* At this time, Result.pvIes may be NULL */
+			status = csr_get_parsed_bss_description_ies(pMac,
+					&pBssDesc->Result.BssDescriptor, &pIes);
+			if (!pIes && (!CDF_IS_STATUS_SUCCESS(status)))
+				continue;
+
+			sms_log(pMac, LOG1, FL("SSID Matched"));
+			if (pFilter->bOSENAssociation) {
+				fMatch = true;
+				sms_log(pMac, LOG1, FL("Security Matched"));
+				if ((pBssDesc->Result.pvIes == NULL) && pIes)
+					cdf_mem_free(pIes);
+				continue;
+			}
+#ifdef WLAN_FEATURE_11W
+			fMatch = csr_is_security_match(pMac, &pFilter->authType,
+					&pFilter->EncryptionType,
+					&pFilter->mcEncryptionType,
+					&pFilter->MFPEnabled,
+					&pFilter->MFPRequired,
+					&pFilter->MFPCapable,
+					&pBssDesc->Result.BssDescriptor,
+					pIes, NULL, NULL, NULL);
+#else
+			fMatch = csr_is_security_match(pMac, &pFilter->authType,
+					&pFilter->EncryptionType,
+					&pFilter->mcEncryptionType,
+					NULL, NULL, NULL,
+					&pBssDesc->Result.BssDescriptor,
+					pIes, NULL, NULL, NULL);
+#endif
+			if ((pBssDesc->Result.pvIes == NULL) && pIes)
+				cdf_mem_free(pIes);
+			if (fMatch)
+				sms_log(pMac, LOG1, FL("Security Matched"));
+		} /* for loop ends */
+
+		if (fMatch
+		    && (pBssDesc->Result.BssDescriptor.rssi >
+			pMac->scan.inScanResultBestAPRssi)) {
+			sms_log(pMac, LOG1,
+				FL("Best AP Rssi changed from %d to %d"),
+				pMac->scan.inScanResultBestAPRssi,
+				pBssDesc->Result.BssDescriptor.rssi);
+			pMac->scan.inScanResultBestAPRssi =
+				pBssDesc->Result.BssDescriptor.rssi;
+		}
+		pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
+				     LL_ACCESS_NOLOCK);
+	}
+}
+
+static void
+csr_prefer_5ghz(tpAniSirGlobal pMac, tCsrScanResultFilter *pFilter)
+{
+	tListElem *pEntry;
+	tCsrScanResult *pBssDesc;
+	struct roam_ext_params *roam_params = NULL;
+
+	if (!pMac->roam.configParam.nSelect5GHzMargin &&
+		!CSR_IS_SELECT_5G_PREFERRED(pMac))
+		return;
+
+	pMac->scan.inScanResultBestAPRssi = -128;
+	roam_params = &pMac->roam.configParam.roam_params;
+#ifdef WLAN_DEBUG_ROAM_OFFLOAD
+	CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
+		  FL("nSelect5GHzMargin"));
+#endif
+	csr_ll_lock(&pMac->scan.scanResultList);
+	/*
+	 * For 5G preference feature, there is no
+	 * need to check the filter match and also re-program the
+	 * RSSI bucket categories, since we use the RSSI values
+	 * while setting the preference value for the BSS.
+	 * There is no need to check the match for roaming since
+	 * it is already done.
+	 */
+	if (!CSR_IS_SELECT_5G_PREFERRED(pMac))
+		csr_parser_scan_result_for_5ghz_preference(pMac, pFilter);
+	if (-128 != pMac->scan.inScanResultBestAPRssi ||
+		CSR_IS_SELECT_5G_PREFERRED(pMac)) {
+		sms_log(pMac, LOG1, FL("Best AP Rssi is %d"),
+			pMac->scan.inScanResultBestAPRssi);
+		/* Modify Rssi category based on best AP Rssi */
+		if (-128 != pMac->scan.inScanResultBestAPRssi)
+			csr_assign_rssi_for_category(pMac,
+					pMac->scan.inScanResultBestAPRssi,
+					pMac->roam.configParam.bCatRssiOffset);
+		pEntry = csr_ll_peek_head(&pMac->scan.scanResultList,
+					  LL_ACCESS_NOLOCK);
+		while (NULL != pEntry) {
+			pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+			/*
+			 * re-assign preference value based on modified
+			 * rssi bucket (or) 5G Preference feature.
+			 */
+			pBssDesc->preferValue = csr_get_bss_prefer_value(pMac,
+				(int)pBssDesc->Result.BssDescriptor.rssi,
+				(struct cdf_mac_addr *)
+				&pBssDesc->Result.BssDescriptor.bssId,
+				pBssDesc->Result.BssDescriptor.channelId);
+
+			sms_log(pMac, LOG2, FL("BSSID("MAC_ADDRESS_STR") Rssi(%d) Chnl(%d) PrefVal(%u) SSID=%.*s"),
+				MAC_ADDR_ARRAY(
+					pBssDesc->Result.BssDescriptor.bssId),
+				pBssDesc->Result.BssDescriptor.rssi,
+				pBssDesc->Result.BssDescriptor.channelId,
+				pBssDesc->preferValue,
+				pBssDesc->Result.ssId.length,
+				pBssDesc->Result.ssId.ssId);
+			pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
+					     LL_ACCESS_NOLOCK);
+		}
+	}
+	csr_ll_unlock(&pMac->scan.scanResultList);
+}
+
+static CDF_STATUS
+csr_save_ies(tpAniSirGlobal pMac,
+	     tCsrScanResultFilter *pFilter,
+	     tCsrScanResult *pBssDesc,
+	     tDot11fBeaconIEs **pNewIes,
+	     bool *fMatch,
+	     eCsrEncryptionType *uc,
+	     eCsrEncryptionType *mc,
+	     eCsrAuthType *auth)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tDot11fBeaconIEs *pIes = NULL;
+
+	if (!pFilter)
+		return status;
+	*fMatch = csr_match_bss(pMac, &pBssDesc->Result.BssDescriptor,
+			       pFilter, auth, uc, mc, &pIes);
+#ifdef WLAN_DEBUG_ROAM_OFFLOAD
+	CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_DEBUG,
+		  FL("csr_match_bss fmatch %d"), *fMatch);
+#endif
+	if (NULL == pIes)
+		return status;
+	/* Only save it when matching */
+	if (!(*fMatch) && !pBssDesc->Result.pvIes) {
+		cdf_mem_free(pIes);
+		return status;
+	}
+	if (!pBssDesc->Result.pvIes) {
+		/*
+		 * csr_match_bss allocates the memory. Simply pass it and it
+		 * is freed later
+		 */
+		*pNewIes = pIes;
+		return status;
+	}
+	/*
+	 * The pIes is allocated by someone else. make a copy
+	 * Only to save parsed IEs if caller provides a filter. Most likely the
+	 * caller is using to for association, hence save the parsed IEs
+	 */
+	*pNewIes = cdf_mem_malloc(sizeof(tDot11fBeaconIEs));
+	if (NULL == *pNewIes) {
+		status = CDF_STATUS_E_NOMEM;
+		sms_log(pMac, LOGE, FL("fail to allocate memory for IEs"));
+		/* Need to free memory allocated by csr_match_bss */
+		if (!pBssDesc->Result.pvIes)
+			cdf_mem_free(pIes);
+		return status;
+	}
+	cdf_mem_copy(*pNewIes, pIes, sizeof(tDot11fBeaconIEs));
+	return status;
+}
+
+static CDF_STATUS
+csr_save_scan_entry(tpAniSirGlobal pMac,
+		    tCsrScanResultFilter *pFilter,
+		    bool fMatch,
+		    tCsrScanResult *pBssDesc,
+		    tDot11fBeaconIEs *pNewIes,
+		    tScanResultList *pRetList,
+		    uint32_t *count,
+		    eCsrEncryptionType uc,
+		    eCsrEncryptionType mc,
+		    eCsrAuthType *auth)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tCsrScanResult *pResult;
+	uint32_t bssLen, allocLen;
+	/* To sort the list */
+	tListElem *pTmpEntry;
+	tCsrScanResult *pTmpResult;
+
+	if (!(NULL == pFilter || fMatch))
+		return status;
+
+	bssLen = pBssDesc->Result.BssDescriptor.length +
+		sizeof(pBssDesc->Result.BssDescriptor.length);
+	allocLen = sizeof(tCsrScanResult) + bssLen;
+	pResult = cdf_mem_malloc(allocLen);
+	if (NULL == pResult) {
+		status = CDF_STATUS_E_NOMEM;
+		sms_log(pMac, LOGE,
+			FL("fail to allocate memory for scan result, len=%d"),
+			allocLen);
+		if (pNewIes)
+			cdf_mem_free(pNewIes);
+		return status;
+	}
+	cdf_mem_set(pResult, allocLen, 0);
+	pResult->capValue = pBssDesc->capValue;
+	pResult->preferValue = pBssDesc->preferValue;
+	pResult->ucEncryptionType = uc;
+	pResult->mcEncryptionType = mc;
+	pResult->authType = *auth;
+	pResult->Result.ssId = pBssDesc->Result.ssId;
+	pResult->Result.timer = pBssDesc->Result.timer;
+	/* save the pIes for later use */
+	pResult->Result.pvIes = pNewIes;
+	/* save bss description */
+	cdf_mem_copy(&pResult->Result.BssDescriptor,
+		     &pBssDesc->Result.BssDescriptor,
+		     bssLen);
+	/*
+	 * No need to lock pRetList because it is locally allocated and no
+	 * outside can access it at this time
+	 */
+	if (csr_ll_is_list_empty(&pRetList->List, LL_ACCESS_NOLOCK)) {
+		csr_ll_insert_tail(&pRetList->List, &pResult->Link,
+				   LL_ACCESS_NOLOCK);
+		(*count)++;
+		return status;
+	}
+
+	pTmpEntry = csr_ll_peek_head(&pRetList->List, LL_ACCESS_NOLOCK);
+	while (pTmpEntry) {
+		pTmpResult = GET_BASE_ADDR(pTmpEntry, tCsrScanResult, Link);
+		if (csr_is_better_bss(pMac, pResult, pTmpResult)) {
+			csr_ll_insert_entry(&pRetList->List, pTmpEntry,
+					    &pResult->Link, LL_ACCESS_NOLOCK);
+			/* To indicate we are done */
+			pResult = NULL;
+			break;
+		}
+		pTmpEntry = csr_ll_next(&pRetList->List,
+					pTmpEntry, LL_ACCESS_NOLOCK);
+	}
+	if (pResult != NULL) {
+		/* This one is not better than any one */
+		csr_ll_insert_tail(&pRetList->List, &pResult->Link,
+				   LL_ACCESS_NOLOCK);
+	}
+	(*count)++;
+	return status;
+}
+
+/**
+ * csr_calc_pref_val_by_pcl() - to calculate preferred value
+ * @mac_ctx: mac context
+ * @filter: filter to find match from scan result
+ * @bss_descr: pointer to bss descriptor
+ *
+ * this routine calculates the new preferred value to be given to
+ * provided bss if its channel falls under preferred channel list.
+ * Thump rule is higer the RSSI better the boost.
+ *
+ * Return: success or failure
+ */
+static CDF_STATUS csr_calc_pref_val_by_pcl(tpAniSirGlobal mac_ctx,
+			tCsrScanResultFilter *filter,
+			tCsrScanResult *bss_descr)
+{
+	int temp_rssi = 0, new_pref_val = 0;
+	int orig_pref_val = 0;
+
+	if (NULL == mac_ctx || NULL == bss_descr)
+		return CDF_STATUS_E_FAILURE;
+
+	if (mac_ctx->policy_manager_enabled &&
+		is_channel_found_in_pcl(mac_ctx,
+			bss_descr->Result.BssDescriptor.channelId, filter) &&
+		(bss_descr->Result.BssDescriptor.rssi > PCL_RSSI_THRESHOLD)) {
+		orig_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx,
+					bss_descr->Result.BssDescriptor.rssi);
+		temp_rssi = bss_descr->Result.BssDescriptor.rssi +
+				(PCL_ADVANTAGE/(CSR_NUM_RSSI_CAT -
+							orig_pref_val));
+		if (temp_rssi > 0)
+			temp_rssi = 0;
+		new_pref_val = csr_derive_prefer_value_from_rssi(mac_ctx,
+					temp_rssi);
+
+		sms_log(mac_ctx, LOG1,
+			FL("%pM: rssi:%d org pref=%d temp rssi:%d new pref=%d pref=%d updated pref=%d"),
+			bss_descr->Result.BssDescriptor.bssId,
+			bss_descr->Result.BssDescriptor.rssi,
+			orig_pref_val, temp_rssi, new_pref_val,
+			bss_descr->preferValue,
+			CSR_MAX(new_pref_val, bss_descr->preferValue));
+
+		bss_descr->preferValue =
+			CSR_MAX(new_pref_val, bss_descr->preferValue);
+	}
+	return CDF_STATUS_SUCCESS;
+}
+
+static CDF_STATUS
+csr_parse_scan_results(tpAniSirGlobal pMac,
+		       tCsrScanResultFilter *pFilter,
+		       tScanResultList *pRetList,
+		       uint32_t *count)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tListElem *pEntry;
+	bool fMatch = false;
+	tCsrScanResult *pBssDesc = NULL;
+	tDot11fBeaconIEs *pIes, *pNewIes = NULL;
+	eCsrEncryptionType uc, mc;
+	eCsrAuthType auth = eCSR_AUTH_TYPE_OPEN_SYSTEM;
+	uint32_t len = 0;
+	enum cds_con_mode new_mode;
+
+
+	csr_ll_lock(&pMac->scan.scanResultList);
+
+	if (pFilter) {
+		if (cds_map_concurrency_mode(pMac->hHdd,
+					&pFilter->csrPersona, &new_mode)) {
+			status = cds_get_pcl(pMac->hHdd, new_mode,
+				&pFilter->pcl_channels.channelList[0], &len);
+			pFilter->pcl_channels.numChannels = (uint8_t)len;
+		}
+	}
+
+	if (CDF_STATUS_E_FAILURE == status)
+		sms_log(pMac, CDF_TRACE_LEVEL_ERROR,
+			FL("Retrieving pcl failed from HDD"));
+	pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		pIes = (tDot11fBeaconIEs *) (pBssDesc->Result.pvIes);
+		/*
+		 * if pBssDesc->Result.pvIes is NULL, we need to free any memory
+		 * allocated by csr_match_bss for any error condition,
+		 * otherwiase, it will be freed later
+		 */
+		fMatch = false;
+		pNewIes = NULL;
+		status = csr_save_ies(pMac, pFilter, pBssDesc, &pNewIes,
+				      &fMatch, &uc, &mc, &auth);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			break;
+		/*
+		 * Modify the prefer value to honor PCL list
+		 */
+		if (pFilter && pFilter->pcl_channels.numChannels > 0)
+			csr_calc_pref_val_by_pcl(pMac, pFilter, pBssDesc);
+		status = csr_save_scan_entry(pMac, pFilter, fMatch, pBssDesc,
+					     pNewIes, pRetList, count, uc, mc,
+					     &auth);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			break;
+		pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
+				     LL_ACCESS_NOLOCK);
+	} /* while */
+	csr_ll_unlock(&pMac->scan.scanResultList);
+	return status;
+}
+
+CDF_STATUS csr_scan_get_result(tpAniSirGlobal pMac,
+			       tCsrScanResultFilter *pFilter,
+			       tScanResultHandle *phResult)
+{
+	CDF_STATUS status;
+	tScanResultList *pRetList;
+	uint32_t count = 0;
+
+	if (phResult)
+		*phResult = CSR_INVALID_SCANRESULT_HANDLE;
+
+	csr_prefer_5ghz(pMac, pFilter);
+
+	pRetList = cdf_mem_malloc(sizeof(tScanResultList));
+	if (NULL == pRetList)
+		return CDF_STATUS_E_NOMEM;
+
+	cdf_mem_set(pRetList, sizeof(tScanResultList), 0);
+	csr_ll_open(pMac->hHdd, &pRetList->List);
+	pRetList->pCurEntry = NULL;
+	status = csr_parse_scan_results(pMac, pFilter, pRetList, &count);
+	sms_log(pMac, LOG2, FL("return %d BSS"), csr_ll_count(&pRetList->List));
+	if (!CDF_IS_STATUS_SUCCESS(status) || (phResult == NULL)) {
+		/* Fail or No one wants the result. */
+		csr_scan_result_purge(pMac, (tScanResultHandle) pRetList);
+	} else {
+		if (0 == count) {
+			/* We are here meaning the there is no match */
+			csr_ll_close(&pRetList->List);
+			cdf_mem_free(pRetList);
+			status = CDF_STATUS_E_NULL_VALUE;
+		} else if (phResult) {
+			*phResult = pRetList;
+		}
+	}
+	return status;
+}
+
+/*
+ * NOTE: This routine is being added to make
+ * sure that scan results are not being flushed
+ * while roaming. If the scan results are flushed,
+ * we are unable to recover from
+ * csr_roam_roaming_state_disassoc_rsp_processor.
+ * If it is needed to remove this routine,
+ * first ensure that we recover gracefully from
+ * csr_roam_roaming_state_disassoc_rsp_processor if
+ * csr_scan_get_result returns with a failure because
+ * of not being able to find the roaming BSS.
+ */
+bool csr_scan_flush_denied(tpAniSirGlobal pMac)
+{
+	uint8_t sessionId;
+
+	for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
+		if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
+			if (csr_neighbor_middle_of_roaming(pMac, sessionId))
+				return 1;
+		}
+	}
+	return 0;
+}
+
+CDF_STATUS csr_scan_flush_result(tpAniSirGlobal pMac)
+{
+	bool isFlushDenied = csr_scan_flush_denied(pMac);
+
+	if (isFlushDenied) {
+		sms_log(pMac, LOGW, "%s: scan flush denied in roam state %d",
+			__func__, isFlushDenied);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOG4, "%s: Flushing all scan results", __func__);
+	csr_ll_scan_purge_result(pMac, &pMac->scan.tempScanResults);
+	csr_ll_scan_purge_result(pMac, &pMac->scan.scanResultList);
+	return CDF_STATUS_SUCCESS;
+}
+
+CDF_STATUS csr_scan_flush_selective_result(tpAniSirGlobal pMac, bool flushP2P)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tListElem *pEntry, *pFreeElem;
+	tCsrScanResult *pBssDesc;
+	tDblLinkList *pList = &pMac->scan.scanResultList;
+
+	csr_ll_lock(pList);
+
+	pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
+	while (pEntry != NULL) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		if (flushP2P == cdf_mem_compare(pBssDesc->Result.ssId.ssId,
+						"DIRECT-", 7)) {
+			pFreeElem = pEntry;
+			pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+			csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK);
+			csr_free_scan_result_entry(pMac, pBssDesc);
+			continue;
+		}
+		pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+	}
+
+	csr_ll_unlock(pList);
+
+	return status;
+}
+
+void csr_scan_flush_bss_entry(tpAniSirGlobal pMac,
+			      tpSmeCsaOffloadInd pCsaOffloadInd)
+{
+	tListElem *pEntry, *pFreeElem;
+	tCsrScanResult *pBssDesc;
+	tDblLinkList *pList = &pMac->scan.scanResultList;
+
+	csr_ll_lock(pList);
+
+	pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
+	while (pEntry != NULL) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		if (cdf_mem_compare(pBssDesc->Result.BssDescriptor.bssId,
+			pCsaOffloadInd->bssId, sizeof(tSirMacAddr))) {
+			pFreeElem = pEntry;
+			pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+			csr_ll_remove_entry(pList, pFreeElem, LL_ACCESS_NOLOCK);
+			csr_free_scan_result_entry(pMac, pBssDesc);
+			sms_log(pMac, LOG1, FL("Removed BSS entry:%pM"),
+				pCsaOffloadInd->bssId);
+			continue;
+		}
+
+		pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+	}
+
+	csr_ll_unlock(pList);
+}
+
+/**
+ * csr_check11d_channel
+ *
+ ***FUNCTION:
+ * This function is called from csr_scan_filter_results function and
+ * compare channel number with given channel list.
+ *
+ ***LOGIC:
+ * Check Scan result channel number with CFG channel list
+ *
+ ***ASSUMPTIONS:
+ *
+ *
+ ***NOTE:
+ *
+ * @param  channelId      channel number
+ * @param  pChannelList   Pointer to channel list
+ * @param  numChannels    Number of channel in channel list
+ *
+ * @return Status
+ */
+
+CDF_STATUS csr_check11d_channel(uint8_t channelId, uint8_t *pChannelList,
+				uint32_t numChannels)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	uint8_t i = 0;
+
+	for (i = 0; i < numChannels; i++) {
+		if (pChannelList[i] == channelId) {
+			status = CDF_STATUS_SUCCESS;
+			break;
+		}
+	}
+	return status;
+}
+
+/**
+ * csr_scan_filter_results
+ *
+ ***FUNCTION:
+ * This function is called from csr_apply_country_information function and
+ * filter scan result based on valid channel list number.
+ *
+ ***LOGIC:
+ * Get scan result from scan list and Check Scan result channel number
+ * with 11d channel list if channel number is found in 11d channel list
+ * then do not remove scan result entry from scan list
+ *
+ ***ASSUMPTIONS:
+ *
+ *
+ ***NOTE:
+ *
+ * @param  pMac        Pointer to Global MAC structure
+ *
+ * @return Status
+ */
+
+CDF_STATUS csr_scan_filter_results(tpAniSirGlobal pMac)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tListElem *pEntry, *pTempEntry;
+	tCsrScanResult *pBssDesc;
+	uint32_t len = sizeof(pMac->roam.validChannelList);
+
+	/* Get valid channels list from CFG */
+	if (!CDF_IS_STATUS_SUCCESS(csr_get_cfg_valid_channels(pMac,
+							      pMac->roam.
+							      validChannelList,
+							      &len))) {
+		sms_log(pMac, LOGE, "Failed to get Channel list from CFG");
+	}
+
+	csr_ll_lock(&pMac->scan.scanResultList);
+	pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		pTempEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
+					 LL_ACCESS_NOLOCK);
+		if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId,
+					 pMac->roam.validChannelList, len)) {
+			/* Remove Scan result which does not have 11d channel */
+			if (csr_ll_remove_entry(&pMac->scan.scanResultList,
+				 pEntry, LL_ACCESS_NOLOCK)) {
+				csr_free_scan_result_entry(pMac, pBssDesc);
+			}
+		} else {
+			sms_log(pMac, LOG1, FL("%d is a Valid channel"),
+				pBssDesc->Result.BssDescriptor.channelId);
+		}
+		pEntry = pTempEntry;
+	}
+
+	csr_ll_unlock(&pMac->scan.scanResultList);
+	csr_ll_lock(&pMac->scan.tempScanResults);
+
+	pEntry = csr_ll_peek_head(&pMac->scan.tempScanResults,
+					 LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		pTempEntry = csr_ll_next(&pMac->scan.tempScanResults, pEntry,
+					 LL_ACCESS_NOLOCK);
+		if (csr_check11d_channel(pBssDesc->Result.BssDescriptor.channelId,
+					 pMac->roam.validChannelList, len)) {
+			/* Remove Scan result which does not have 11d channel */
+			if (csr_ll_remove_entry
+				    (&pMac->scan.tempScanResults, pEntry,
+				    LL_ACCESS_NOLOCK)) {
+				csr_free_scan_result_entry(pMac, pBssDesc);
+			}
+		} else {
+			sms_log(pMac, LOG1, FL("%d is a Valid channel"),
+				pBssDesc->Result.BssDescriptor.channelId);
+		}
+		pEntry = pTempEntry;
+	}
+
+	csr_ll_unlock(&pMac->scan.tempScanResults);
+	return status;
+}
+
+CDF_STATUS csr_scan_copy_result_list(tpAniSirGlobal pMac, tScanResultHandle hIn,
+				     tScanResultHandle *phResult)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tScanResultList *pRetList, *pInList = (tScanResultList *) hIn;
+	tCsrScanResult *pResult, *pScanResult;
+	uint32_t count = 0;
+	tListElem *pEntry;
+	uint32_t bssLen, allocLen;
+
+	if (phResult) {
+		*phResult = CSR_INVALID_SCANRESULT_HANDLE;
+	}
+	pRetList = cdf_mem_malloc(sizeof(tScanResultList));
+	if (NULL == pRetList)
+		status = CDF_STATUS_E_NOMEM;
+	else {
+		cdf_mem_set(pRetList, sizeof(tScanResultList), 0);
+		csr_ll_open(pMac->hHdd, &pRetList->List);
+		pRetList->pCurEntry = NULL;
+		csr_ll_lock(&pMac->scan.scanResultList);
+		csr_ll_lock(&pInList->List);
+
+		pEntry = csr_ll_peek_head(&pInList->List, LL_ACCESS_NOLOCK);
+		while (pEntry) {
+			pScanResult =
+				GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+			bssLen =
+				pScanResult->Result.BssDescriptor.length +
+				sizeof(pScanResult->Result.BssDescriptor.length);
+			allocLen = sizeof(tCsrScanResult) + bssLen;
+			pResult = cdf_mem_malloc(allocLen);
+			if (NULL == pResult)
+				status = CDF_STATUS_E_NOMEM;
+			else
+				status = CDF_STATUS_SUCCESS;
+			if (!CDF_IS_STATUS_SUCCESS(status)) {
+				csr_scan_result_purge(pMac,
+						      (tScanResultHandle *)
+						      pRetList);
+				count = 0;
+				break;
+			}
+			cdf_mem_set(pResult, allocLen, 0);
+			cdf_mem_copy(&pResult->Result.BssDescriptor,
+				     &pScanResult->Result.BssDescriptor,
+				     bssLen);
+			if (pScanResult->Result.pvIes) {
+				pResult->Result.pvIes =
+					cdf_mem_malloc(sizeof(tDot11fBeaconIEs));
+				if (NULL == pResult->Result.pvIes)
+					status = CDF_STATUS_E_NOMEM;
+				else
+					status = CDF_STATUS_SUCCESS;
+				if (!CDF_IS_STATUS_SUCCESS(status)) {
+					/* Free the memory we allocate above first */
+					cdf_mem_free(pResult);
+					csr_scan_result_purge(pMac,
+							      (tScanResultHandle *)
+							      pRetList);
+					count = 0;
+					break;
+				}
+				cdf_mem_copy(pResult->Result.pvIes,
+					     pScanResult->Result.pvIes,
+					     sizeof(tDot11fBeaconIEs));
+			}
+			csr_ll_insert_tail(&pRetList->List, &pResult->Link,
+					   LL_ACCESS_LOCK);
+			count++;
+			pEntry =
+				csr_ll_next(&pInList->List, pEntry, LL_ACCESS_NOLOCK);
+		} /* while */
+		csr_ll_unlock(&pInList->List);
+		csr_ll_unlock(&pMac->scan.scanResultList);
+
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			if (0 == count) {
+				csr_ll_close(&pRetList->List);
+				cdf_mem_free(pRetList);
+				status = CDF_STATUS_E_NULL_VALUE;
+			} else if (phResult) {
+				*phResult = pRetList;
+			}
+		}
+	} /* Allocated pRetList */
+
+	return status;
+}
+
+CDF_STATUS csr_scanning_state_msg_processor(tpAniSirGlobal pMac,
+	void *pMsgBuf)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tSirMbMsg *pMsg = (tSirMbMsg *) pMsgBuf;
+	tCsrRoamSession *pSession;
+	tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
+	tCsrRoamInfo roamInfo;
+	tCsrRoamInfo *pRoamInfo = NULL;
+	uint32_t sessionId;
+
+	if (eWNI_SME_SCAN_RSP == pMsg->type)
+		return csr_scan_sme_scan_response(pMac, pMsgBuf);
+
+	if (pMsg->type != eWNI_SME_UPPER_LAYER_ASSOC_CNF) {
+		if (csr_is_any_session_in_connect_state(pMac)) {
+			/*
+			 * In case of we are connected, we need to check whether
+			 * connect status changes because scan may also run
+			 * while connected.
+			 */
+			csr_roam_check_for_link_status_change(pMac,
+						(tSirSmeRsp *) pMsgBuf);
+		} else {
+			sms_log(pMac, LOGW,
+				FL("Message [0x%04x] received in wrong state"),
+				pMsg->type);
+		}
+		return status;
+	}
+
+	sms_log(pMac, LOG1,
+		FL("Scanning: ASSOC cnf can be given to upper layer"));
+	cdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
+	pRoamInfo = &roamInfo;
+	pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *) pMsgBuf;
+	status = csr_roam_get_session_id_from_bssid(pMac,
+			(struct cdf_mac_addr *)pUpperLayerAssocCnf->bssId, &sessionId);
+	pSession = CSR_GET_SESSION(pMac, sessionId);
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("session %d not found"), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	/* send the status code as Success */
+	pRoamInfo->statusCode = eSIR_SME_SUCCESS;
+	pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
+	pRoamInfo->staId = (uint8_t) pUpperLayerAssocCnf->aid;
+	pRoamInfo->rsnIELen = (uint8_t) pUpperLayerAssocCnf->rsnIE.length;
+	pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata;
+	pRoamInfo->addIELen = (uint8_t) pUpperLayerAssocCnf->addIE.length;
+	pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata;
+	cdf_mem_copy(pRoamInfo->peerMac.bytes,
+			pUpperLayerAssocCnf->peerMacAddr,
+			CDF_MAC_ADDR_SIZE);
+	cdf_mem_copy(&pRoamInfo->bssid.bytes, pUpperLayerAssocCnf->bssId,
+		     CDF_MAC_ADDR_SIZE);
+	pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta;
+	if (CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile)) {
+		pMac->roam.roamSession[sessionId].connectState =
+			eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED;
+		pRoamInfo->fReassocReq = pUpperLayerAssocCnf->reassocReq;
+		status = csr_roam_call_callback(pMac, sessionId,
+					pRoamInfo, 0,
+					eCSR_ROAM_INFRA_IND,
+					eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
+	}
+	if (CSR_IS_WDS_AP(pRoamInfo->u.pConnectedProfile)) {
+		cdf_sleep(100);
+		pMac->roam.roamSession[sessionId].connectState =
+			eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED;
+		status = csr_roam_call_callback(pMac, sessionId, pRoamInfo, 0,
+				eCSR_ROAM_WDS_IND,
+				eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);
+	}
+	return status;
+}
+
+void csr_check_n_save_wsc_ie(tpAniSirGlobal pMac, tSirBssDescription *pNewBssDescr,
+			     tSirBssDescription *pOldBssDescr)
+{
+	int idx, len;
+	uint8_t *pbIe;
+
+	/* If failed to remove, assuming someone else got it. */
+	if ((pNewBssDescr->fProbeRsp != pOldBssDescr->fProbeRsp) &&
+	    (0 == pNewBssDescr->WscIeLen)) {
+		idx = 0;
+		len = pOldBssDescr->length - sizeof(tSirBssDescription) +
+		      sizeof(uint16_t) + sizeof(uint32_t) -
+		      DOT11F_IE_WSCPROBERES_MIN_LEN - 2;
+		pbIe = (uint8_t *) pOldBssDescr->ieFields;
+		/* Save WPS IE if it exists */
+		pNewBssDescr->WscIeLen = 0;
+		while (idx < len) {
+			if ((DOT11F_EID_WSCPROBERES == pbIe[0]) &&
+			    (0x00 == pbIe[2]) && (0x50 == pbIe[3])
+			    && (0xf2 == pbIe[4]) && (0x04 == pbIe[5])) {
+				/* Founrd it */
+				if ((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >=
+				    pbIe[1]) {
+					cdf_mem_copy(pNewBssDescr->
+						     WscIeProbeRsp, pbIe,
+						     pbIe[1] + 2);
+					pNewBssDescr->WscIeLen = pbIe[1] + 2;
+				}
+				break;
+			}
+			idx += pbIe[1] + 2;
+			pbIe += pbIe[1] + 2;
+		}
+	}
+}
+
+/* pIes may be NULL */
+bool csr_remove_dup_bss_description(tpAniSirGlobal pMac,
+				    tSirBssDescription *bss_dscp,
+				    tDot11fBeaconIEs *pIes, tAniSSID *pSsid,
+				    v_TIME_t *timer, bool fForced)
+{
+	tListElem *pEntry;
+	tCsrScanResult *scan_entry;
+	bool fRC = false;
+	int8_t scan_entry_rssi = 0;
+
+	/*
+	 * Walk through all the chained BssDescriptions. If we find a chained
+	 * BssDescription that matches the BssID of the BssDescription passed
+	 * in, then these must be duplicate scan results for this Bss. In that
+	 * case, remove the 'old' Bss description from the linked list.
+	 */
+	csr_ll_lock(&pMac->scan.scanResultList);
+	pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
+
+	while (pEntry) {
+		scan_entry = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		/*
+		 * we have a duplicate scan results only when BSSID, SSID,
+		 * Channel and NetworkType matches
+		 */
+		if (csr_is_duplicate_bss_description(pMac,
+			&scan_entry->Result.BssDescriptor,
+			bss_dscp, pIes, fForced)) {
+			/*
+			 * Following is mathematically a = (aX + b(100-X))/100
+			 * where:
+			 * a = bss_dscp->rssi, b = scan_entry_rssi
+			 * and X = CSR_SCAN_RESULT_RSSI_WEIGHT
+			 */
+			scan_entry_rssi = scan_entry->Result.BssDescriptor.rssi;
+			bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi *
+						CSR_SCAN_RESULT_RSSI_WEIGHT) +
+				((int32_t) scan_entry_rssi *
+				 (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100);
+			/* Remove the old entry from the list */
+			if (csr_ll_remove_entry
+				    (&pMac->scan.scanResultList, pEntry,
+				    LL_ACCESS_NOLOCK)) {
+				/*
+				 * we need to free the memory associated with
+				 * this node. If failed to remove, assuming
+				 * someone else got it.
+				 */
+				*pSsid = scan_entry->Result.ssId;
+				*timer = scan_entry->Result.timer;
+				csr_check_n_save_wsc_ie(pMac, bss_dscp,
+							&scan_entry->Result.
+							BssDescriptor);
+				csr_free_scan_result_entry(pMac, scan_entry);
+			} else {
+				sms_log(pMac, LOGW, FL("fail to remove entry"));
+			}
+			fRC = true;
+			/*
+			 * If we found a match, we can stop looking through
+			 * the list.
+			 */
+			break;
+		}
+		pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
+				     LL_ACCESS_NOLOCK);
+	}
+
+	csr_ll_unlock(&pMac->scan.scanResultList);
+	return fRC;
+}
+
+CDF_STATUS csr_add_pmkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId,
+					tSirBssDescription *pBssDesc,
+					tDot11fBeaconIEs *pIes)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+	tPmkidCandidateInfo *pmkid_info = NULL;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+	WLAN_HOST_DIAG_EVENT_DEF(secEvent,
+				 host_event_wlan_security_payload_type);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("  session %d not found "), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOGW, FL("NumPmkidCandidate = %d"),
+		pSession->NumPmkidCandidate);
+	if (!pIes)
+		return status;
+		/* check if this is a RSN BSS */
+	if (!pIes->RSN.present)
+		return status;
+
+	if (pSession->NumPmkidCandidate >= CSR_MAX_PMKID_ALLOWED)
+		return CDF_STATUS_E_FAILURE;
+
+	/* BSS is capable of doing pre-authentication */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+	cdf_mem_set(&secEvent, sizeof(host_event_wlan_security_payload_type),
+		    0);
+	secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_CANDIDATE_FOUND;
+	secEvent.encryptionModeMulticast = (uint8_t)diag_enc_type_from_csr_type(
+				pSession->connectedProfile.mcEncryptionType);
+	secEvent.encryptionModeUnicast = (uint8_t)diag_enc_type_from_csr_type(
+				pSession->connectedProfile.EncryptionType);
+	cdf_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid.bytes,
+			CDF_MAC_ADDR_SIZE);
+	secEvent.authMode = (uint8_t)diag_auth_type_from_csr_type(
+				pSession->connectedProfile.AuthType);
+	WLAN_HOST_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
+#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
+
+	pmkid_info = &pSession->PmkidCandidateInfo[pSession->NumPmkidCandidate];
+	/* if yes, then add to PMKIDCandidateList */
+	cdf_mem_copy(pmkid_info->BSSID.bytes, pBssDesc->bssId,
+			CDF_MAC_ADDR_SIZE);
+	/* Bit 0 offirst byte - PreAuthentication Capability */
+	if ((pIes->RSN.RSN_Cap[0] >> 0) & 0x1)
+		pmkid_info->preAuthSupported = true;
+	else
+		pmkid_info->preAuthSupported = false;
+	pSession->NumPmkidCandidate++;
+	return status;
+}
+
+/*
+ * This function checks whether new AP is found for the current connected
+ * profile. If it is found, it return the sessionId, else it return invalid
+ * sessionID
+ */
+CDF_STATUS csr_process_bss_desc_for_pmkid_list(tpAniSirGlobal pMac,
+					       tSirBssDescription *pBssDesc,
+					       tDot11fBeaconIEs *pIes,
+					       uint8_t sessionId)
+{
+	tCsrRoamSession *pSession;
+	tDot11fBeaconIEs *pIesLocal = pIes;
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+
+	if (!(pIesLocal ||
+	    CDF_IS_STATUS_SUCCESS(
+		csr_get_parsed_bss_description_ies(pMac, pBssDesc,
+						   &pIesLocal))))
+		return status;
+
+	if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
+		if (!pIes)
+			cdf_mem_free(pIesLocal);
+		return status;
+	}
+
+	pSession = CSR_GET_SESSION(pMac, sessionId);
+	if (csr_is_conn_state_connected_infra(pMac, sessionId)
+	    && (eCSR_AUTH_TYPE_RSN == pSession->connectedProfile.AuthType)
+	    && csr_match_bss_to_connect_profile(pMac,
+				&pSession->connectedProfile,
+				pBssDesc, pIesLocal)) {
+		/* This new BSS fits the current profile connected */
+		status = csr_add_pmkid_candidate_list(pMac, sessionId,
+						      pBssDesc, pIesLocal);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			sms_log(pMac, LOGE,
+				FL("csr_add_pmkid_candidate_list failed"));
+		else
+			status = CDF_STATUS_SUCCESS;
+	}
+
+	if (!pIes)
+		cdf_mem_free(pIesLocal);
+
+	return status;
+}
+
+#ifdef FEATURE_WLAN_WAPI
+CDF_STATUS csr_add_bkid_candidate_list(tpAniSirGlobal pMac, uint32_t sessionId,
+				       tSirBssDescription *pBssDesc,
+				       tDot11fBeaconIEs *pIes)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("  session %d not found "), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOGW,
+		"csr_add_bkid_candidate_list called pMac->scan.NumBkidCandidate = %d",
+		pSession->NumBkidCandidate);
+	if (pIes) {
+		/* check if this is a WAPI BSS */
+		if (pIes->WAPI.present) {
+			/* Check if the BSS is capable of doing pre-authentication */
+			if (pSession->NumBkidCandidate < CSR_MAX_BKID_ALLOWED) {
+
+				/* if yes, then add to BKIDCandidateList */
+				cdf_mem_copy(pSession->
+					     BkidCandidateInfo[pSession->
+							       NumBkidCandidate].
+					     BSSID.bytes, pBssDesc->bssId,
+					     CDF_MAC_ADDR_SIZE);
+				if (pIes->WAPI.preauth) {
+					pSession->BkidCandidateInfo[pSession->
+								    NumBkidCandidate].
+					preAuthSupported = true;
+				} else {
+					pSession->BkidCandidateInfo[pSession->
+								    NumBkidCandidate].
+					preAuthSupported = false;
+				}
+				pSession->NumBkidCandidate++;
+			} else {
+				status = CDF_STATUS_E_FAILURE;
+			}
+		}
+	}
+
+	return status;
+}
+
+/*
+ * This function checks whether new AP is found for the current connected
+ * profile, if so add to BKIDCandidateList
+ */
+bool csr_process_bss_desc_for_bkid_list(tpAniSirGlobal pMac,
+					tSirBssDescription *pBssDesc,
+					tDot11fBeaconIEs *pIes)
+{
+	bool fRC = false;
+	tDot11fBeaconIEs *pIesLocal = pIes;
+	uint32_t sessionId;
+	tCsrRoamSession *pSession;
+	CDF_STATUS status;
+
+	if (!(pIesLocal ||
+	    CDF_IS_STATUS_SUCCESS(
+		csr_get_parsed_bss_description_ies(pMac, pBssDesc,
+						   &pIesLocal))))
+		return fRC;
+
+	for (sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++) {
+		if (!CSR_IS_SESSION_VALID(pMac, sessionId))
+			continue;
+		pSession = CSR_GET_SESSION(pMac, sessionId);
+		if (csr_is_conn_state_connected_infra(pMac, sessionId)
+		    && (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE ==
+			pSession->connectedProfile.AuthType)
+		    && csr_match_bss_to_connect_profile(pMac,
+				&pSession->connectedProfile,
+				pBssDesc, pIesLocal)) {
+			/* this new BSS fits the current profile connected */
+			status = csr_add_bkid_candidate_list(pMac, sessionId,
+							pBssDesc, pIesLocal);
+			if (CDF_IS_STATUS_SUCCESS(status))
+				fRC = true;
+		}
+	}
+	if (!pIes)
+		cdf_mem_free(pIesLocal);
+	return fRC;
+}
+
+#endif
+
+static void
+csr_remove_from_tmp_list(tpAniSirGlobal mac_ctx,
+			 uint8_t reason,
+			 uint8_t session_id)
+{
+	CDF_STATUS status;
+	tListElem *entry;
+	tCsrScanResult *bss_dscp;
+	tDot11fBeaconIEs *local_ie = NULL;
+	bool dup_bss;
+	tAniSSID tmpSsid;
+	v_TIME_t timer = 0;
+
+	tmpSsid.length = 0;
+	while ((entry = csr_ll_remove_tail(&mac_ctx->scan.tempScanResults,
+					   LL_ACCESS_LOCK)) != NULL) {
+		bss_dscp = GET_BASE_ADDR(entry, tCsrScanResult, Link);
+		sms_log(mac_ctx, LOG2,
+			FL("...Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = -%d"),
+			MAC_ADDR_ARRAY(bss_dscp->Result.BssDescriptor.
+				       bssId),
+			bss_dscp->Result.BssDescriptor.channelId,
+			bss_dscp->Result.BssDescriptor.rssi * (-1));
+
+		/* At this time, bss_dscp->Result.pvIes may be NULL */
+		local_ie = (tDot11fBeaconIEs *)(bss_dscp->Result.pvIes);
+		status = csr_get_parsed_bss_description_ies(mac_ctx,
+				&bss_dscp->Result.BssDescriptor, &local_ie);
+		if (!(local_ie || CDF_IS_STATUS_SUCCESS(status))) {
+			sms_log(mac_ctx, LOGE, FL("Cannot pared IEs"));
+			csr_free_scan_result_entry(mac_ctx, bss_dscp);
+			continue;
+		}
+		dup_bss = csr_remove_dup_bss_description(mac_ctx,
+				&bss_dscp->Result.BssDescriptor,
+				local_ie, &tmpSsid, &timer, false);
+		/*
+		 * Check whether we have reach out limit, but don't lose the
+		 * LFR candidates came from FW
+		 */
+		if (CSR_SCAN_IS_OVER_BSS_LIMIT(mac_ctx)) {
+			sms_log(mac_ctx, LOGW, FL("BSS limit reached"));
+			if ((bss_dscp->Result.pvIes == NULL) && local_ie)
+				cdf_mem_free(local_ie);
+			csr_free_scan_result_entry(mac_ctx, bss_dscp);
+			/* Continue because there may be duplicated BSS */
+			continue;
+		}
+		/* check for duplicate scan results */
+		if (!dup_bss) {
+			status = csr_process_bss_desc_for_pmkid_list(mac_ctx,
+					&bss_dscp->Result.BssDescriptor,
+					local_ie, session_id);
+			if (CDF_IS_STATUS_SUCCESS(status)) {
+				/* Found a new BSS */
+				csr_roam_call_callback(mac_ctx, session_id,
+					NULL, 0, eCSR_ROAM_SCAN_FOUND_NEW_BSS,
+					eCSR_ROAM_RESULT_NONE);
+			}
+		} else {
+			/*
+			 * Check if the new one has SSID it it, if not, use
+			 * the older SSID if it exists.
+			 *
+			 * New BSS has a hidden SSID and old one has the SSID.
+			 * Keep the SSID only if diff of saved SSID time and
+			 * current time is less than 1 min to avoid side effect
+			 * of saving SSID with old one is that if AP changes
+			 * its SSID while remain hidden, we may never see it
+			 * and also to address the requirement of When we remove
+			 * hidden ssid from the profile i.e., forget the SSID
+			 * via GUI that SSID shouldn't see in the profile
+			 */
+			v_TIME_t time_gap = cdf_mc_timer_get_system_time() -
+									timer;
+			if ((0 == bss_dscp->Result.ssId.length)
+			    && (time_gap <= HIDDEN_TIMER)
+			    && tmpSsid.length) {
+				bss_dscp->Result.timer = timer;
+				bss_dscp->Result.ssId = tmpSsid;
+			}
+		}
+
+		if (csr_is11d_supported(mac_ctx)
+		    && local_ie->Country.present) {
+			csr_add_vote_for_country_info(mac_ctx,
+						local_ie->Country.country);
+			sms_log(mac_ctx, LOGW,
+				FL("11d AP Bssid "MAC_ADDRESS_STR
+				   " chan= %d, rssi = -%d, countryCode %c%c"),
+				MAC_ADDR_ARRAY(
+					bss_dscp->Result.BssDescriptor.bssId),
+				bss_dscp->Result.BssDescriptor.channelId,
+				bss_dscp->Result.BssDescriptor.rssi * (-1),
+				local_ie->Country.country[0],
+				local_ie->Country.country[1]);
+		}
+		/* append to main list */
+		csr_scan_add_result(mac_ctx, bss_dscp, local_ie, session_id);
+		if ((bss_dscp->Result.pvIes == NULL) && local_ie)
+			cdf_mem_free(local_ie);
+	} /* end of loop */
+}
+
+static void csr_move_temp_scan_results_to_main_list(tpAniSirGlobal pMac,
+						    uint8_t reason,
+						    uint8_t sessionId)
+{
+	tCsrRoamSession *pSession;
+	uint32_t i;
+
+	/* remove the BSS descriptions from temporary list */
+	csr_remove_from_tmp_list(pMac, reason, sessionId);
+	/*
+	 * We don't need to update CC while connected to an AP which is
+	 * advertising CC already
+	 */
+	if (!csr_is11d_supported(pMac))
+		return;
+
+	for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
+		if (!CSR_IS_SESSION_VALID(pMac, i))
+			continue;
+		pSession = CSR_GET_SESSION(pMac, i);
+		if (csr_is_conn_state_connected(pMac, i)) {
+			sms_log(pMac, LOGW,
+				FL("No need to update CC in connected state"));
+			return;
+		}
+	}
+	csr_elected_country_info(pMac);
+	csr_learn_11dcountry_information(pMac, NULL, NULL, true);
+}
+
+static tCsrScanResult *csr_scan_save_bss_description(tpAniSirGlobal pMac,
+						     tSirBssDescription *
+						     pBSSDescription,
+						     tDot11fBeaconIEs *pIes,
+						     uint8_t sessionId)
+{
+	tCsrScanResult *pCsrBssDescription = NULL;
+	uint32_t cbBSSDesc;
+	uint32_t cbAllocated;
+
+	/* figure out how big the BSS description is (the BSSDesc->length does NOT */
+	/* include the size of the length field itself). */
+	cbBSSDesc = pBSSDescription->length + sizeof(pBSSDescription->length);
+
+	cbAllocated = sizeof(tCsrScanResult) + cbBSSDesc;
+
+	pCsrBssDescription = cdf_mem_malloc(cbAllocated);
+	if (NULL != pCsrBssDescription) {
+		cdf_mem_set(pCsrBssDescription, cbAllocated, 0);
+		pCsrBssDescription->AgingCount =
+			(int32_t) pMac->roam.configParam.agingCount;
+		sms_log(pMac, LOGW,
+			FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "),
+			pCsrBssDescription->AgingCount,
+			MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.
+				       bssId));
+		cdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor,
+			     pBSSDescription, cbBSSDesc);
+#if defined(CDF_ENSBALED)
+		if (NULL != pCsrBssDescription->Result.pvIes) {
+			CDF_ASSERT(pCsrBssDescription->Result.pvIes == NULL);
+			return NULL;
+		}
+#endif
+		csr_scan_add_result(pMac, pCsrBssDescription, pIes, sessionId);
+	}
+
+	return pCsrBssDescription;
+}
+
+/* Append a Bss Description... */
+tCsrScanResult *csr_scan_append_bss_description(tpAniSirGlobal pMac,
+						tSirBssDescription *
+						pSirBssDescription,
+						tDot11fBeaconIEs *pIes,
+						bool fForced, uint8_t sessionId)
+{
+	tCsrScanResult *pCsrBssDescription = NULL;
+	tAniSSID tmpSsid;
+	v_TIME_t timer = 0;
+	int result;
+
+	tmpSsid.length = 0;
+	result = csr_remove_dup_bss_description(pMac, pSirBssDescription,
+						pIes, &tmpSsid, &timer,
+						fForced);
+	pCsrBssDescription = csr_scan_save_bss_description(pMac,
+					pSirBssDescription, pIes, sessionId);
+	if (result && (pCsrBssDescription != NULL)) {
+		/*
+		* Check if the new one has SSID it it, if not, use the older
+		* SSID if it exists.
+		*/
+		if ((0 == pCsrBssDescription->Result.ssId.length)
+		    && tmpSsid.length) {
+			/*
+			 * New BSS has a hidden SSID and old one has the SSID.
+			 * Keep the SSID only if diff of saved SSID time and
+			 * current time is less than 1 min to avoid side effect
+			 * of saving SSID with old one is that if AP changes its
+			 * SSID while remain hidden, we may never see it and
+			 * also to address the requirement of. When we remove
+			 * hidden ssid from the profile i.e., forget the SSID
+			 * via GUI that SSID shouldn't see in the profile
+			 */
+			if ((cdf_mc_timer_get_system_time() - timer) <=
+			    HIDDEN_TIMER) {
+				pCsrBssDescription->Result.ssId = tmpSsid;
+				pCsrBssDescription->Result.timer = timer;
+			}
+		}
+	}
+
+	return pCsrBssDescription;
+}
+
+void csr_purge_channel_power(tpAniSirGlobal pMac, tDblLinkList *pChannelList)
+{
+	tCsrChannelPowerInfo *pChannelSet;
+	tListElem *pEntry;
+
+	csr_ll_lock(pChannelList);
+	/*
+	* Remove the channel sets from the learned list and put them
+	* in the free list
+	*/
+	while ((pEntry = csr_ll_remove_head(pChannelList,
+					    LL_ACCESS_NOLOCK)) != NULL) {
+		pChannelSet = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link);
+		if (pChannelSet)
+			cdf_mem_free(pChannelSet);
+	}
+	csr_ll_unlock(pChannelList);
+	return;
+}
+
+/*
+ * Save the channelList into the ultimate storage as the final stage of channel
+ * Input: pCountryInfo -- the country code (e.g. "USI"), channel list, and power
+ * limit are all stored inside this data structure
+ */
+CDF_STATUS csr_save_to_channel_power2_g_5_g(tpAniSirGlobal pMac,
+					    uint32_t tableSize,
+					    tSirMacChanInfo *channelTable)
+{
+	uint32_t i = tableSize / sizeof(tSirMacChanInfo);
+	tSirMacChanInfo *pChannelInfo;
+	tCsrChannelPowerInfo *pChannelSet;
+	bool f2GHzInfoFound = false;
+	bool f2GListPurged = false, f5GListPurged = false;
+
+	pChannelInfo = channelTable;
+	/* atleast 3 bytes have to be remaining  -- from "countryString" */
+	while (i--) {
+		pChannelSet = cdf_mem_malloc(sizeof(tCsrChannelPowerInfo));
+		if (NULL == pChannelSet) {
+			pChannelInfo++;
+			continue;
+		}
+		cdf_mem_set(pChannelSet, sizeof(tCsrChannelPowerInfo), 0);
+		pChannelSet->firstChannel = pChannelInfo->firstChanNum;
+		pChannelSet->numChannels = pChannelInfo->numChannels;
+		/*
+		 * Now set the inter-channel offset based on the frequency band
+		 * the channel set lies in
+		 */
+		if ((CDS_IS_CHANNEL_24GHZ(pChannelSet->firstChannel)) &&
+		    ((pChannelSet->firstChannel +
+		      (pChannelSet->numChannels - 1)) <=
+		     CDS_MAX_24GHz_CHANNEL_NUMBER)) {
+			pChannelSet->interChannelOffset = 1;
+			f2GHzInfoFound = true;
+		} else if ((CDS_IS_CHANNEL_5GHZ(pChannelSet->firstChannel))
+		    && ((pChannelSet->firstChannel +
+		      ((pChannelSet->numChannels - 1) * 4)) <=
+		     CDS_MAX_5GHz_CHANNEL_NUMBER)) {
+			pChannelSet->interChannelOffset = 4;
+			f2GHzInfoFound = false;
+		} else {
+			sms_log(pMac, LOGW,
+				FL("Invalid Channel %d Present in Country IE"),
+				pChannelSet->firstChannel);
+			cdf_mem_free(pChannelSet);
+			return CDF_STATUS_E_FAILURE;
+		}
+		pChannelSet->txPower = CDF_MIN(pChannelInfo->maxTxPower,
+					pMac->roam.configParam.nTxPowerCap);
+		if (f2GHzInfoFound) {
+			if (!f2GListPurged) {
+				/* purge previous results if found new */
+				csr_purge_channel_power(pMac,
+							&pMac->scan.
+							channelPowerInfoList24);
+				f2GListPurged = true;
+			}
+			if (CSR_IS_OPERATING_BG_BAND(pMac)) {
+				/* add to the list of 2.4 GHz channel sets */
+				csr_ll_insert_tail(&pMac->scan.
+						   channelPowerInfoList24,
+						   &pChannelSet->link,
+						   LL_ACCESS_LOCK);
+			} else {
+				sms_log(pMac, LOGW,
+					FL("Adding 11B/G ch in 11A. 1st ch %d"),
+					pChannelSet->firstChannel);
+				cdf_mem_free(pChannelSet);
+			}
+		} else {
+			/* 5GHz info found */
+			if (!f5GListPurged) {
+				/* purge previous results if found new */
+				csr_purge_channel_power(pMac,
+							&pMac->scan.
+							channelPowerInfoList5G);
+				f5GListPurged = true;
+			}
+			if (CSR_IS_OPERATING_A_BAND(pMac)) {
+				/* add to the list of 5GHz channel sets */
+				csr_ll_insert_tail(&pMac->scan.
+						   channelPowerInfoList5G,
+						   &pChannelSet->link,
+						   LL_ACCESS_LOCK);
+			} else {
+				sms_log(pMac, LOGW,
+					FL("Adding 11A ch in B/G. 1st ch %d"),
+					pChannelSet->firstChannel);
+				cdf_mem_free(pChannelSet);
+			}
+		}
+		pChannelInfo++; /* move to next entry */
+	}
+	return CDF_STATUS_SUCCESS;
+}
+
+static void csr_clear_dfs_channel_list(tpAniSirGlobal pMac)
+{
+	tSirMbMsg *pMsg;
+	uint16_t msgLen;
+
+	msgLen = (uint16_t) (sizeof(tSirMbMsg));
+	pMsg = cdf_mem_malloc(msgLen);
+	if (NULL != pMsg) {
+		cdf_mem_set((void *)pMsg, msgLen, 0);
+		pMsg->type = eWNI_SME_CLEAR_DFS_CHANNEL_LIST;
+		pMsg->msgLen = msgLen;
+		cds_send_mb_message_to_mac(pMsg);
+	}
+}
+
+void csr_apply_power2_current(tpAniSirGlobal pMac)
+{
+	sms_log(pMac, LOG3, FL(" Updating Cfg with power settings"));
+	csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList24,
+				 WNI_CFG_MAX_TX_POWER_2_4);
+	csr_save_tx_power_to_cfg(pMac, &pMac->scan.channelPowerInfoList5G,
+				 WNI_CFG_MAX_TX_POWER_5);
+}
+
+void csr_apply_channel_power_info_to_fw(tpAniSirGlobal mac_ctx,
+					  tCsrChannel *ch_lst,
+					  uint8_t *countryCode)
+{
+	int i;
+	uint8_t num_ch = 0;
+	uint8_t tempNumChannels = 0;
+	tCsrChannel tmp_ch_lst;
+
+	if (ch_lst->numChannels) {
+		tempNumChannels = CSR_MIN(ch_lst->numChannels,
+					  WNI_CFG_VALID_CHANNEL_LIST_LEN);
+		for (i = 0; i < tempNumChannels; i++) {
+			tmp_ch_lst.channelList[num_ch] = ch_lst->channelList[i];
+			num_ch++;
+		}
+		tmp_ch_lst.numChannels = num_ch;
+		/* Store the channel+power info in the global place: Cfg */
+		csr_apply_power2_current(mac_ctx);
+		csr_set_cfg_valid_channel_list(mac_ctx, tmp_ch_lst.channelList,
+					       tmp_ch_lst.numChannels);
+		/*
+		 * extend scan capability, build a scan list based on the
+		 * channel list : channel# + active/passive scan
+		 */
+		csr_set_cfg_scan_control_list(mac_ctx, countryCode,
+					      &tmp_ch_lst);
+		/* Send msg to Lim to clear DFS channel list */
+		csr_clear_dfs_channel_list(mac_ctx);
+	} else {
+		sms_log(mac_ctx, LOGE, FL("11D channel list is empty"));
+	}
+	csr_set_cfg_country_code(mac_ctx, countryCode);
+}
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+static void csr_diag_reset_country_information(tpAniSirGlobal pMac)
+{
+
+	host_log_802_11d_pkt_type *p11dLog;
+	int Index;
+	WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type,
+				 LOG_WLAN_80211D_C);
+	if (!p11dLog)
+		return;
+
+	p11dLog->eventId = WLAN_80211D_EVENT_RESET;
+	cdf_mem_copy(p11dLog->countryCode, pMac->scan.countryCodeCurrent, 3);
+	p11dLog->numChannel = pMac->scan.base_channels.numChannels;
+	if (p11dLog->numChannel <= HOST_LOG_MAX_NUM_CHANNEL) {
+		cdf_mem_copy(p11dLog->Channels,
+			     pMac->scan.base_channels.channelList,
+			     p11dLog->numChannel);
+		for (Index = 0;
+		     Index < pMac->scan.base_channels.numChannels;
+		     Index++) {
+			p11dLog->TxPwr[Index] = CDF_MIN(
+				pMac->scan.defaultPowerTable[Index].pwr,
+				pMac->roam.configParam.nTxPowerCap);
+		}
+	}
+	if (!pMac->roam.configParam.Is11dSupportEnabled)
+		p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
+	else
+		p11dLog->supportMultipleDomain =
+			WLAN_80211D_SUPPORT_MULTI_DOMAIN;
+	WLAN_HOST_DIAG_LOG_REPORT(p11dLog);
+}
+#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
+
+/**
+ * csr_apply_channel_power_info_wrapper() - sends channel info to fw
+ * @pMac: main MAC data structure
+ *
+ * This function sends the channel power info to firmware
+ *
+ * Return: none
+ */
+void csr_apply_channel_power_info_wrapper(tpAniSirGlobal pMac)
+{
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+	csr_diag_reset_country_information(pMac);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT_CSR */
+	csr_prune_channel_list_for_mode(pMac, &pMac->scan.base_channels);
+	csr_save_channel_power_for_band(pMac, false);
+	csr_save_channel_power_for_band(pMac, true);
+	/* apply the channel list, power settings, and the country code. */
+	csr_apply_channel_power_info_to_fw(pMac,
+		&pMac->scan.base_channels, pMac->scan.countryCodeCurrent);
+	/* clear the 11d channel list */
+	cdf_mem_set(&pMac->scan.channels11d, sizeof(pMac->scan.channels11d), 0);
+}
+
+void csr_clear_votes_for_country_info(tpAniSirGlobal pMac)
+{
+	pMac->scan.countryCodeCount = 0;
+	cdf_mem_set(pMac->scan.votes11d,
+		    sizeof(tCsrVotes11d) * CSR_MAX_NUM_COUNTRY_CODE, 0);
+}
+
+void csr_add_vote_for_country_info(tpAniSirGlobal pMac, uint8_t *pCountryCode)
+{
+	bool match = false;
+	uint8_t i;
+
+	/* convert to UPPER here so we are assured
+	 * the strings are always in upper case.
+	 */
+	for (i = 0; i < 3; i++) {
+		pCountryCode[i] = (uint8_t) csr_to_upper(pCountryCode[i]);
+	}
+
+	/* Some of the 'old' Cisco 350 series AP's advertise NA as the
+	 * country code (for North America ??). NA is not a valid country code
+	 * or domain so let's allow this by changing it to the proper
+	 * country code (which is US).  We've also seen some NETGEAR AP's
+	 * that have "XX " as the country code with valid 2.4 GHz US channel
+	 * information.  If we cannot find the country code advertised in the
+	 * 11d information element, let's default to US.
+	 */
+
+	if (!CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(pMac,
+						pCountryCode, NULL,
+						COUNTRY_QUERY))) {
+		pCountryCode[0] = '0';
+		pCountryCode[1] = '0';
+	}
+
+	/* We've seen some of the AP's improperly put a 0 for the
+	 * third character of the country code. spec says valid charcters are
+	 * 'O' (for outdoor), 'I' for Indoor, or ' ' (space; for either).
+	 * if we see a 0 in this third character, let's change it to a ' '.
+	 */
+	if (0 == pCountryCode[2]) {
+		pCountryCode[2] = ' ';
+	}
+
+	for (i = 0; i < pMac->scan.countryCodeCount; i++) {
+		match = (cdf_mem_compare(pMac->scan.votes11d[i].countryCode,
+					 pCountryCode, 2));
+		if (match) {
+			break;
+		}
+	}
+
+	if (match) {
+		pMac->scan.votes11d[i].votes++;
+	} else {
+		cdf_mem_copy(pMac->scan.votes11d[pMac->scan.countryCodeCount].
+			     countryCode, pCountryCode, 3);
+		pMac->scan.votes11d[pMac->scan.countryCodeCount].votes = 1;
+		pMac->scan.countryCodeCount++;
+	}
+
+	return;
+}
+
+bool csr_elected_country_info(tpAniSirGlobal pMac)
+{
+	bool fRet = false;
+	uint8_t maxVotes = 0;
+	uint8_t i, j = 0;
+
+	if (!pMac->scan.countryCodeCount) {
+		return fRet;
+	}
+	maxVotes = pMac->scan.votes11d[0].votes;
+	fRet = true;
+
+	for (i = 1; i < pMac->scan.countryCodeCount; i++) {
+		/* If we have a tie for max votes for 2 different country codes,
+		 * pick random.we can put some more intelligence - TBD
+		 */
+		if (maxVotes < pMac->scan.votes11d[i].votes) {
+			CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
+				  " Votes for Country %c%c : %d\n",
+				  pMac->scan.votes11d[i].countryCode[0],
+				  pMac->scan.votes11d[i].countryCode[1],
+				  pMac->scan.votes11d[i].votes);
+
+			maxVotes = pMac->scan.votes11d[i].votes;
+			j = i;
+			fRet = true;
+		}
+
+	}
+	if (fRet) {
+		cdf_mem_copy(pMac->scan.countryCodeElected,
+		       pMac->scan.votes11d[j].countryCode,
+		       WNI_CFG_COUNTRY_CODE_LEN);
+		cdf_mem_copy(pMac->scan.countryCode11d,
+		       pMac->scan.votes11d[j].countryCode,
+		       WNI_CFG_COUNTRY_CODE_LEN);
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
+			  "Selected Country is %c%c With count %d\n",
+			  pMac->scan.votes11d[j].countryCode[0],
+			  pMac->scan.votes11d[j].countryCode[1],
+			  pMac->scan.votes11d[j].votes);
+	}
+	return fRet;
+}
+
+/**
+ * csr_set_country_code() - Set country code
+ * @pMac: main MAC data structure
+ * @pCountry: ptr to Country Code
+ *
+ * This function sends the channel power info to firmware
+ *
+ * Return: none
+ */
+CDF_STATUS csr_set_country_code(tpAniSirGlobal pMac, uint8_t *pCountry)
+{
+	CDF_STATUS status = CDF_STATUS_E_INVAL;
+	v_REGDOMAIN_t domainId;
+
+	if (pCountry) {
+
+		status = csr_get_regulatory_domain_for_country(pMac, pCountry,
+							       &domainId,
+							       COUNTRY_USER);
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			cdf_mem_copy(pMac->scan.countryCodeCurrent,
+				     pCountry,
+				     WNI_CFG_COUNTRY_CODE_LEN);
+			csr_set_cfg_country_code(pMac, pCountry);
+		}
+	}
+	return status;
+}
+
+/* caller allocated memory for pNumChn and pChnPowerInfo */
+/* As input, *pNumChn has the size of the array of pChnPowerInfo */
+/* Upon return, *pNumChn has the number of channels assigned. */
+void csr_get_channel_power_info(tpAniSirGlobal pMac, tDblLinkList *list,
+				uint32_t *num_ch,
+				tChannelListWithPower *chn_pwr_info)
+{
+	tListElem *entry;
+	uint32_t chn_idx = 0, idx;
+	tCsrChannelPowerInfo *ch_set;
+
+	/* Get 2.4Ghz first */
+	entry = csr_ll_peek_head(list, LL_ACCESS_LOCK);
+	while (entry && (chn_idx < *num_ch)) {
+		ch_set = GET_BASE_ADDR(entry, tCsrChannelPowerInfo, link);
+		for (idx = 0; (idx < ch_set->numChannels)
+				&& (chn_idx < *num_ch); idx++) {
+			chn_pwr_info[chn_idx].chanId =
+				(uint8_t) (ch_set->firstChannel
+				 + (idx * ch_set->interChannelOffset));
+			chn_pwr_info[chn_idx++].pwr = ch_set->txPower;
+		}
+		entry = csr_ll_next(list, entry, LL_ACCESS_LOCK);
+	}
+	*num_ch = chn_idx;
+
+	return;
+}
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+void csr_diag_apply_country_info(tpAniSirGlobal mac_ctx)
+{
+	host_log_802_11d_pkt_type *p11dLog;
+	tChannelListWithPower chnPwrInfo[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+	uint32_t nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN, nTmp;
+
+	WLAN_HOST_DIAG_LOG_ALLOC(p11dLog, host_log_802_11d_pkt_type,
+				 LOG_WLAN_80211D_C);
+	if (!p11dLog)
+		return;
+
+	p11dLog->eventId = WLAN_80211D_EVENT_COUNTRY_SET;
+	cdf_mem_copy(p11dLog->countryCode, mac_ctx->scan.countryCode11d, 3);
+	p11dLog->numChannel = mac_ctx->scan.channels11d.numChannels;
+	if (p11dLog->numChannel > HOST_LOG_MAX_NUM_CHANNEL)
+		goto diag_end;
+
+	cdf_mem_copy(p11dLog->Channels,
+		     mac_ctx->scan.channels11d.channelList,
+		     p11dLog->numChannel);
+	csr_get_channel_power_info(mac_ctx,
+				&mac_ctx->scan.channelPowerInfoList24,
+				&nChnInfo, chnPwrInfo);
+	nTmp = nChnInfo;
+	nChnInfo = WNI_CFG_VALID_CHANNEL_LIST_LEN - nTmp;
+	csr_get_channel_power_info(mac_ctx,
+				&mac_ctx->scan.channelPowerInfoList5G,
+				&nChnInfo, &chnPwrInfo[nTmp]);
+	for (nTmp = 0; nTmp < p11dLog->numChannel; nTmp++) {
+		for (nChnInfo = 0;
+		     nChnInfo < WNI_CFG_VALID_CHANNEL_LIST_LEN;
+		     nChnInfo++) {
+			if (p11dLog->Channels[nTmp] ==
+			    chnPwrInfo[nChnInfo].chanId) {
+				p11dLog->TxPwr[nTmp] =
+					chnPwrInfo[nChnInfo].pwr;
+				break;
+			}
+		}
+	}
+diag_end:
+	if (!mac_ctx->roam.configParam.Is11dSupportEnabled)
+		p11dLog->supportMultipleDomain = WLAN_80211D_DISABLED;
+	else
+		p11dLog->supportMultipleDomain =
+				WLAN_80211D_SUPPORT_MULTI_DOMAIN;
+	WLAN_HOST_DIAG_LOG_REPORT(p11dLog);
+}
+#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
+
+/**
+ * csr_apply_country_information() - apply country code information
+ * @pMac: core MAC data structure
+ *
+ * This function programs the new country code
+ *
+ * Return: none
+ */
+void csr_apply_country_information(tpAniSirGlobal pMac)
+{
+	v_REGDOMAIN_t domainId;
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	if (!csr_is11d_supported(pMac)
+	    || 0 == pMac->scan.channelOf11dInfo)
+		return;
+	status = csr_get_regulatory_domain_for_country(pMac,
+			pMac->scan.countryCode11d, &domainId, COUNTRY_QUERY);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		return;
+	/* Check whether we need to enforce default domain */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+	csr_diag_apply_country_info(pMac);
+#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
+
+	if (pMac->scan.domainIdCurrent != domainId)
+		return;
+	if (pMac->scan.domainIdCurrent != domainId) {
+		sms_log(pMac, LOGW, FL("Domain Changed Old %d, new %d"),
+			pMac->scan.domainIdCurrent, domainId);
+		status = wma_set_reg_domain(pMac, domainId);
+	}
+	if (status != CDF_STATUS_SUCCESS)
+		sms_log(pMac, LOGE, FL("fail to set regId %d"), domainId);
+	pMac->scan.domainIdCurrent = domainId;
+	/* switch to active scans using this new channel list */
+	pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
+}
+
+void csr_save_channel_power_for_band(tpAniSirGlobal pMac, bool fill_5f)
+{
+	uint32_t idx, count = 0;
+	tSirMacChanInfo *chan_info;
+	tSirMacChanInfo *ch_info_start;
+	int32_t max_ch_idx;
+	bool tmp_bool;
+	uint8_t ch = 0;
+
+	max_ch_idx =
+		(pMac->scan.base_channels.numChannels <
+		WNI_CFG_VALID_CHANNEL_LIST_LEN) ?
+		pMac->scan.base_channels.numChannels :
+		WNI_CFG_VALID_CHANNEL_LIST_LEN;
+
+	chan_info = cdf_mem_malloc(sizeof(tSirMacChanInfo) *
+				   WNI_CFG_VALID_CHANNEL_LIST_LEN);
+	if (NULL == chan_info)
+		return;
+
+	cdf_mem_set(chan_info, sizeof(tSirMacChanInfo) *
+		    WNI_CFG_VALID_CHANNEL_LIST_LEN, 0);
+	ch_info_start = chan_info;
+	for (idx = 0; idx < max_ch_idx; idx++) {
+		ch = pMac->scan.defaultPowerTable[idx].chanId;
+		tmp_bool =  (fill_5f && CDS_IS_CHANNEL_5GHZ(ch))
+			|| (!fill_5f && CDS_IS_CHANNEL_24GHZ(ch));
+		if (!tmp_bool)
+			continue;
+
+		if (count >= WNI_CFG_VALID_CHANNEL_LIST_LEN) {
+			sms_log(pMac, LOGW, FL("count(%d) exceeded"), count);
+			break;
+		}
+
+		chan_info->firstChanNum =
+			pMac->scan.defaultPowerTable[idx].chanId;
+		chan_info->numChannels = 1;
+		chan_info->maxTxPower =
+			CDF_MIN(pMac->scan.defaultPowerTable[idx].pwr,
+				pMac->roam.configParam.nTxPowerCap);
+		chan_info++;
+		count++;
+	}
+	if (count) {
+		csr_save_to_channel_power2_g_5_g(pMac,
+				count * sizeof(tSirMacChanInfo), ch_info_start);
+	}
+	cdf_mem_free(ch_info_start);
+}
+
+bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId)
+{
+	bool fRet = false;
+	uint32_t i;
+
+	for (i = 0; i < pMac->scan.base_channels.numChannels; i++) {
+		if (channelId ==
+		    pMac->scan.base_channels.channelList[i]) {
+			fRet = true;
+			break;
+		}
+	}
+
+	return fRet;
+}
+
+/*
+ * 802.11D only: Gather 11d IE via beacon or Probe response and store them in pAdapter->channels11d
+ */
+bool csr_learn_11dcountry_information(tpAniSirGlobal pMac,
+				   tSirBssDescription *pSirBssDesc,
+				   tDot11fBeaconIEs *pIes, bool fForce)
+{
+	CDF_STATUS status;
+	uint8_t *pCountryCodeSelected;
+	bool fRet = false;
+	v_REGDOMAIN_t domainId;
+	tDot11fBeaconIEs *pIesLocal = pIes;
+	bool useVoting = false;
+
+	if (CDF_SAP_MODE == cds_get_conparam())
+		return CDF_STATUS_SUCCESS;
+
+	if ((NULL == pSirBssDesc) && (NULL == pIes))
+		useVoting = true;
+
+	/* check if .11d support is enabled */
+	if (!csr_is11d_supported(pMac))
+		goto free_ie;
+
+	if (false == useVoting) {
+		if (!pIesLocal &&
+		   (!CDF_IS_STATUS_SUCCESS(
+			csr_get_parsed_bss_description_ies(
+				pMac, pSirBssDesc, &pIesLocal))))
+			goto free_ie;
+		/* check if country information element is present */
+		if (!pIesLocal->Country.present)
+			/* No country info */
+			goto free_ie;
+		status = csr_get_regulatory_domain_for_country(pMac,
+				pIesLocal->Country.country, &domainId,
+				COUNTRY_QUERY);
+		if (CDF_IS_STATUS_SUCCESS(status)
+		    && (domainId == REGDOMAIN_WORLD))
+			goto free_ie;
+	} /* useVoting == false */
+
+	if (false == useVoting)
+		pCountryCodeSelected = pIesLocal->Country.country;
+	else
+		pCountryCodeSelected = pMac->scan.countryCodeElected;
+
+	status = csr_get_regulatory_domain_for_country(pMac,
+				pCountryCodeSelected, &domainId, COUNTRY_IE);
+	if (status != CDF_STATUS_SUCCESS) {
+		sms_log(pMac, LOGE, FL("fail to get regId %d"), domainId);
+		fRet = false;
+		goto free_ie;
+	}
+
+	/* updating 11d Country Code with Country code selected. */
+	cdf_mem_copy(pMac->scan.countryCode11d, pCountryCodeSelected,
+		     WNI_CFG_COUNTRY_CODE_LEN);
+	fRet = true;
+free_ie:
+	if (!pIes && pIesLocal) {
+		/* locally allocated */
+		cdf_mem_free(pIesLocal);
+	}
+	return fRet;
+}
+
+void csr_save_scan_results(tpAniSirGlobal pMac, uint8_t reason,
+				  uint8_t sessionId)
+{
+	sms_log(pMac, LOG4, "%s: Saving scan results", __func__);
+
+	/* initialize this to false. profMoveInterimScanResultsToMainList() routine */
+	/* will set this to the channel where an .11d beacon is seen */
+	pMac->scan.channelOf11dInfo = 0;
+	/* move the scan results from interim list to the main scan list */
+	csr_move_temp_scan_results_to_main_list(pMac, reason, sessionId);
+
+	/* Now check if we gathered any domain/country specific information */
+	/* If so, we should update channel list and apply Tx power settings */
+	if (csr_is11d_supported(pMac)) {
+		csr_apply_country_information(pMac);
+	}
+}
+
+void csr_reinit_scan_cmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+	switch (pCommand->u.scanCmd.reason) {
+	case eCsrScanAbortNormalScan:
+	default:
+		csr_scan_free_request(pMac, &pCommand->u.scanCmd.u.scanRequest);
+		break;
+	}
+	if (pCommand->u.scanCmd.pToRoamProfile) {
+		csr_release_profile(pMac, pCommand->u.scanCmd.pToRoamProfile);
+		cdf_mem_free(pCommand->u.scanCmd.pToRoamProfile);
+	}
+	cdf_mem_set(&pCommand->u.scanCmd, sizeof(tScanCmd), 0);
+}
+
+eCsrScanCompleteNextCommand csr_scan_get_next_command_state(tpAniSirGlobal pMac,
+							    tSmeCmd *pCommand,
+							    bool fSuccess)
+{
+	eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
+
+	switch (pCommand->u.scanCmd.reason) {
+	case eCsrScan11d1:
+		NextCommand =
+			(fSuccess) ? eCsrNext11dScan1Success :
+			eCsrNext11dScan1Failure;
+		break;
+	case eCsrScan11d2:
+		NextCommand =
+			(fSuccess) ? eCsrNext11dScan2Success :
+			eCsrNext11dScan2Failure;
+		break;
+	case eCsrScan11dDone:
+		NextCommand = eCsrNext11dScanComplete;
+		break;
+	case eCsrScanLostLink1:
+		NextCommand =
+			(fSuccess) ? eCsrNextLostLinkScan1Success :
+			eCsrNextLostLinkScan1Failed;
+		break;
+	case eCsrScanLostLink2:
+		NextCommand =
+			(fSuccess) ? eCsrNextLostLinkScan2Success :
+			eCsrNextLostLinkScan2Failed;
+		break;
+	case eCsrScanLostLink3:
+		NextCommand =
+			(fSuccess) ? eCsrNextLostLinkScan3Success :
+			eCsrNextLostLinkScan3Failed;
+		break;
+	case eCsrScanForSsid:
+		NextCommand =
+			(fSuccess) ? eCsrNexteScanForSsidSuccess :
+			eCsrNexteScanForSsidFailure;
+		break;
+	default:
+		NextCommand = eCsrNextScanNothing;
+		break;
+	}
+	return NextCommand;
+}
+
+/* Return whether the pCommand is finished. */
+bool csr_handle_scan11d1_failure(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+	bool fRet = true;
+
+	/* Apply back the default setting and passively scan one more time. */
+	csr_apply_channel_power_info_wrapper(pMac);
+	pCommand->u.scanCmd.reason = eCsrScan11d2;
+	if (CDF_IS_STATUS_SUCCESS(csr_scan_channels(pMac, pCommand))) {
+		fRet = false;
+	}
+
+	return fRet;
+}
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+static void
+csr_diag_scan_complete(tpAniSirGlobal pMac,
+		       tSmeCmd *pCommand,
+		       tSirSmeScanRsp *pScanRsp)
+{
+	host_log_scan_pkt_type *pScanLog = NULL;
+	tScanResultHandle hScanResult;
+	tCsrScanResultInfo *pScanResult;
+	tDot11fBeaconIEs *pIes;
+	int n = 0, c = 0;
+	CDF_STATUS status;
+
+	WLAN_HOST_DIAG_LOG_ALLOC(pScanLog,
+				 host_log_scan_pkt_type,
+				 LOG_WLAN_SCAN_C);
+	if (!pScanLog)
+		return;
+
+	if (eCsrScanProbeBss == pCommand->u.scanCmd.reason) {
+		pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_RSP;
+	} else {
+		if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)
+			pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_RSP;
+		else
+			pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_RSP;
+	}
+	if (eSIR_SME_SUCCESS != pScanRsp->statusCode) {
+		pScanLog->status = WLAN_SCAN_STATUS_FAILURE;
+		WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
+		return;
+	}
+
+	status = csr_scan_get_result(pMac, NULL, &hScanResult);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
+		return;
+	}
+
+	pScanResult = csr_scan_result_get_next(pMac, hScanResult);
+	while (pScanResult != NULL) {
+		if (n < HOST_LOG_MAX_NUM_BSSID) {
+			status = csr_get_parsed_bss_description_ies(pMac,
+					&pScanResult->BssDescriptor, &pIes);
+			if (!CDF_IS_STATUS_SUCCESS(status)) {
+				sms_log(pMac, LOGE, FL("fail to parse IEs"));
+				break;
+			}
+			cdf_mem_copy(pScanLog->bssid[n],
+				pScanResult->BssDescriptor.bssId, 6);
+			if (pIes && pIes->SSID.present &&
+			    HOST_LOG_MAX_SSID_SIZE >= pIes->SSID.num_ssid) {
+				cdf_mem_copy(pScanLog->ssid[n],
+					pIes->SSID.ssid,
+					pIes->SSID.num_ssid);
+			}
+			cdf_mem_free(pIes);
+			n++;
+		}
+		c++;
+		pScanResult = csr_scan_result_get_next(pMac, hScanResult);
+	}
+	pScanLog->numSsid = (uint8_t) n;
+	pScanLog->totalSsid = (uint8_t) c;
+	csr_scan_result_purge(pMac, hScanResult);
+	WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
+
+	csr_diag_event_report(pMac, eCSR_EVENT_SCAN_COMPLETE, eSIR_SUCCESS,
+			      eSIR_SUCCESS);
+	if (c > 0)
+		csr_diag_event_report(pMac, eCSR_EVENT_SCAN_RES_FOUND,
+				      eSIR_SUCCESS, eSIR_SUCCESS);
+}
+#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
+
+static void
+csr_handle_nxt_cmd(tpAniSirGlobal mac_ctx, tSmeCmd *pCommand,
+		   eCsrScanCompleteNextCommand *nxt_cmd,
+		   bool *remove_cmd, uint32_t session_id)
+{
+	CDF_STATUS status;
+	switch (*nxt_cmd) {
+	case eCsrNext11dScan1Success:
+	case eCsrNext11dScan2Success:
+		sms_log(mac_ctx, LOG2,
+			FL("11dScan1/3 produced results. Reissue Active scan"));
+		/*
+		 * if we found country information, no need to continue scanning
+		 * further, bail out
+		 */
+		*remove_cmd = true;
+		*nxt_cmd = eCsrNext11dScanComplete;
+		break;
+	case eCsrNext11dScan1Failure:
+		/*
+		 * We are not done yet. 11d scan fail once. We will try to reset
+		 * anything and do it over again. The only meaningful thing for
+		 * this retry is that we cannot find 11d information after a
+		 * reset so we clear the "old" 11d info and give it once more
+		 * chance
+		 */
+		*remove_cmd = csr_handle_scan11d1_failure(mac_ctx, pCommand);
+		if (*remove_cmd)
+			*nxt_cmd = eCsrNext11dScanComplete;
+		break;
+	case eCsrNextLostLinkScan1Success:
+		status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
+							    eCsrLostLink1);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
+		break;
+	case eCsrNextLostLinkScan2Success:
+		status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
+							    eCsrLostLink2);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
+		break;
+	case eCsrNextLostLinkScan3Success:
+		status = csr_issue_roam_after_lostlink_scan(mac_ctx, session_id,
+							    eCsrLostLink3);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			csr_scan_handle_failed_lostlink3(mac_ctx, session_id);
+		break;
+	case eCsrNextLostLinkScan1Failed:
+		csr_scan_handle_failed_lostlink1(mac_ctx, session_id);
+		break;
+	case eCsrNextLostLinkScan2Failed:
+		csr_scan_handle_failed_lostlink2(mac_ctx, session_id);
+		break;
+	case eCsrNextLostLinkScan3Failed:
+		csr_scan_handle_failed_lostlink3(mac_ctx, session_id);
+		break;
+	case eCsrNexteScanForSsidSuccess:
+		csr_scan_handle_search_for_ssid(mac_ctx, pCommand);
+		break;
+	case eCsrNexteScanForSsidFailure:
+		csr_scan_handle_search_for_ssid_failure(mac_ctx, pCommand);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * csr_get_active_scan_entry() - To get scan entry from active command list
+ *
+ * @mac_ctx - MAC context
+ * @scan_id - Scan identifier of the scan request
+ * @entry - scan entry returned.
+ *
+ * Scan entry in the active scan list mapping to the sent scan id
+ * is returned to the caller.
+ *
+ * Return: CDF_STATUS.
+ */
+CDF_STATUS csr_get_active_scan_entry(tpAniSirGlobal mac_ctx,
+	uint32_t scan_id, tListElem **entry)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tListElem *localentry;
+	tSmeCmd *cmd;
+	uint32_t cmd_scan_id = 0;
+
+	csr_ll_lock(&mac_ctx->sme.smeScanCmdActiveList);
+
+	if (csr_ll_is_list_empty(&mac_ctx->sme.smeScanCmdActiveList,
+			LL_ACCESS_NOLOCK)) {
+		sms_log(mac_ctx, LOGE,
+			FL(" Active list Empty scanId: %d"), scan_id);
+		return CDF_STATUS_SUCCESS;
+	}
+	localentry = csr_ll_peek_head(&mac_ctx->sme.smeScanCmdActiveList,
+			LL_ACCESS_NOLOCK);
+	do {
+		cmd = GET_BASE_ADDR(localentry, tSmeCmd, Link);
+		if (cmd->command == eSmeCommandScan)
+			cmd_scan_id = cmd->u.scanCmd.u.scanRequest.scan_id;
+		else if (cmd->command == eSmeCommandRemainOnChannel)
+			cmd_scan_id = cmd->u.remainChlCmd.scan_id;
+		if (cmd_scan_id == scan_id) {
+			sms_log(mac_ctx, LOG1, FL(" scanId Matched %d"),
+					scan_id);
+			*entry = localentry;
+			csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
+			return CDF_STATUS_SUCCESS;
+		}
+		localentry = csr_ll_next(&mac_ctx->sme.smeScanCmdActiveList,
+				localentry, LL_ACCESS_NOLOCK);
+	} while (localentry);
+	csr_ll_unlock(&mac_ctx->sme.smeScanCmdActiveList);
+	return status;
+}
+
+/* Return whether the command should be removed */
+bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp)
+{
+	eCsrScanCompleteNextCommand NextCommand = eCsrNextScanNothing;
+	tListElem *pEntry = NULL;
+	tSmeCmd *pCommand;
+	bool fRemoveCommand = true;
+	bool fSuccess;
+	uint32_t sessionId = 0;
+
+	csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry);
+	if (!pEntry) {
+		sms_log(pMac, LOGE,
+			FL("Scan Completion called but NO cmd ACTIVE ..."));
+		return false;
+	}
+
+	pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+	/*
+	 * If the head of the queue is Active and it is a SCAN command, remove
+	 * and put this on the Free queue.
+	 */
+	if (eSmeCommandScan != pCommand->command) {
+		sms_log(pMac, LOGW,
+			FL("Scan Completion called, but active SCAN cmd"));
+		return false;
+	}
+
+	sessionId = pCommand->sessionId;
+	if (eSIR_SME_SUCCESS != pScanRsp->statusCode) {
+		fSuccess = false;
+	} else {
+		/*
+		 * pMac->scan.tempScanResults is not empty meaning the scan
+		 * found something. This check only valid here because
+		 * csrSaveScanresults is not yet called
+		 */
+		fSuccess = (!csr_ll_is_list_empty(&pMac->scan.tempScanResults,
+						  LL_ACCESS_LOCK));
+	}
+	if (pCommand->u.scanCmd.abortScanDueToBandChange) {
+		/*
+		 * Scan aborted due to band change
+		 * The scan results need to be flushed
+		 */
+		if (pCommand->u.scanCmd.callback
+		    != pMac->scan.callback11dScanDone) {
+			sms_log(pMac, LOG1, FL("Filtering the scan results"));
+			csr_scan_filter_results(pMac);
+		} else {
+			sms_log(pMac, LOG1,
+				FL("11d_scan_done, flushing the scan results"));
+		}
+		pCommand->u.scanCmd.abortScanDueToBandChange = false;
+	}
+	csr_save_scan_results(pMac, pCommand->u.scanCmd.reason, sessionId);
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+	csr_diag_scan_complete(pMac, pCommand, pScanRsp);
+#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
+	NextCommand = csr_scan_get_next_command_state(pMac, pCommand, fSuccess);
+	/* We reuse the command here instead reissue a new command */
+	csr_handle_nxt_cmd(pMac, pCommand, &NextCommand,
+			   &fRemoveCommand, sessionId);
+	return fRemoveCommand;
+}
+
+static void
+csr_scan_remove_dup_bss_description_from_interim_list(tpAniSirGlobal mac_ctx,
+					tSirBssDescription *bss_dscp,
+					tDot11fBeaconIEs *pIes)
+{
+	tListElem *pEntry;
+	tCsrScanResult *scan_bss_dscp;
+	int8_t scan_entry_rssi = 0;
+	/*
+	 * Walk through all the chained BssDescriptions. If we find a chained
+	 * BssDescription that matches the BssID of the BssDescription passed
+	 * in, then these must be duplicate scan results for this Bss. In that
+	 * case, remove the 'old' Bss description from the linked list.
+	 */
+	sms_log(mac_ctx, LOG4, FL(" for BSS " MAC_ADDRESS_STR " "),
+		MAC_ADDR_ARRAY(bss_dscp->bssId));
+	csr_ll_lock(&mac_ctx->scan.tempScanResults);
+	pEntry = csr_ll_peek_head(&mac_ctx->scan.tempScanResults,
+				 LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		scan_bss_dscp = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		/*
+		 * we have a duplicate scan results only when BSSID, SSID,
+		 * Channel and NetworkType matches
+		 */
+		scan_entry_rssi = scan_bss_dscp->Result.BssDescriptor.rssi;
+		if (csr_is_duplicate_bss_description(mac_ctx,
+			&scan_bss_dscp->Result.BssDescriptor, bss_dscp,
+			pIes, false)) {
+			/*
+			 * Following is mathematically a = (aX + b(100-X))/100
+			 * where:
+			 * a = bss_dscp->rssi, b = scan_entry_rssi
+			 * and X = CSR_SCAN_RESULT_RSSI_WEIGHT
+			 */
+			bss_dscp->rssi = (int8_t) ((((int32_t) bss_dscp->rssi *
+				CSR_SCAN_RESULT_RSSI_WEIGHT) +
+				((int32_t) scan_entry_rssi *
+				 (100 - CSR_SCAN_RESULT_RSSI_WEIGHT))) / 100);
+			/* Remove the 'old' entry from the list */
+			if (csr_ll_remove_entry(&mac_ctx->scan.tempScanResults,
+				pEntry, LL_ACCESS_NOLOCK)) {
+				csr_check_n_save_wsc_ie(mac_ctx, bss_dscp,
+							&scan_bss_dscp->Result.
+							BssDescriptor);
+				/*
+				 * we need to free the memory associated with
+				 * this node
+				 */
+				csr_free_scan_result_entry(mac_ctx,
+							   scan_bss_dscp);
+			}
+			/*
+			 * If we found a match, we can stop looking through
+			 * the list.
+			 */
+			break;
+		}
+		pEntry = csr_ll_next(&mac_ctx->scan.tempScanResults, pEntry,
+				     LL_ACCESS_NOLOCK);
+	}
+
+	csr_ll_unlock(&mac_ctx->scan.tempScanResults);
+}
+
+/* Caller allocated memory pfNewBssForConn to return whether new candidate for */
+/* current connection is found. Cannot be NULL */
+tCsrScanResult *csr_scan_save_bss_description_to_interim_list(tpAniSirGlobal pMac,
+							      tSirBssDescription *
+							      pBSSDescription,
+							      tDot11fBeaconIEs *pIes)
+{
+	tCsrScanResult *pCsrBssDescription = NULL;
+	uint32_t cbBSSDesc;
+	uint32_t cbAllocated;
+
+	/* figure out how big the BSS description is (the BSSDesc->length does NOT */
+	/* include the size of the length field itself). */
+	cbBSSDesc = pBSSDescription->length + sizeof(pBSSDescription->length);
+
+	cbAllocated = sizeof(tCsrScanResult) + cbBSSDesc;
+
+	sms_log(pMac, LOG4, FL("new BSS description, length %d, cbBSSDesc %d"),
+		cbAllocated, cbBSSDesc);
+	pCsrBssDescription = cdf_mem_malloc(cbAllocated);
+	if (NULL != pCsrBssDescription) {
+		cdf_mem_set(pCsrBssDescription, cbAllocated, 0);
+		cdf_mem_copy(&pCsrBssDescription->Result.BssDescriptor,
+			     pBSSDescription, cbBSSDesc);
+		pCsrBssDescription->AgingCount =
+			(int32_t) pMac->roam.configParam.agingCount;
+		sms_log(pMac, LOG4,
+			FL(" Set Aging Count = %d for BSS " MAC_ADDRESS_STR " "),
+			pCsrBssDescription->AgingCount,
+			MAC_ADDR_ARRAY(pCsrBssDescription->Result.BssDescriptor.
+				       bssId));
+		/* Save SSID separately for later use */
+		if (pIes->SSID.present
+		    && !csr_is_nullssid(pIes->SSID.ssid, pIes->SSID.num_ssid)) {
+			/* SSID not hidden */
+			uint32_t len = pIes->SSID.num_ssid;
+			if (len > SIR_MAC_MAX_SSID_LENGTH) {
+				/* truncate to fit in our struct */
+				len = SIR_MAC_MAX_SSID_LENGTH;
+			}
+			pCsrBssDescription->Result.ssId.length = len;
+			pCsrBssDescription->Result.timer =
+				cdf_mc_timer_get_system_time();
+			cdf_mem_copy(pCsrBssDescription->Result.ssId.ssId,
+				     pIes->SSID.ssid, len);
+		}
+		csr_ll_insert_tail(&pMac->scan.tempScanResults,
+				   &pCsrBssDescription->Link, LL_ACCESS_LOCK);
+	}
+
+	return pCsrBssDescription;
+}
+
+bool csr_is_duplicate_bss_description(tpAniSirGlobal pMac,
+				      tSirBssDescription *pSirBssDesc1,
+				      tSirBssDescription *pSirBssDesc2,
+				      tDot11fBeaconIEs *pIes2, bool fForced)
+{
+	bool fMatch = false;
+	tSirMacCapabilityInfo *pCap1, *pCap2;
+	tDot11fBeaconIEs *pIes1 = NULL;
+	tDot11fBeaconIEs *pIesTemp = pIes2;
+	CDF_STATUS status;
+
+	pCap1 = (tSirMacCapabilityInfo *) &pSirBssDesc1->capabilityInfo;
+	pCap2 = (tSirMacCapabilityInfo *) &pSirBssDesc2->capabilityInfo;
+
+	if (pCap1->ess != pCap2->ess)
+		goto free_ies;
+
+	if (pCap1->ess &&
+	    cdf_is_macaddr_equal((struct cdf_mac_addr *) pSirBssDesc1->bssId,
+				 (struct cdf_mac_addr *) pSirBssDesc2->bssId)
+	    && (fForced
+		|| (cds_chan_to_band(pSirBssDesc1->channelId) ==
+		    cds_chan_to_band((pSirBssDesc2->channelId))))) {
+		fMatch = true;
+		/* Check for SSID match, if exists */
+		status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1,
+							    &pIes1);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			goto free_ies;
+
+		if (NULL == pIesTemp) {
+			status = csr_get_parsed_bss_description_ies(pMac,
+						pSirBssDesc2, &pIesTemp);
+			if (!CDF_IS_STATUS_SUCCESS(status))
+				goto free_ies;
+		}
+		if (pIes1->SSID.present && pIesTemp->SSID.present) {
+			fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid,
+						   pIes1->SSID.num_ssid,
+						   pIesTemp->SSID.ssid,
+						   pIesTemp->SSID.num_ssid,
+						   true);
+		}
+	} else if (pCap1->ibss && (pSirBssDesc1->channelId ==
+					pSirBssDesc2->channelId)) {
+		status = csr_get_parsed_bss_description_ies(pMac, pSirBssDesc1,
+							    &pIes1);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			goto free_ies;
+
+		if (NULL == pIesTemp) {
+			status = csr_get_parsed_bss_description_ies(pMac,
+						pSirBssDesc2, &pIesTemp);
+			if (!CDF_IS_STATUS_SUCCESS(status))
+				goto free_ies;
+		}
+
+		/* Same channel cannot have same SSID for different IBSS */
+		if (pIes1->SSID.present && pIesTemp->SSID.present) {
+			fMatch = csr_is_ssid_match(pMac, pIes1->SSID.ssid,
+						   pIes1->SSID.num_ssid,
+						   pIesTemp->SSID.ssid,
+						   pIesTemp->SSID.num_ssid,
+						   true);
+		}
+	}
+	/* In case of P2P devices, ess and ibss will be set to zero */
+	else if (!pCap1->ess &&
+		cdf_is_macaddr_equal(
+			(struct cdf_mac_addr *) pSirBssDesc1->bssId,
+			(struct cdf_mac_addr *) pSirBssDesc2->bssId)) {
+		fMatch = true;
+	}
+
+free_ies:
+	if (pIes1)
+		cdf_mem_free(pIes1);
+	if ((NULL == pIes2) && pIesTemp)
+		/* locally allocated */
+		cdf_mem_free(pIesTemp);
+	return fMatch;
+}
+
+bool csr_is_network_type_equal(tSirBssDescription *pSirBssDesc1,
+			       tSirBssDescription *pSirBssDesc2)
+{
+	return pSirBssDesc1->nwType == pSirBssDesc2->nwType;
+}
+
+/* to check whether the BSS matches the dot11Mode */
+static bool csr_scan_is_bss_allowed(tpAniSirGlobal pMac,
+				    tSirBssDescription *pBssDesc,
+				    tDot11fBeaconIEs *pIes)
+{
+	bool fAllowed = false;
+	eCsrPhyMode phyMode;
+
+	if (CDF_IS_STATUS_SUCCESS
+		    (csr_get_phy_mode_from_bss(pMac, pBssDesc, &phyMode, pIes))) {
+		switch (pMac->roam.configParam.phyMode) {
+		case eCSR_DOT11_MODE_11b:
+			fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode);
+			break;
+		case eCSR_DOT11_MODE_11g:
+			fAllowed = (bool) (eCSR_DOT11_MODE_11a != phyMode);
+			break;
+		case eCSR_DOT11_MODE_11g_ONLY:
+			fAllowed = (bool) (eCSR_DOT11_MODE_11g == phyMode);
+			break;
+		case eCSR_DOT11_MODE_11a:
+			fAllowed = (bool) ((eCSR_DOT11_MODE_11b != phyMode)
+					   && (eCSR_DOT11_MODE_11g != phyMode));
+			break;
+		case eCSR_DOT11_MODE_11n_ONLY:
+			fAllowed = (bool) ((eCSR_DOT11_MODE_11n == phyMode));
+			break;
+
+#ifdef WLAN_FEATURE_11AC
+		case eCSR_DOT11_MODE_11ac_ONLY:
+			fAllowed = (bool) ((eCSR_DOT11_MODE_11ac == phyMode));
+			break;
+#endif
+		case eCSR_DOT11_MODE_11b_ONLY:
+			fAllowed = (bool) (eCSR_DOT11_MODE_11b == phyMode);
+			break;
+		case eCSR_DOT11_MODE_11n:
+#ifdef WLAN_FEATURE_11AC
+		case eCSR_DOT11_MODE_11ac:
+#endif
+		default:
+			fAllowed = true;
+			break;
+		}
+	}
+
+	return fAllowed;
+}
+
+/* Return pIes to caller for future use when returning true. */
+static bool csr_scan_validate_scan_result(tpAniSirGlobal pMac,
+					  uint8_t *pChannels,
+					  uint8_t numChn,
+					  tSirBssDescription *pBssDesc,
+					  tDot11fBeaconIEs **ppIes)
+{
+	bool valid = false;
+	tDot11fBeaconIEs *pIes = NULL;
+	uint8_t index;
+	CDF_STATUS status;
+
+	for (index = 0; index < numChn; index++) {
+		/*
+		 * This check relies on the fact that a single BSS description
+		 * is returned in each ScanRsp call, which is the way LIM
+		 * implemented the scan req/rsp funtions. We changed to this
+		 * model when we ran with a large number of APs. If this were to
+		 * change, then this check would have to mess with removing the
+		 * bssDescription from somewhere in an arbitrary index in the
+		 * bssDescription array.
+		 */
+		if (pChannels[index] == pBssDesc->channelId) {
+			valid = true;
+			break;
+		}
+	}
+	*ppIes = NULL;
+	if (valid) {
+		status = csr_get_parsed_bss_description_ies(pMac, pBssDesc,
+							    &pIes);
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			return false;
+
+		valid = csr_scan_is_bss_allowed(pMac, pBssDesc, pIes);
+		if (valid)
+			*ppIes = pIes;
+		else
+			cdf_mem_free(pIes);
+	}
+	return valid;
+}
+
+static void csr_update_scantype(tpAniSirGlobal pMac, tDot11fBeaconIEs *pIes,
+				uint8_t channelId)
+{
+	if (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)
+		return;
+
+	if (csr_is11d_supported(pMac)) {
+		/* Check whether the BSS is acceptable based on
+		 * 11d info and our config.
+		 */
+		if (!csr_match_country_code(pMac, NULL, pIes))
+			return;
+
+		/* check if channel is acceptable by config */
+		if (csr_is_supported_channel(pMac, channelId))
+			pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
+
+	} else
+		pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
+
+}
+
+/* Return whether last scan result is received */
+static bool csr_scan_process_scan_results(tpAniSirGlobal pMac, tSmeCmd *pCommand,
+					  tSirSmeScanRsp *pScanRsp,
+					  bool *pfRemoveCommand)
+{
+	bool fRet = false, fRemoveCommand = false;
+
+	sms_log(pMac, LOG1, FL("scan reason = %d, response status code = %d"),
+		pCommand->u.scanCmd.reason, pScanRsp->statusCode);
+	fRemoveCommand = csr_scan_complete(pMac, pScanRsp);
+	fRet = true;
+	if (pfRemoveCommand) {
+		*pfRemoveCommand = fRemoveCommand;
+	}
+	return fRet;
+}
+
+/* csr_scan_process_single_bssdescr() - Add a bssdescriptor to scan table
+ *
+ * @mac_ctx - MAC context
+ * @bssdescr - Pointer to BSS description structure that contains
+ *             everything from beacon/probe response frame and additional
+ *             information.
+ * @scan_id - Scan identifier of the scan request that was running
+ *            when this beacon was received. Reserved for future when
+ *            firmware provides that information.
+ * @flags - Reserved for future use.
+ *
+ * Callback routine called by LIM when it receives a beacon or probe response
+ * from the device. 802.11 frame is already converted to internal
+ * tSirBssDescription data structure.
+ *
+ * Return: 0 or other error codes.
+ */
+
+CDF_STATUS csr_scan_process_single_bssdescr(tpAniSirGlobal mac_ctx,
+					tSirBssDescription *bssdescr,
+					uint32_t scan_id, uint32_t flags)
+{
+	tDot11fBeaconIEs *ies = NULL;
+	uint8_t *chanlist = NULL;
+	uint8_t cnt_channels = 0;
+	uint32_t len = sizeof(mac_ctx->roam.validChannelList);
+
+	sms_log(mac_ctx, LOG4, "CSR: Processing single bssdescr");
+	if (CDF_IS_STATUS_SUCCESS(
+		csr_get_cfg_valid_channels(mac_ctx,
+			(uint8_t *) mac_ctx->roam.validChannelList,
+			&len))) {
+		chanlist = mac_ctx->roam.validChannelList;
+		cnt_channels = (uint8_t) len;
+	} else {
+		/* Cannot continue */
+		sms_log(mac_ctx, LOGW,
+			FL("Received results on invalid channel"));
+		return CDF_STATUS_E_INVAL;
+	}
+
+	if (csr_scan_validate_scan_result(mac_ctx, chanlist,
+			cnt_channels, bssdescr, &ies)) {
+		csr_scan_remove_dup_bss_description_from_interim_list
+			(mac_ctx, bssdescr, ies);
+		csr_scan_save_bss_description_to_interim_list
+			(mac_ctx, bssdescr, ies);
+		csr_update_scantype(mac_ctx, ies, bssdescr->channelId);
+		/* Free the resource */
+		if (ies != NULL)
+			cdf_mem_free(ies);
+	}
+	return CDF_STATUS_SUCCESS;
+}
+
+
+bool csr_scan_is_wild_card_scan(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+	uint8_t bssid[CDF_MAC_ADDR_SIZE] = {0};
+	bool f = cdf_mem_compare(pCommand->u.scanCmd.u.scanRequest.bssid.bytes,
+				 bssid, sizeof(struct cdf_mac_addr));
+	/*
+	 * It is not a wild card scan if the bssid is not broadcast and
+	 * the number of SSID is 1.
+	 */
+	return (f || (0xff == pCommand->u.scanCmd.u.scanRequest.bssid.bytes[0]))
+		&& (pCommand->u.scanCmd.u.scanRequest.SSIDs.numOfSSIDs != 1);
+}
+
+CDF_STATUS csr_scan_sme_scan_response(tpAniSirGlobal pMac,
+		void *pMsgBuf)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tListElem *pEntry = NULL;
+	tSmeCmd *pCommand;
+	eCsrScanStatus scanStatus;
+	tSirSmeScanRsp *pScanRsp = (tSirSmeScanRsp *)pMsgBuf;
+	bool fRemoveCommand = true;
+	eCsrScanReason reason = eCsrScanOther;
+
+	csr_get_active_scan_entry(pMac, pScanRsp->scan_id, &pEntry);
+	if (!pEntry)
+		goto error_handling;
+
+	sms_log(pMac, LOG1, FL("Scan completion called:scan_id %d, entry = %p"),
+		pScanRsp->scan_id, pEntry);
+
+	pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+	if (eSmeCommandScan != pCommand->command)
+		goto error_handling;
+
+	scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ?
+			eCSR_SCAN_SUCCESS : eCSR_SCAN_FAILURE;
+	reason = pCommand->u.scanCmd.reason;
+	switch (pCommand->u.scanCmd.reason) {
+	case eCsrScanAbortNormalScan:
+		break;
+	case eCsrScanP2PFindPeer:
+		scanStatus = (eSIR_SME_SUCCESS == pScanRsp->statusCode) ?
+				eCSR_SCAN_FOUND_PEER : eCSR_SCAN_FAILURE;
+		csr_scan_process_scan_results(pMac, pCommand, pScanRsp, NULL);
+		break;
+	default:
+		if (csr_scan_process_scan_results(pMac, pCommand, pScanRsp,
+						  &fRemoveCommand)
+		    && csr_scan_is_wild_card_scan(pMac, pCommand)
+		    && !pCommand->u.scanCmd.u.scanRequest.p2pSearch) {
+
+		/* Age out logic will be taken care by the age out timer */
+		}
+		break;
+	}
+	if (fRemoveCommand)
+		csr_release_scan_command(pMac, pCommand, scanStatus);
+	sme_process_pending_queue(pMac);
+	return status;
+
+error_handling:
+#ifdef FEATURE_WLAN_SCAN_PNO
+	if (pMac->pnoOffload && pScanRsp->statusCode == eSIR_PNO_SCAN_SUCCESS) {
+		sms_log(pMac, LOGE, FL("PNO Scan completion called."));
+		csr_save_scan_results(pMac, eCsrScanCandidateFound,
+				      pScanRsp->sessionId);
+		return CDF_STATUS_SUCCESS;
+	} else {
+		/*
+		 * Scan completion was called, PNO is active, but scan
+		 * response was not PNO
+		 */
+		sms_log(pMac, LOGE,
+			FL("Scan completion called, scan rsp was not PNO."));
+		return CDF_STATUS_E_FAILURE;
+	}
+#endif
+	sms_log(pMac, LOGE, FL("Scan completion called, but no active SCAN command."));
+	return CDF_STATUS_E_FAILURE;
+}
+
+tCsrScanResultInfo *csr_scan_result_get_first(tpAniSirGlobal pMac,
+					      tScanResultHandle hScanResult)
+{
+	tListElem *pEntry;
+	tCsrScanResult *pResult;
+	tCsrScanResultInfo *pRet = NULL;
+	tScanResultList *pResultList = (tScanResultList *) hScanResult;
+
+	if (pResultList) {
+		csr_ll_lock(&pResultList->List);
+		pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
+		if (pEntry) {
+			pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+			pRet = &pResult->Result;
+		}
+		pResultList->pCurEntry = pEntry;
+		csr_ll_unlock(&pResultList->List);
+	}
+
+	return pRet;
+}
+
+tCsrScanResultInfo *csr_scan_result_get_next(tpAniSirGlobal pMac,
+					     tScanResultHandle hScanResult)
+{
+	tListElem *pEntry = NULL;
+	tCsrScanResult *pResult = NULL;
+	tCsrScanResultInfo *pRet = NULL;
+	tScanResultList *pResultList = (tScanResultList *) hScanResult;
+
+	if (!pResultList)
+		return NULL;
+
+	csr_ll_lock(&pResultList->List);
+	if (NULL == pResultList->pCurEntry) {
+		pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
+	} else {
+		pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry,
+				     LL_ACCESS_NOLOCK);
+	}
+	if (pEntry) {
+		pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		pRet = &pResult->Result;
+	}
+	pResultList->pCurEntry = pEntry;
+	csr_ll_unlock(&pResultList->List);
+	return pRet;
+}
+
+/*
+ * This function moves the first BSS that matches the bssid to the
+ * head of the result
+ */
+CDF_STATUS csr_move_bss_to_head_from_bssid(tpAniSirGlobal pMac,
+					   struct cdf_mac_addr *bssid,
+					   tScanResultHandle hScanResult)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tScanResultList *pResultList = (tScanResultList *) hScanResult;
+	tCsrScanResult *pResult = NULL;
+	tListElem *pEntry = NULL;
+
+	if (!(pResultList && bssid))
+		return status;
+
+	csr_ll_lock(&pResultList->List);
+	pEntry = csr_ll_peek_head(&pResultList->List, LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		if (cdf_mem_compare(bssid, pResult->Result.BssDescriptor.bssId,
+				    sizeof(struct cdf_mac_addr))) {
+			status = CDF_STATUS_SUCCESS;
+			csr_ll_remove_entry(&pResultList->List, pEntry,
+					    LL_ACCESS_NOLOCK);
+			csr_ll_insert_head(&pResultList->List, pEntry,
+					   LL_ACCESS_NOLOCK);
+			break;
+		}
+		pEntry = csr_ll_next(&pResultList->List, pResultList->pCurEntry,
+				     LL_ACCESS_NOLOCK);
+	}
+	csr_ll_unlock(&pResultList->List);
+	return status;
+}
+
+/* Remove the BSS if possible. */
+/* Return -- true == the BSS is remove. False == Fail to remove it */
+/* This function is called when list lock is held. Be caution what functions it can call. */
+bool csr_scan_age_out_bss(tpAniSirGlobal pMac, tCsrScanResult *pResult)
+{
+	bool fRet = false;
+	uint32_t i;
+	tCsrRoamSession *pSession;
+	bool isConnBssfound = false;
+
+	for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
+		if (!CSR_IS_SESSION_VALID(pMac, i))
+			continue;
+		pSession = CSR_GET_SESSION(pMac, i);
+		/* Not to remove the BSS we are connected to. */
+		if (csr_is_conn_state_connected_infra(pMac, i)
+		    && (NULL != pSession->pConnectBssDesc)
+		    && (csr_is_duplicate_bss_description(pMac,
+			&pResult->Result.BssDescriptor,
+			pSession->pConnectBssDesc, NULL, false))) {
+			isConnBssfound = true;
+			break;
+		}
+	}
+	if (isConnBssfound) {
+		/*
+		 * Reset the counter so that aging out of connected BSS won't
+		 * hapeen too soon
+		 */
+		pResult->AgingCount =
+			(int32_t) pMac->roam.configParam.agingCount;
+		sms_log(pMac, LOGW,
+			FL("Connected BSS, Set Aging Count=%d for BSS "
+			   MAC_ADDRESS_STR), pResult->AgingCount,
+			MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId));
+		pResult->Result.BssDescriptor.nReceivedTime =
+			(uint32_t) cdf_mc_timer_get_system_ticks();
+		return fRet;
+	}
+	sms_log(pMac, LOGW,
+		"Aging out BSS " MAC_ADDRESS_STR " Channel %d",
+		MAC_ADDR_ARRAY(pResult->Result.BssDescriptor.bssId),
+		pResult->Result.BssDescriptor.channelId);
+	/*
+	 * No need to hold the spin lock because caller should hold the lock for
+	 * pMac->scan.scanResultList
+	 */
+	if (csr_ll_remove_entry(&pMac->scan.scanResultList, &pResult->Link,
+				LL_ACCESS_NOLOCK)) {
+		if (cdf_is_macaddr_equal(
+			(struct cdf_mac_addr *) &pResult->Result.BssDescriptor.bssId,
+			(struct cdf_mac_addr *) &pMac->scan.currentCountryBssid)) {
+			sms_log(pMac, LOGW,
+				FL("Aging out 11d BSS " MAC_ADDRESS_STR),
+				MAC_ADDR_ARRAY(
+					pResult->Result.BssDescriptor.bssId));
+			pMac->scan.currentCountryRSSI = -128;
+		}
+		csr_free_scan_result_entry(pMac, pResult);
+		fRet = true;
+	}
+	return fRet;
+}
+
+CDF_STATUS csr_scan_age_results(tpAniSirGlobal pMac,
+				tSmeGetScanChnRsp *pScanChnInfo)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tListElem *pEntry, *tmpEntry;
+	tCsrScanResult *pResult;
+	tLimScanChn *pChnInfo;
+	uint8_t i;
+
+	csr_ll_lock(&pMac->scan.scanResultList);
+	for (i = 0; i < pScanChnInfo->numChn; i++) {
+		pChnInfo = &pScanChnInfo->scanChn[i];
+		pEntry =
+			csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
+		while (pEntry) {
+			tmpEntry =
+				csr_ll_next(&pMac->scan.scanResultList, pEntry,
+					    LL_ACCESS_NOLOCK);
+			pResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+			if (pResult->Result.BssDescriptor.channelId ==
+			    pChnInfo->channelId) {
+				if (pResult->AgingCount <= 0) {
+					sms_log(pMac, LOGW,
+						" age out due to ref count");
+					csr_scan_age_out_bss(pMac, pResult);
+				} else {
+					pResult->AgingCount--;
+					sms_log(pMac, LOGW,
+						FL
+							("Decremented AgingCount=%d for BSS "
+							MAC_ADDRESS_STR ""),
+						pResult->AgingCount,
+						MAC_ADDR_ARRAY(pResult->Result.
+							       BssDescriptor.
+							       bssId));
+				}
+			}
+			pEntry = tmpEntry;
+		}
+	}
+	csr_ll_unlock(&pMac->scan.scanResultList);
+
+	return status;
+}
+
+CDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId,
+				tCsrScanRequest *pScanReq,
+				tScanReqParam *pScanReqParam)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tSirSmeScanReq *pMsg;
+	uint16_t msgLen;
+	tSirScanType scanType = pScanReq->scanType;
+	uint32_t minChnTime;    /* in units of milliseconds */
+	uint32_t maxChnTime;    /* in units of milliseconds */
+	uint32_t i;
+	uint8_t selfMacAddr[CDF_MAC_ADDR_SIZE];
+	uint8_t *pSelfMac = NULL;
+
+	msgLen = (uint16_t) (sizeof(tSirSmeScanReq) -
+		 sizeof(pMsg->channelList.channelNumber) +
+		 (sizeof(pMsg->channelList.channelNumber) *
+		 pScanReq->ChannelInfo.numOfChannels)) +
+		 (pScanReq->uIEFieldLen);
+
+	pMsg = cdf_mem_malloc(msgLen);
+	if (NULL == pMsg) {
+		sms_log(pMac, LOGE, FL("memory allocation failed"));
+		sms_log(pMac, LOG1, FL("Failed: SId: %d FirstMatch = %d"
+				       " UniqueResult = %d freshScan = %d hiddenSsid = %d"),
+			sessionId, pScanReqParam->bReturnAfter1stMatch,
+			pScanReqParam->fUniqueResult, pScanReqParam->freshScan,
+			pScanReqParam->hiddenSsid);
+		sms_log(pMac, LOG1,
+			FL("scanType = %u BSSType = %u numOfSSIDs = %d"
+			   " numOfChannels = %d requestType = %d p2pSearch = %d\n"),
+			pScanReq->scanType, pScanReq->BSSType,
+			pScanReq->SSIDs.numOfSSIDs,
+			pScanReq->ChannelInfo.numOfChannels,
+			pScanReq->requestType, pScanReq->p2pSearch);
+		return CDF_STATUS_E_NOMEM;
+	}
+
+	cdf_mem_set(pMsg, msgLen, 0);
+	pMsg->messageType = eWNI_SME_SCAN_REQ;
+	pMsg->length = msgLen;
+	/* ToDO: Fill in session info when we need to do scan base on session */
+	if ((sessionId != CSR_SESSION_ID_INVALID)) {
+		pMsg->sessionId = sessionId;
+	} else {
+		/* if sessionId == CSR_SESSION_ID_INVALID, then send the scan
+		   request on first available session */
+		pMsg->sessionId = 0;
+	}
+	if (pMsg->sessionId >= CSR_ROAM_SESSION_MAX)
+		sms_log(pMac, LOGE, FL(" Invalid Sme Session ID = %d"),
+			pMsg->sessionId);
+	pMsg->transactionId = 0;
+	pMsg->dot11mode = (uint8_t) csr_translate_to_wni_cfg_dot11_mode(pMac,
+				csr_find_best_phy_mode(pMac,
+					pMac->roam.configParam.phyMode));
+	pMsg->bssType = csr_translate_bsstype_to_mac_type(pScanReq->BSSType);
+
+	if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
+		pSelfMac = (uint8_t *)
+			&pMac->roam.roamSession[sessionId].selfMacAddr;
+	} else {
+		/*
+		 * Since we don't have session for the scanning, we find a valid
+		 * session. In case we fail to do so, get the WNI_CFG_STA_ID
+		 */
+		for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
+			if (CSR_IS_SESSION_VALID(pMac, i)) {
+				pSelfMac = (uint8_t *)
+					&pMac->roam.roamSession[i].selfMacAddr;
+				break;
+			}
+		}
+		if (CSR_ROAM_SESSION_MAX == i) {
+			uint32_t len = CDF_MAC_ADDR_SIZE;
+			pSelfMac = selfMacAddr;
+			status = wlan_cfg_get_str(pMac, WNI_CFG_STA_ID,
+						  pSelfMac, &len);
+			if (!CDF_IS_STATUS_SUCCESS(status)
+			    || (len < CDF_MAC_ADDR_SIZE)) {
+				sms_log(pMac, LOGE,
+					FL("Can't get self MAC address = %d"),
+					status);
+				/* Force failed status */
+				status = CDF_STATUS_E_FAILURE;
+				goto send_scan_req;
+			}
+		}
+	}
+	cdf_mem_copy((uint8_t *) pMsg->selfMacAddr,
+		     pSelfMac, sizeof(tSirMacAddr));
+
+	/* sir_copy_mac_addr */
+	cdf_mem_copy(pMsg->bssId, &pScanReq->bssid, sizeof(tSirMacAddr));
+	if (cdf_is_macaddr_zero(&pScanReq->bssid))
+		cdf_mem_set(pMsg->bssId, sizeof(tSirMacAddr), 0xff);
+	else
+		cdf_mem_copy(pMsg->bssId, pScanReq->bssid.bytes,
+				CDF_MAC_ADDR_SIZE);
+	minChnTime = pScanReq->minChnTime;
+	maxChnTime = pScanReq->maxChnTime;
+
+	/*
+	 * Verify the scan type first, if the scan is active scan, we need to
+	 * make sure we are allowed to do so. if 11d is enabled & we don't see
+	 * any beacon around, scan type falls back to passive. But in BT AMP STA
+	 * mode we need to send out a directed probe
+	 */
+	if ((eSIR_PASSIVE_SCAN != scanType)
+	    && (eCSR_SCAN_P2P_DISCOVERY !=
+		pScanReq->requestType)
+	    && (eCSR_BSS_TYPE_WDS_STA != pScanReq->BSSType)
+	    && (false == pMac->scan.fEnableBypass11d)) {
+		scanType = pMac->scan.curScanType;
+		if (eSIR_PASSIVE_SCAN == pMac->scan.curScanType) {
+			if (minChnTime <
+			    pMac->roam.configParam.nPassiveMinChnTime) {
+				minChnTime =
+				    pMac->roam.configParam.nPassiveMinChnTime;
+			}
+			if (maxChnTime <
+			    pMac->roam.configParam.nPassiveMaxChnTime) {
+				maxChnTime =
+				    pMac->roam.configParam.nPassiveMaxChnTime;
+			}
+		}
+	}
+	pMsg->scanType = scanType;
+
+	pMsg->numSsid = (pScanReq->SSIDs.numOfSSIDs < SIR_SCAN_MAX_NUM_SSID) ?
+			 pScanReq->SSIDs.numOfSSIDs : SIR_SCAN_MAX_NUM_SSID;
+	if ((pScanReq->SSIDs.numOfSSIDs != 0)
+	    && (eSIR_PASSIVE_SCAN != scanType)) {
+		for (i = 0; i < pMsg->numSsid; i++) {
+			cdf_mem_copy(&pMsg->ssId[i],
+				     &pScanReq->SSIDs.SSIDList[i].SSID,
+				     sizeof(tSirMacSSid));
+		}
+	} else {
+		/* Otherwise we scan all SSID and let the result filter later */
+		for (i = 0; i < SIR_SCAN_MAX_NUM_SSID; i++)
+			pMsg->ssId[i].length = 0;
+	}
+
+	pMsg->minChannelTime = minChnTime;
+	pMsg->maxChannelTime = maxChnTime;
+	/* hidden SSID option */
+	pMsg->hiddenSsid = pScanReqParam->hiddenSsid;
+	/* rest time */
+	pMsg->restTime = pScanReq->restTime;
+	pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch;
+	/* All the scan results caching will be done by Roaming */
+	/* We do not want LIM to do any caching of scan results, */
+	/* so delete the LIM cache on all scan requests */
+	pMsg->returnFreshResults = pScanReqParam->freshScan;
+	/* Always ask for unique result */
+	pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
+	pMsg->channelList.numChannels =
+		(uint8_t) pScanReq->ChannelInfo.numOfChannels;
+	if (pScanReq->ChannelInfo.numOfChannels) {
+		/* Assuming the channelNumber is uint8_t (1 byte) */
+		cdf_mem_copy(pMsg->channelList.channelNumber,
+			     pScanReq->ChannelInfo.ChannelList,
+			     pScanReq->ChannelInfo.numOfChannels);
+	}
+
+	pMsg->uIEFieldLen = (uint16_t) pScanReq->uIEFieldLen;
+	pMsg->uIEFieldOffset = (uint16_t) (sizeof(tSirSmeScanReq) -
+			sizeof(pMsg->channelList.channelNumber) +
+			(sizeof(pMsg->channelList.channelNumber) *
+			 pScanReq->ChannelInfo.numOfChannels));
+	if (pScanReq->uIEFieldLen != 0) {
+		cdf_mem_copy((uint8_t *) pMsg + pMsg->uIEFieldOffset,
+			     pScanReq->pIEField, pScanReq->uIEFieldLen);
+	}
+	pMsg->p2pSearch = pScanReq->p2pSearch;
+	pMsg->scan_id = pScanReq->scan_id;
+
+send_scan_req:
+	sms_log(pMac, LOG1,
+		FL("scanId %d domainIdCurrent %d scanType %d bssType %d requestType %d numChannels %d"),
+		pMsg->scan_id, pMac->scan.domainIdCurrent, pMsg->scanType,
+		pMsg->bssType, pScanReq->requestType,
+		pMsg->channelList.numChannels);
+
+	for (i = 0; i < pMsg->channelList.numChannels; i++) {
+		sms_log(pMac, LOG1, FL("channelNumber[%d]= %d"), i,
+			pMsg->channelList.channelNumber[i]);
+	}
+
+	if (CDF_IS_STATUS_SUCCESS(status)) {
+		status = cds_send_mb_message_to_mac(pMsg);
+	} else {
+		sms_log(pMac, LOGE,
+			FL("failed to send down scan req with status = %d"),
+			status);
+		cdf_mem_free(pMsg);
+	}
+	return status;
+}
+
+CDF_STATUS csr_send_mb_scan_result_req(tpAniSirGlobal pMac,
+				       uint32_t sessionId,
+				       tScanReqParam *pScanReqParam)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tSirSmeScanReq *pMsg;
+	uint16_t msgLen;
+
+	msgLen = (uint16_t) (sizeof(tSirSmeScanReq));
+	pMsg = cdf_mem_malloc(msgLen);
+	if (NULL == pMsg)
+		return CDF_STATUS_E_NOMEM;
+
+	cdf_mem_set(pMsg, msgLen, 0);
+	pMsg->messageType = eWNI_SME_SCAN_REQ;
+	pMsg->length = msgLen;
+	pMsg->sessionId = sessionId;
+	pMsg->transactionId = 0;
+	pMsg->returnFreshResults = pScanReqParam->freshScan;
+	/* Always ask for unique result */
+	pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
+	pMsg->returnAfterFirstMatch =
+		pScanReqParam->bReturnAfter1stMatch;
+	status = cds_send_mb_message_to_mac(pMsg);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(pMac, LOGE,
+			FL("Failed to send down scan req with status = %d\n"),
+			status);
+	}
+	return status;
+}
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
+static void csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+	host_log_scan_pkt_type *pScanLog = NULL;
+
+	WLAN_HOST_DIAG_LOG_ALLOC(pScanLog,
+				 host_log_scan_pkt_type,
+				 LOG_WLAN_SCAN_C);
+	if (!pScanLog)
+		return;
+
+	if (eCsrScanProbeBss == pCommand->u.scanCmd.reason) {
+		pScanLog->eventId = WLAN_SCAN_EVENT_HO_SCAN_REQ;
+	} else {
+		if ((eSIR_PASSIVE_SCAN !=
+			pCommand->u.scanCmd.u.scanRequest.scanType)
+		    && (eSIR_PASSIVE_SCAN != pMac->scan.curScanType)) {
+			pScanLog->eventId = WLAN_SCAN_EVENT_ACTIVE_SCAN_REQ;
+		} else {
+			pScanLog->eventId = WLAN_SCAN_EVENT_PASSIVE_SCAN_REQ;
+		}
+	}
+	pScanLog->minChnTime =
+		(uint8_t) pCommand->u.scanCmd.u.scanRequest.minChnTime;
+	pScanLog->maxChnTime =
+		(uint8_t) pCommand->u.scanCmd.u.scanRequest.maxChnTime;
+	pScanLog->numChannel =
+	(uint8_t) pCommand->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+	if (pScanLog->numChannel &&
+	    (pScanLog->numChannel < HOST_LOG_MAX_NUM_CHANNEL)) {
+		cdf_mem_copy(pScanLog->channels,
+		      pCommand->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList,
+		      pScanLog->numChannel);
+	}
+	WLAN_HOST_DIAG_LOG_REPORT(pScanLog);
+}
+#else
+#define csr_diag_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand) (void)0;
+#endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */
+
+CDF_STATUS csr_scan_channels(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+	tScanReqParam scanReq;
+
+	/*
+	 * Don't delete cached results. Rome rssi based scan candidates may land
+	 * up in scan cache instead of LFR cache. They will be deleted upon
+	 * query
+	 */
+	scanReq.freshScan = SIR_BG_SCAN_RETURN_FRESH_RESULTS;
+	scanReq.fUniqueResult = true;
+	scanReq.hiddenSsid = SIR_SCAN_NO_HIDDEN_SSID;
+	if (eCsrScanForSsid == pCommand->u.scanCmd.reason) {
+		scanReq.bReturnAfter1stMatch =
+			CSR_SCAN_RETURN_AFTER_FIRST_MATCH;
+	} else {
+		/*
+		 * Basically do scan on all channels even for 11D 1st scan case
+		 */
+		scanReq.bReturnAfter1stMatch =
+			CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
+	}
+	if (eCsrScanProbeBss == pCommand->u.scanCmd.reason)
+		scanReq.hiddenSsid = SIR_SCAN_HIDDEN_SSID_PE_DECISION;
+	csr_diag_scan_channels(pMac, pCommand);
+	csr_clear_votes_for_country_info(pMac);
+	status = csr_send_mb_scan_req(pMac, pCommand->sessionId,
+				      &pCommand->u.scanCmd.u.scanRequest,
+				      &scanReq);
+	return status;
+}
+
+static CDF_STATUS
+csr_issue_user_scan(tpAniSirGlobal mac_ctx, tSmeCmd *cmd)
+{
+	int i, j;
+	CDF_STATUS status;
+	uint32_t len = 0;
+	uint8_t *ch_lst = NULL;
+	tCsrChannelInfo new_ch_info = { 0, NULL };
+
+	if (!mac_ctx->roam.configParam.fScanTwice)
+		return csr_scan_channels(mac_ctx, cmd);
+
+	/* We scan 2.4 channel twice */
+	if (cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels
+	    && (NULL != cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList)) {
+		len = cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+		/* allocate twice the channel */
+		new_ch_info.ChannelList = (uint8_t *) cdf_mem_malloc(len * 2);
+		ch_lst = cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList;
+	} else {
+		/* get the valid channel list to scan all. */
+		len = sizeof(mac_ctx->roam.validChannelList);
+		status = csr_get_cfg_valid_channels(mac_ctx,
+			    (uint8_t *) mac_ctx->roam.validChannelList, &len);
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			/* allocate twice the channel */
+			new_ch_info.ChannelList =
+				(uint8_t *) cdf_mem_malloc(len * 2);
+			ch_lst = mac_ctx->roam.validChannelList;
+		}
+	}
+	if (NULL == new_ch_info.ChannelList) {
+		new_ch_info.numOfChannels = 0;
+	} else {
+		j = 0;
+		for (i = 0; i < len; i++) {
+			new_ch_info.ChannelList[j++] = ch_lst[i];
+			if (CDS_MAX_24GHz_CHANNEL_NUMBER >= ch_lst[i])
+				new_ch_info.ChannelList[j++] = ch_lst[i];
+		}
+		if (NULL !=
+		    cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList) {
+			/*
+			 * ch_lst points to the channellist from the command,
+			 * free it.
+			 */
+			cdf_mem_free(
+			  cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList);
+			cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList =
+			  NULL;
+		}
+		cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = j;
+		cmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList =
+							new_ch_info.ChannelList;
+	}
+
+	return csr_scan_channels(mac_ctx, cmd);
+}
+
+CDF_STATUS csr_process_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	sms_log(pMac, LOG3,
+			FL("starting SCAN cmd in %d state. reason %d"),
+			pCommand->u.scanCmd.lastRoamState[pCommand->sessionId],
+			pCommand->u.scanCmd.reason);
+
+	switch (pCommand->u.scanCmd.reason) {
+	case eCsrScanUserRequest:
+		status = csr_issue_user_scan(pMac, pCommand);
+		break;
+	default:
+		status = csr_scan_channels(pMac, pCommand);
+		break;
+	}
+
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		csr_release_scan_command(pMac, pCommand, eCSR_SCAN_FAILURE);
+	}
+
+	return status;
+}
+
+/**
+ * csr_scan_copy_request_valid_channels_only() - scan request of valid channels
+ * @mac_ctx : pointer to Global Mac Structure
+ * @dst_req: pointer to tCsrScanRequest
+ * @skip_dfs_chnl: 1 - skip dfs channel, 0 - don't skip dfs channel
+ * @src_req: pointer to tCsrScanRequest
+ *
+ * This function makes a copy of scan request with valid channels
+ *
+ * Return: none
+ */
+static void csr_scan_copy_request_valid_channels_only(tpAniSirGlobal mac_ctx,
+				tCsrScanRequest *dst_req, uint8_t skip_dfs_chnl,
+				tCsrScanRequest *src_req)
+{
+	uint32_t index = 0;
+	uint32_t new_index = 0;
+
+	for (index = 0; index < src_req->ChannelInfo.numOfChannels; index++) {
+		/* Allow scan on valid channels only.
+		 * If it is p2p scan and valid channel list doesnt contain
+		 * social channels, enforce scan on social channels because
+		 * that is the only way to find p2p peers.
+		 * This can happen only if band is set to 5Ghz mode.
+		 */
+		if (src_req->ChannelInfo.ChannelList[index] < MIN_11P_CHANNEL &&
+			((csr_roam_is_valid_channel(mac_ctx,
+			src_req->ChannelInfo.ChannelList[index])) ||
+			((eCSR_SCAN_P2P_DISCOVERY == src_req->requestType) &&
+			CSR_IS_SOCIAL_CHANNEL(
+				src_req->ChannelInfo.ChannelList[index])))) {
+			if (((src_req->skipDfsChnlInP2pSearch || skip_dfs_chnl)
+				&& (CHANNEL_STATE_DFS ==
+				cds_get_channel_state(src_req->
+							ChannelInfo.
+							ChannelList
+							[index])))
+			) {
+#ifdef FEATURE_WLAN_LFR
+				sms_log(mac_ctx, LOG2,
+					FL(" reqType=%d, numOfChannels=%d, ignoring DFS channel %d"),
+					src_req->requestType,
+					src_req->ChannelInfo.numOfChannels,
+					src_req->ChannelInfo.ChannelList
+						[index]);
+#endif
+				continue;
+			}
+
+			dst_req->ChannelInfo.ChannelList[new_index] =
+				src_req->ChannelInfo.ChannelList[index];
+			new_index++;
+		}
+	}
+	dst_req->ChannelInfo.numOfChannels = new_index;
+}
+
+/**
+ * csr_scan_copy_request() - Function to copy scan request
+ * @mac_ctx : pointer to Global Mac Structure
+ * @dst_req: pointer to tCsrScanRequest
+ * @src_req: pointer to tCsrScanRequest
+ *
+ * This function makes a copy of scan request
+ *
+ * Return: 0 - Success, Error number - Failure
+ */
+CDF_STATUS csr_scan_copy_request(tpAniSirGlobal mac_ctx,
+				tCsrScanRequest *dst_req,
+				tCsrScanRequest *src_req)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	uint32_t len = sizeof(mac_ctx->roam.validChannelList);
+	uint32_t index = 0;
+	uint32_t new_index = 0;
+	CHANNEL_STATE channel_state;
+	bool skip_dfs_chnl =
+			mac_ctx->roam.configParam.initial_scan_no_dfs_chnl ||
+				!mac_ctx->scan.fEnableDFSChnlScan;
+
+	status = csr_scan_free_request(mac_ctx, dst_req);
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto complete;
+	cdf_mem_copy(dst_req, src_req, sizeof(tCsrScanRequest));
+	/* Re-initialize the pointers to NULL since we did a copy */
+	dst_req->pIEField = NULL;
+	dst_req->ChannelInfo.ChannelList = NULL;
+	dst_req->SSIDs.SSIDList = NULL;
+
+	if (src_req->uIEFieldLen) {
+		dst_req->pIEField =
+			cdf_mem_malloc(src_req->uIEFieldLen);
+		if (NULL == dst_req->pIEField) {
+			status = CDF_STATUS_E_NOMEM;
+			sms_log(mac_ctx, LOGE,
+					FL("No memory for scanning IE fields"));
+			goto complete;
+		} else {
+			status = CDF_STATUS_SUCCESS;
+			cdf_mem_copy(dst_req->pIEField, src_req->pIEField,
+				src_req->uIEFieldLen);
+			dst_req->uIEFieldLen = src_req->uIEFieldLen;
+		}
+	}
+
+	/* Allocate memory for IE field */
+	if (src_req->ChannelInfo.numOfChannels == 0) {
+		dst_req->ChannelInfo.ChannelList = NULL;
+		dst_req->ChannelInfo.numOfChannels = 0;
+	} else {
+		dst_req->ChannelInfo.ChannelList =
+			cdf_mem_malloc(src_req->ChannelInfo.numOfChannels *
+				sizeof(*dst_req->ChannelInfo.ChannelList));
+		if (NULL == dst_req->ChannelInfo.ChannelList) {
+			status = CDF_STATUS_E_NOMEM;
+			dst_req->ChannelInfo.numOfChannels = 0;
+			sms_log(mac_ctx, LOGE,
+				FL("No memory for scanning Channel List"));
+			goto complete;
+		}
+
+		if ((src_req->scanType == eSIR_PASSIVE_SCAN) &&
+			(src_req->requestType == eCSR_SCAN_REQUEST_11D_SCAN)) {
+			for (index = 0; index < src_req->ChannelInfo.
+						numOfChannels; index++) {
+				channel_state =
+					cds_get_channel_state(src_req->
+							ChannelInfo.
+							ChannelList[index]);
+				if (src_req->ChannelInfo.ChannelList[index] <
+						MIN_11P_CHANNEL &&
+					((CHANNEL_STATE_ENABLE ==
+						channel_state) ||
+					((CHANNEL_STATE_DFS == channel_state) &&
+					!skip_dfs_chnl))) {
+					dst_req->ChannelInfo.ChannelList
+							[new_index] =
+								src_req->
+								ChannelInfo.
+								ChannelList
+								[index];
+					new_index++;
+				}
+			}
+			dst_req->ChannelInfo.numOfChannels = new_index;
+		} else if (CDF_IS_STATUS_SUCCESS(
+				csr_get_cfg_valid_channels(mac_ctx,
+						mac_ctx->roam.validChannelList,
+						&len))) {
+			new_index = 0;
+			mac_ctx->roam.numValidChannels = len;
+			csr_scan_copy_request_valid_channels_only(mac_ctx,
+							dst_req, skip_dfs_chnl,
+							src_req);
+		} else {
+			sms_log(mac_ctx, LOGE,
+				FL("Couldn't get the valid Channel List, keeping requester's list"));
+			new_index = 0;
+			for (index = 0; index < src_req->ChannelInfo.
+					numOfChannels; index++) {
+				if (src_req->ChannelInfo.ChannelList[index] <
+						MIN_11P_CHANNEL) {
+					dst_req->ChannelInfo.
+						ChannelList[new_index] =
+						src_req->ChannelInfo.
+						ChannelList[index];
+					new_index++;
+				}
+			}
+			dst_req->ChannelInfo.numOfChannels =
+				new_index;
+		}
+	} /* Allocate memory for Channel List */
+	if (src_req->SSIDs.numOfSSIDs == 0) {
+		dst_req->SSIDs.numOfSSIDs = 0;
+		dst_req->SSIDs.SSIDList = NULL;
+	} else {
+		dst_req->SSIDs.SSIDList =
+			cdf_mem_malloc(src_req->SSIDs.numOfSSIDs *
+					sizeof(*dst_req->SSIDs.SSIDList));
+		if (NULL == dst_req->SSIDs.SSIDList)
+			status = CDF_STATUS_E_NOMEM;
+		else
+			status = CDF_STATUS_SUCCESS;
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			dst_req->SSIDs.numOfSSIDs =
+				src_req->SSIDs.numOfSSIDs;
+			cdf_mem_copy(dst_req->SSIDs.SSIDList,
+				src_req->SSIDs.SSIDList,
+				src_req->SSIDs.numOfSSIDs *
+				sizeof(*dst_req->SSIDs.SSIDList));
+		} else {
+			dst_req->SSIDs.numOfSSIDs = 0;
+			sms_log(mac_ctx, LOGE,
+					FL("No memory for scanning SSID List"));
+			goto complete;
+		}
+	} /* Allocate memory for SSID List */
+	dst_req->p2pSearch = src_req->p2pSearch;
+	dst_req->skipDfsChnlInP2pSearch =
+		src_req->skipDfsChnlInP2pSearch;
+	dst_req->scan_id = src_req->scan_id;
+	dst_req->timestamp = src_req->timestamp;
+
+complete:
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		csr_scan_free_request(mac_ctx, dst_req);
+	}
+
+	return status;
+}
+
+CDF_STATUS csr_scan_free_request(tpAniSirGlobal pMac, tCsrScanRequest *pReq)
+{
+
+	if (pReq->ChannelInfo.ChannelList) {
+		cdf_mem_free(pReq->ChannelInfo.ChannelList);
+		pReq->ChannelInfo.ChannelList = NULL;
+	}
+	pReq->ChannelInfo.numOfChannels = 0;
+	if (pReq->pIEField) {
+		cdf_mem_free(pReq->pIEField);
+		pReq->pIEField = NULL;
+	}
+	pReq->uIEFieldLen = 0;
+	if (pReq->SSIDs.SSIDList) {
+		cdf_mem_free(pReq->SSIDs.SSIDList);
+		pReq->SSIDs.SSIDList = NULL;
+	}
+	pReq->SSIDs.numOfSSIDs = 0;
+
+	return CDF_STATUS_SUCCESS;
+}
+
+void csr_scan_call_callback(tpAniSirGlobal pMac, tSmeCmd *pCommand,
+			    eCsrScanStatus scanStatus)
+{
+	if (pCommand->u.scanCmd.callback) {
+		pCommand->u.scanCmd.callback(pMac, pCommand->u.scanCmd.pContext,
+					     pCommand->sessionId,
+					     pCommand->u.scanCmd.scanID,
+					     scanStatus);
+	} else {
+		sms_log(pMac, LOG2, "%s:%d - Callback NULL!!!", __func__,
+			__LINE__);
+	}
+}
+
+void csr_scan_stop_timers(tpAniSirGlobal pMac)
+{
+	if (0 != pMac->scan.scanResultCfgAgingTime) {
+		csr_scan_stop_result_cfg_aging_timer(pMac);
+	}
+
+}
+
+#ifdef WLAN_AP_STA_CONCURRENCY
+/**
+ * csr_sta_ap_conc_timer_handler - Function to handle STA,AP concurrency timer
+ * @pv: pointer variable
+ *
+ * Function handles STA,AP concurrency timer
+ *
+ * Return: none
+ */
+static void csr_sta_ap_conc_timer_handler(void *pv)
+{
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv);
+	tListElem *entry;
+	tSmeCmd *scan_cmd;
+	uint32_t session_id = CSR_SESSION_ID_INVALID;
+	tCsrScanRequest scan_req;
+	tSmeCmd *send_scancmd = NULL;
+	uint8_t num_chn = 0;
+	uint8_t numchan_combinedconc = 0;
+	uint8_t i, j;
+	tCsrChannelInfo *chn_info = NULL;
+	uint8_t channel_to_scan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+	CDF_STATUS status;
+
+	csr_ll_lock(&mac_ctx->scan.scanCmdPendingList);
+
+	entry = csr_ll_peek_head(&mac_ctx->scan.scanCmdPendingList,
+			LL_ACCESS_NOLOCK);
+
+	if (NULL == entry) {
+		csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
+		return;
+	}
+
+
+	chn_info = &scan_req.ChannelInfo;
+	scan_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
+	num_chn =
+		scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels;
+	session_id = scan_cmd->sessionId;
+
+	/*
+	 * if any session is connected and the number of channels to scan is
+	 * greater than 1 then split the scan into multiple scan operations
+	 * on each individual channel else continue to perform scan on all
+	 * specified channels */
+
+	/*
+	 * split scan if number of channels to scan is greater than 1 and
+	 * any one of the following:
+	 * - STA session is connected and the scan is not a P2P search
+	 * - any P2P session is connected
+	 * Do not split scans if no concurrent infra connections are
+	 * active and if the scan is a BG scan triggered by LFR (OR)
+	 * any scan if LFR is in the middle of a BG scan. Splitting
+	 * the scan is delaying the time it takes for LFR to find
+	 * candidates and resulting in disconnects.
+	 */
+
+	if ((csr_is_sta_session_connected(mac_ctx) &&
+		!csr_is_p2p_session_connected(mac_ctx)))
+		numchan_combinedconc =
+			mac_ctx->roam.configParam.nNumStaChanCombinedConc;
+	else if (csr_is_p2p_session_connected(mac_ctx))
+		numchan_combinedconc =
+			mac_ctx->roam.configParam.nNumP2PChanCombinedConc;
+
+	if ((num_chn > numchan_combinedconc) &&
+		((csr_is_sta_session_connected(mac_ctx) &&
+#ifdef FEATURE_WLAN_LFR
+		(csr_is_concurrent_infra_connected(mac_ctx)) &&
+#endif
+		(scan_cmd->u.scanCmd.u.scanRequest.p2pSearch != 1)) ||
+		(csr_is_p2p_session_connected(mac_ctx)))) {
+			cdf_mem_set(&scan_req, sizeof(tCsrScanRequest), 0);
+
+		/* optimize this to use 2 command buffer only */
+		send_scancmd = csr_get_command_buffer(mac_ctx);
+		if (!send_scancmd) {
+			sms_log(mac_ctx, LOGE,
+				FL(" Failed to get Queue command buffer"));
+			csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
+			return;
+		}
+		send_scancmd->command = scan_cmd->command;
+		send_scancmd->sessionId = scan_cmd->sessionId;
+		send_scancmd->u.scanCmd.callback = NULL;
+		send_scancmd->u.scanCmd.pContext =
+		scan_cmd->u.scanCmd.pContext;
+		send_scancmd->u.scanCmd.reason =
+				scan_cmd->u.scanCmd.reason;
+		/* let it wrap around */
+		wma_get_scan_id(&send_scancmd->u.scanCmd.scanID);
+
+		/*
+		 * First copy all the parameters to local variable of scan
+		 * request
+		 */
+		csr_scan_copy_request(mac_ctx, &scan_req,
+					&scan_cmd->u.scanCmd.u.scanRequest);
+
+		/*
+		 * Now modify the elements of local var scan request required
+		 * to be modified for split scan
+		 */
+		if (scan_req.ChannelInfo.ChannelList != NULL) {
+				cdf_mem_free(scan_req.ChannelInfo.ChannelList);
+			scan_req.ChannelInfo.ChannelList = NULL;
+		}
+
+		chn_info->numOfChannels = numchan_combinedconc;
+		cdf_mem_copy(&channel_to_scan[0],
+				&scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.
+				ChannelList[0], chn_info->numOfChannels
+				* sizeof(uint8_t));
+		chn_info->ChannelList = &channel_to_scan[0];
+
+		for (i = 0, j = numchan_combinedconc;
+				i < (num_chn - numchan_combinedconc);
+						i++, j++) {
+			/* Move all the channels one step */
+			scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.
+					ChannelList[i] =
+					scan_cmd->u.scanCmd.u.scanRequest.
+					ChannelInfo.ChannelList[j];
+		}
+
+		/* reduce outstanding # of channels to be scanned */
+		scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels =
+				num_chn - numchan_combinedconc;
+
+		scan_req.BSSType = eCSR_BSS_TYPE_ANY;
+		/* Modify callers parameters in case of concurrency */
+		scan_req.scanType = eSIR_ACTIVE_SCAN;
+		/* Use concurrency values for min/maxChnTime. */
+		csr_set_default_scan_timing(mac_ctx, scan_req.scanType,
+						&scan_req);
+
+		status = csr_scan_copy_request(mac_ctx,
+						&send_scancmd->u.scanCmd.u.
+						scanRequest, &scan_req);
+		if (!CDF_IS_STATUS_SUCCESS(status)) {
+			sms_log(mac_ctx, LOGE,
+				FL(" Failed to get copy csr_scan_request = %d"),
+				status);
+			csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
+			return;
+		}
+		/* Clean the local scan variable */
+		scan_req.ChannelInfo.ChannelList = NULL;
+		scan_req.ChannelInfo.numOfChannels = 0;
+		csr_scan_free_request(mac_ctx, &scan_req);
+	} else {
+		/*
+		 * no active connected session present or numChn == 1
+		 * scan all remaining channels
+		 */
+		send_scancmd = scan_cmd;
+		/* remove this command from pending list */
+		if (csr_ll_remove_head(&mac_ctx->scan.scanCmdPendingList,
+			/*
+			 * In case between PeekHead and here, the entry
+			 * got removed by another thread.
+			 */
+					LL_ACCESS_NOLOCK) == NULL) {
+			sms_log(mac_ctx, LOGE,
+				FL(" Failed to remove entry from scanCmdPendingList"));
+		}
+
+	}
+	csr_queue_sme_command(mac_ctx, send_scancmd, false);
+
+
+	csr_ll_unlock(&mac_ctx->scan.scanCmdPendingList);
+
+}
+#endif
+
+CDF_STATUS csr_scan_start_result_cfg_aging_timer(tpAniSirGlobal pMac)
+{
+	CDF_STATUS status = CDF_STATUS_E_FAILURE;
+
+	if (pMac->scan.fScanEnable) {
+		status =
+			cdf_mc_timer_start(&pMac->scan.hTimerResultCfgAging,
+					   CSR_SCAN_RESULT_CFG_AGING_INTERVAL /
+					   CDF_MC_TIMER_TO_MS_UNIT);
+	}
+	return status;
+}
+
+CDF_STATUS csr_scan_stop_result_cfg_aging_timer(tpAniSirGlobal pMac)
+{
+	return cdf_mc_timer_stop(&pMac->scan.hTimerResultCfgAging);
+}
+
+/**
+ * csr_scan_result_cfg_aging_timer_handler() - Time based scan aging handler
+ * @pv: Global context
+ *
+ * This routine is to handle scan aging based on user configured timer value.
+ *
+ * Return: None
+ */
+static void csr_scan_result_cfg_aging_timer_handler(void *pv)
+{
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(pv);
+	tListElem *entry, *tmp_entry;
+	tCsrScanResult *result;
+	uint32_t ageout_time =
+		mac_ctx->scan.scanResultCfgAgingTime * CDF_TICKS_PER_SECOND/10;
+	uint32_t cur_time = (uint32_t) cdf_mc_timer_get_system_ticks();
+	uint8_t *bssId;
+
+	csr_ll_lock(&mac_ctx->scan.scanResultList);
+	entry = csr_ll_peek_head(&mac_ctx->scan.scanResultList, LL_ACCESS_NOLOCK);
+	while (entry) {
+		tmp_entry = csr_ll_next(&mac_ctx->scan.scanResultList, entry,
+					LL_ACCESS_NOLOCK);
+		result = GET_BASE_ADDR(entry, tCsrScanResult, Link);
+		/*
+		 * cdf_mc_timer_get_system_ticks() returns in 10ms interval.
+		 * so ageout time value also updated to 10ms interval value.
+		 */
+		if ((cur_time - result->Result.BssDescriptor.nReceivedTime) >
+			    ageout_time) {
+			bssId = result->Result.BssDescriptor.bssId;
+			sms_log(mac_ctx, LOGW,
+				FL("age out due to time out"MAC_ADDRESS_STR),
+				MAC_ADDR_ARRAY(bssId));
+			csr_scan_age_out_bss(mac_ctx, result);
+		}
+		entry = tmp_entry;
+	}
+	csr_ll_unlock(&mac_ctx->scan.scanResultList);
+	cdf_mc_timer_start(&mac_ctx->scan.hTimerResultCfgAging,
+			   CSR_SCAN_RESULT_CFG_AGING_INTERVAL /
+			   CDF_MC_TIMER_TO_MS_UNIT);
+}
+
+bool csr_scan_remove_fresh_scan_command(tpAniSirGlobal pMac, uint8_t sessionId)
+{
+	bool fRet = false;
+	tListElem *pEntry, *pEntryTmp;
+	tSmeCmd *pCommand;
+	tDblLinkList localList;
+	tDblLinkList *pCmdList;
+
+	cdf_mem_zero(&localList, sizeof(tDblLinkList));
+	if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
+		sms_log(pMac, LOGE, FL(" failed to open list"));
+		return fRet;
+	}
+
+	pCmdList = &pMac->sme.smeScanCmdPendingList;
+
+	csr_ll_lock(pCmdList);
+	pEntry = csr_ll_peek_head(pCmdList, LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		pEntryTmp = csr_ll_next(pCmdList, pEntry, LL_ACCESS_NOLOCK);
+		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+		if (!((eSmeCommandScan == pCommand->command)
+		    && (sessionId == pCommand->sessionId))) {
+			pEntry = pEntryTmp;
+			continue;
+		}
+		sms_log(pMac, LOGW,
+			FL("-------- abort scan command reason = %d"),
+			pCommand->u.scanCmd.reason);
+		/* The rest are fresh scan requests */
+		if (csr_ll_remove_entry(pCmdList, pEntry,
+					LL_ACCESS_NOLOCK)) {
+			csr_ll_insert_tail(&localList, pEntry,
+					   LL_ACCESS_NOLOCK);
+		}
+		fRet = true;
+		pEntry = pEntryTmp;
+	}
+
+	csr_ll_unlock(pCmdList);
+
+	while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
+		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+		if (pCommand->u.scanCmd.callback) {
+			/*
+			 * User scan request is pending, send response with
+			 * status eCSR_SCAN_ABORT
+			 */
+			pCommand->u.scanCmd.callback(pMac,
+				pCommand->u.scanCmd.pContext, sessionId,
+				pCommand->u.scanCmd.scanID, eCSR_SCAN_ABORT);
+		}
+		csr_release_command_scan(pMac, pCommand);
+	}
+	csr_ll_close(&localList);
+
+	return fRet;
+}
+
+void csr_release_scan_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
+			      eCsrScanStatus scanStatus)
+{
+	eCsrScanReason reason = pCommand->u.scanCmd.reason;
+	bool status;
+	tDblLinkList *cmd_list = NULL;
+
+	csr_scan_call_callback(pMac, pCommand, scanStatus);
+	sms_log(pMac, LOG1, FL("Remove Scan command reason = %d, scan_id %d"),
+		reason, pCommand->u.scanCmd.scanID);
+	cmd_list = &pMac->sme.smeScanCmdActiveList;
+	status = csr_ll_remove_entry(cmd_list, &pCommand->Link, LL_ACCESS_LOCK);
+	if (!status) {
+		sms_log(pMac, LOGE,
+			FL("cannot release command reason %d scan_id %d"),
+			pCommand->u.scanCmd.reason,
+			pCommand->u.scanCmd.scanID);
+		return;
+	}
+	csr_release_command_scan(pMac, pCommand);
+}
+
+CDF_STATUS csr_scan_get_pmkid_candidate_list(tpAniSirGlobal pMac,
+					     uint32_t sessionId,
+					     tPmkidCandidateInfo *pPmkidList,
+					     uint32_t *pNumItems)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+	tCsrScanResultFilter *pScanFilter;
+	tCsrScanResultInfo *pScanResult;
+	tScanResultHandle hBSSList;
+	uint32_t nItems = *pNumItems;
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("  session %d not found "), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOGW, FL("pMac->scan.NumPmkidCandidate = %d"),
+		pSession->NumPmkidCandidate);
+	csr_reset_pmkid_candidate_list(pMac, sessionId);
+	if (!(csr_is_conn_state_connected(pMac, sessionId)
+	    && pSession->pCurRoamProfile))
+		return status;
+
+	*pNumItems = 0;
+	pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
+	if (NULL == pScanFilter)
+		return CDF_STATUS_E_NOMEM;
+
+	cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
+	/* Here is the profile we need to connect to */
+	status = csr_roam_prepare_filter_from_profile(pMac,
+					pSession->pCurRoamProfile, pScanFilter);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		cdf_mem_free(pScanFilter);
+		return status;
+	}
+
+	status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		csr_free_scan_filter(pMac, pScanFilter);
+		cdf_mem_free(pScanFilter);
+		return status;
+	}
+
+	if (pSession->NumPmkidCandidate < nItems) {
+		pScanResult = csr_scan_result_get_next(pMac, hBSSList);
+		while (pScanResult != NULL) {
+			/* NumPmkidCandidate adds up here */
+			csr_process_bss_desc_for_pmkid_list(pMac,
+				&pScanResult->BssDescriptor,
+				(tDot11fBeaconIEs *)(pScanResult->pvIes),
+				sessionId);
+			pScanResult = csr_scan_result_get_next(pMac, hBSSList);
+		}
+	}
+
+	if (pSession->NumPmkidCandidate) {
+		*pNumItems = pSession->NumPmkidCandidate;
+		cdf_mem_copy(pPmkidList, pSession->PmkidCandidateInfo,
+			     pSession->NumPmkidCandidate *
+			     sizeof(tPmkidCandidateInfo));
+	}
+
+	csr_scan_result_purge(pMac, hBSSList);
+	csr_free_scan_filter(pMac, pScanFilter);
+	cdf_mem_free(pScanFilter);
+	return status;
+}
+
+#ifdef FEATURE_WLAN_WAPI
+CDF_STATUS csr_scan_get_bkid_candidate_list(tpAniSirGlobal pMac,
+					    uint32_t sessionId,
+					    tBkidCandidateInfo *pBkidList,
+					    uint32_t *pNumItems)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+	tCsrScanResultFilter *pScanFilter;
+	tCsrScanResultInfo *pScanResult;
+	tScanResultHandle hBSSList;
+	uint32_t nItems = *pNumItems;
+
+	if (!pSession) {
+		sms_log(pMac, LOGE, FL("  session %d not found "), sessionId);
+		return CDF_STATUS_E_FAILURE;
+	}
+
+	sms_log(pMac, LOGW, FL("pMac->scan.NumBkidCandidate = %d"),
+		pSession->NumBkidCandidate);
+	csr_reset_bkid_candidate_list(pMac, sessionId);
+	if (!(csr_is_conn_state_connected(pMac, sessionId)
+	    && pSession->pCurRoamProfile))
+		return status;
+
+	*pNumItems = 0;
+	pScanFilter = cdf_mem_malloc(sizeof(tCsrScanResultFilter));
+	if (NULL == pScanFilter)
+		return CDF_STATUS_E_NOMEM;
+
+	cdf_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
+	/* Here is the profile we need to connect to */
+	status = csr_roam_prepare_filter_from_profile(pMac,
+					pSession->pCurRoamProfile, pScanFilter);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		cdf_mem_free(pScanFilter);
+		return status;
+	}
+
+	status = csr_scan_get_result(pMac, pScanFilter, &hBSSList);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		csr_free_scan_filter(pMac, pScanFilter);
+		cdf_mem_free(pScanFilter);
+		return status;
+	}
+
+	if (pSession->NumBkidCandidate < nItems) {
+		pScanResult = csr_scan_result_get_next(pMac, hBSSList);
+		while (pScanResult != NULL) {
+			/* pMac->scan.NumBkidCandidate adds up here */
+			csr_process_bss_desc_for_bkid_list(pMac,
+				&pScanResult->BssDescriptor,
+				(tDot11fBeaconIEs *)(pScanResult->pvIes));
+			pScanResult = csr_scan_result_get_next(pMac, hBSSList);
+		}
+	}
+
+	if (pSession->NumBkidCandidate) {
+		*pNumItems = pSession->NumBkidCandidate;
+		cdf_mem_copy(pBkidList, pSession->BkidCandidateInfo,
+			     pSession->NumBkidCandidate *
+			     sizeof(tBkidCandidateInfo));
+	}
+
+	csr_scan_result_purge(pMac, hBSSList);
+	csr_free_scan_filter(pMac, pScanFilter);
+	cdf_mem_free(pScanFilter);
+	return status;
+}
+#endif /* FEATURE_WLAN_WAPI */
+
+/**
+ * csr_roam_copy_channellist() - Function to copy channel list
+ * @mac_ctx: pointer to Global Mac structure
+ * @profile: pointer to tCsrRoamProfile
+ * @scan_cmd: pointer to tSmeCmd
+ * @index: index for channellist
+ *
+ * Function copies channel list
+ *
+ * Return: none
+ */
+static void csr_roam_copy_channellist(tpAniSirGlobal mac_ctx,
+				tCsrRoamProfile *profile,
+				tSmeCmd *scan_cmd, uint8_t index)
+{
+	tCsrChannelInfo *channel_info =
+		&scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo;
+
+	for (index = 0; index < profile->ChannelInfo.numOfChannels;
+			index++) {
+		if (!csr_roam_is_valid_channel(mac_ctx,
+			profile->ChannelInfo.ChannelList[index])) {
+			sms_log(mac_ctx, LOGW,
+				FL("process a channel (%d) that is invalid"),
+			profile->ChannelInfo.ChannelList[index]);
+			continue;
+		}
+		channel_info->ChannelList[channel_info->numOfChannels] =
+			profile->ChannelInfo.ChannelList[index];
+		scan_cmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels++;
+	}
+}
+
+/**
+ * csr_scan_for_ssid() -  Function usually used for BSSs that suppresses SSID
+ * @mac_ctx: Pointer to Global Mac structure
+ * @profile: pointer to tCsrRoamProfile
+ * @roam_id: variable representing roam id
+ * @notify: boolean variable
+ *
+ * Function is usually used for BSSs that suppresses SSID so the profile
+ * shall have one and only one SSID.
+ *
+ * Return: Success - CDF_STATUS_SUCCESS, Failure - error number
+ */
+CDF_STATUS csr_scan_for_ssid(tpAniSirGlobal mac_ctx, uint32_t session_id,
+			tCsrRoamProfile *profile, uint32_t roam_id,
+			bool notify)
+{
+	CDF_STATUS status = CDF_STATUS_E_INVAL;
+	tSmeCmd *scan_cmd = NULL;
+	tCsrScanRequest *scan_req = NULL;
+	uint8_t index = 0;
+	uint32_t num_ssid = profile->SSIDs.numOfSSIDs;
+	tpCsrNeighborRoamControlInfo neighbor_roaminfo =
+		&mac_ctx->roam.neighborRoamInfo[session_id];
+	tCsrSSIDs *ssids = NULL;
+
+	sms_log(mac_ctx, LOG2, FL("called"));
+
+	/* For WDS, we use the index 0. There must be at least one in there */
+	if (CSR_IS_WDS_STA(profile) && num_ssid)
+		num_ssid = 1;
+
+	if (!(mac_ctx->scan.fScanEnable) && (num_ssid != 1)) {
+		sms_log(mac_ctx, LOGE,
+			FL("cannot scan because scanEnable (%d) or numSSID (%d) is invalid"),
+			mac_ctx->scan.fScanEnable, profile->SSIDs.numOfSSIDs);
+		return status;
+	}
+
+	scan_cmd = csr_get_command_buffer(mac_ctx);
+
+	if (!scan_cmd) {
+		sms_log(mac_ctx, LOGE,
+			FL("failed to allocate command buffer"));
+		goto error;
+	}
+
+	cdf_mem_set(&scan_cmd->u.scanCmd, sizeof(tScanCmd), 0);
+	scan_cmd->u.scanCmd.pToRoamProfile =
+			cdf_mem_malloc(sizeof(tCsrRoamProfile));
+
+	if (NULL == scan_cmd->u.scanCmd.pToRoamProfile)
+		status = CDF_STATUS_E_NOMEM;
+	else
+		status = csr_roam_copy_profile(mac_ctx,
+					scan_cmd->u.scanCmd.pToRoamProfile,
+					profile);
+
+	if (!CDF_IS_STATUS_SUCCESS(status))
+		goto error;
+
+	scan_cmd->u.scanCmd.roamId = roam_id;
+	scan_cmd->command = eSmeCommandScan;
+	scan_cmd->sessionId = (uint8_t) session_id;
+	scan_cmd->u.scanCmd.callback = NULL;
+	scan_cmd->u.scanCmd.pContext = NULL;
+	scan_cmd->u.scanCmd.reason = eCsrScanForSsid;
+
+	/* let it wrap around */
+	wma_get_scan_id(&scan_cmd->u.scanCmd.scanID);
+	cdf_mem_set(&scan_cmd->u.scanCmd.u.scanRequest,
+			sizeof(tCsrScanRequest), 0);
+	status = cdf_mc_timer_init(&scan_cmd->u.scanCmd.csr_scan_timer,
+			CDF_TIMER_TYPE_SW,
+			csr_scan_active_list_timeout_handle, &scan_cmd);
+	scan_req = &scan_cmd->u.scanCmd.u.scanRequest;
+	scan_req->scanType = eSIR_ACTIVE_SCAN;
+	scan_req->BSSType = profile->BSSType;
+	scan_req->scan_id = scan_cmd->u.scanCmd.scanID;
+	/*
+	 * To avoid 11b rate in probe request Set p2pSearch
+	 * flag as 1 for P2P Client Mode
+	 */
+	if (CDF_P2P_CLIENT_MODE == profile->csrPersona)
+		scan_req->p2pSearch = 1;
+
+	/* Allocate memory for IE field */
+	if (profile->pAddIEScan) {
+		scan_req->pIEField =
+			cdf_mem_malloc(profile->nAddIEScanLength);
+
+		if (NULL == scan_req->pIEField)
+			status = CDF_STATUS_E_NOMEM;
+		else
+			status = CDF_STATUS_SUCCESS;
+
+		cdf_mem_set(scan_req->pIEField,
+				profile->nAddIEScanLength, 0);
+
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			cdf_mem_copy(scan_req->pIEField,
+					profile->pAddIEScan,
+					profile->nAddIEScanLength);
+			scan_req->uIEFieldLen = profile->nAddIEScanLength;
+		} else {
+			sms_log(mac_ctx, LOGE,
+				"No memory for scanning IE fields");
+		}
+	} else
+		scan_req->uIEFieldLen = 0;
+
+	/*
+	 * For one channel be good enpugh time to receive beacon
+	 * atleast
+	 */
+	if (1 == profile->ChannelInfo.numOfChannels) {
+		if (neighbor_roaminfo->handoffReqInfo.src ==
+					FASTREASSOC) {
+			scan_req->maxChnTime =
+				MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC;
+			scan_req->minChnTime =
+				MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL_FASTREASSOC;
+			/* Reset this value */
+			neighbor_roaminfo->handoffReqInfo.src = 0;
+		} else {
+			scan_req->maxChnTime =
+					MAX_ACTIVE_SCAN_FOR_ONE_CHANNEL;
+			scan_req->minChnTime =
+					MIN_ACTIVE_SCAN_FOR_ONE_CHANNEL;
+		}
+	} else {
+		scan_req->maxChnTime =
+			mac_ctx->roam.configParam.nActiveMaxChnTime;
+		scan_req->minChnTime =
+			mac_ctx->roam.configParam.nActiveMinChnTime;
+	}
+
+	if (profile->BSSIDs.numOfBSSIDs == 1)
+		cdf_copy_macaddr(&scan_req->bssid,
+				profile->BSSIDs.bssid);
+	else
+		cdf_set_macaddr_broadcast(&scan_req->bssid);
+
+	if (profile->ChannelInfo.numOfChannels) {
+		scan_req->ChannelInfo.ChannelList =
+		    cdf_mem_malloc(sizeof(*scan_req->ChannelInfo.ChannelList) *
+					profile->ChannelInfo.numOfChannels);
+
+		if (NULL == scan_req->ChannelInfo.ChannelList)
+			status = CDF_STATUS_E_NOMEM;
+		else
+			status = CDF_STATUS_SUCCESS;
+
+		scan_req->ChannelInfo.numOfChannels = 0;
+
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			csr_roam_is_channel_valid(mac_ctx,
+				profile->ChannelInfo.ChannelList[0]);
+			csr_roam_copy_channellist(mac_ctx,
+				profile, scan_cmd, index);
+		} else {
+			goto error;
+		}
+	} else {
+		scan_req->ChannelInfo.numOfChannels = 0;
+	}
+
+	if (profile->SSIDs.numOfSSIDs) {
+		scan_req->SSIDs.SSIDList =
+			cdf_mem_malloc(profile->SSIDs.numOfSSIDs *
+					sizeof(tCsrSSIDInfo));
+
+		if (NULL == scan_req->SSIDs.SSIDList)
+			status = CDF_STATUS_E_NOMEM;
+		else
+			status = CDF_STATUS_SUCCESS;
+
+		if (!CDF_IS_STATUS_SUCCESS(status))
+			goto error;
+
+		ssids = &scan_req->SSIDs;
+		ssids->numOfSSIDs =  1;
+
+		cdf_mem_copy(scan_req->SSIDs.SSIDList,
+				profile->SSIDs.SSIDList,
+				sizeof(tCsrSSIDInfo));
+	}
+
+	/* Start process the command */
+	status = csr_queue_sme_command(mac_ctx, scan_cmd, false);
+error:
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE,
+			FL(" failed to iniate scan with status = %d"), status);
+		if (scan_cmd)
+			csr_release_command_scan(mac_ctx, scan_cmd);
+		if (notify)
+			csr_roam_call_callback(mac_ctx, session_id, NULL,
+					roam_id, eCSR_ROAM_FAILED,
+					eCSR_ROAM_RESULT_FAILURE);
+	}
+	return status;
+}
+
+void csr_set_cfg_valid_channel_list(tpAniSirGlobal pMac, uint8_t *pChannelList,
+				    uint8_t NumChannels)
+{
+	uint32_t dataLen = sizeof(uint8_t) * NumChannels;
+	CDF_STATUS status;
+
+	CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
+		  "%s: dump valid channel list(NumChannels(%d))",
+		  __func__, NumChannels);
+	CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
+			   pChannelList, NumChannels);
+	cfg_set_str(pMac, WNI_CFG_VALID_CHANNEL_LIST, pChannelList,
+			dataLen);
+
+	CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
+		  "Scan offload is enabled, update default chan list");
+	/*
+	 * disable fcc constraint since new country code
+	 * is being set
+	 */
+	pMac->scan.fcc_constraint = false;
+	status = csr_update_channel_list(pMac);
+	if (CDF_STATUS_SUCCESS != status) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+			  "failed to update the supported channel list");
+	}
+	return;
+}
+
+/*
+ * The Tx power limits are saved in the cfg for future usage.
+ */
+void csr_save_tx_power_to_cfg(tpAniSirGlobal pMac, tDblLinkList *pList,
+			      uint32_t cfgId)
+{
+	tListElem *pEntry;
+	uint32_t cbLen = 0, dataLen, tmp_len;
+	tCsrChannelPowerInfo *ch_set;
+	uint32_t idx;
+	tSirMacChanInfo *ch_pwr_set;
+	uint8_t *pBuf = NULL;
+
+	/* allocate maximum space for all channels */
+	dataLen = WNI_CFG_VALID_CHANNEL_LIST_LEN * sizeof(tSirMacChanInfo);
+	pBuf = cdf_mem_malloc(dataLen);
+	if (pBuf == NULL)
+		return;
+
+	cdf_mem_set(pBuf, dataLen, 0);
+	ch_pwr_set = (tSirMacChanInfo *) (pBuf);
+	pEntry = csr_ll_peek_head(pList, LL_ACCESS_LOCK);
+	/*
+	 * write the tuples (startChan, numChan, txPower) for each channel found
+	 * in the channel power list.
+	 */
+	while (pEntry) {
+		ch_set = GET_BASE_ADDR(pEntry, tCsrChannelPowerInfo, link);
+		if (1 != ch_set->interChannelOffset) {
+			/*
+			 * we keep the 5G channel sets internally with an
+			 * interchannel offset of 4. Expand these to the right
+			 * format. (inter channel offset of 1 is the only option
+			 * for the triplets that 11d advertises.
+			 */
+			tmp_len = cbLen + (ch_set->numChannels *
+						sizeof(tSirMacChanInfo));
+			if (tmp_len >= dataLen) {
+				/*
+				 * expanding this entry will overflow our
+				 * allocation
+				 */
+				sms_log(pMac, LOGE,
+					FL("Buffer overflow, start %d, num %d, offset %d"),
+					ch_set->firstChannel,
+					ch_set->numChannels,
+					ch_set->interChannelOffset);
+				break;
+			}
+
+			for (idx = 0; idx < ch_set->numChannels; idx++) {
+				ch_pwr_set->firstChanNum = (tSirMacChanNum)
+					(ch_set->firstChannel + (idx *
+						ch_set->interChannelOffset));
+				sms_log(pMac, LOG3,
+					FL("Setting Channel Number %d"),
+					ch_pwr_set->firstChanNum);
+				ch_pwr_set->numChannels = 1;
+				ch_pwr_set->maxTxPower =
+					CDF_MIN(ch_set->txPower,
+					pMac->roam.configParam.nTxPowerCap);
+				sms_log(pMac, LOG3,
+					FL("Setting Max Transmit Power %d"),
+					ch_pwr_set->maxTxPower);
+				cbLen += sizeof(tSirMacChanInfo);
+				ch_pwr_set++;
+			}
+		} else {
+			if (cbLen >= dataLen) {
+				/* this entry will overflow our allocation */
+				sms_log(pMac, LOGE,
+					FL("Buffer overflow, start %d, num %d, offset %d"),
+					ch_set->firstChannel,
+					ch_set->numChannels,
+					ch_set->interChannelOffset);
+				break;
+			}
+			ch_pwr_set->firstChanNum = ch_set->firstChannel;
+			sms_log(pMac, LOG3, FL("Setting Channel Number %d"),
+				ch_pwr_set->firstChanNum);
+			ch_pwr_set->numChannels = ch_set->numChannels;
+			ch_pwr_set->maxTxPower = CDF_MIN(ch_set->txPower,
+					pMac->roam.configParam.nTxPowerCap);
+			sms_log(pMac, LOG3,
+				FL("Setting Max Tx Power %d, nTxPower %d"),
+				ch_pwr_set->maxTxPower,
+				pMac->roam.configParam.nTxPowerCap);
+			cbLen += sizeof(tSirMacChanInfo);
+			ch_pwr_set++;
+		}
+		pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_LOCK);
+	}
+	if (cbLen)
+		cfg_set_str(pMac, cfgId, (uint8_t *) pBuf, cbLen);
+
+	cdf_mem_free(pBuf);
+}
+
+void csr_set_cfg_country_code(tpAniSirGlobal pMac, uint8_t *countryCode)
+{
+	uint8_t cc[WNI_CFG_COUNTRY_CODE_LEN];
+	/* v_REGDOMAIN_t DomainId */
+
+	sms_log(pMac, LOG3, FL("Setting Country Code in Cfg %s"), countryCode);
+	cdf_mem_copy(cc, countryCode, WNI_CFG_COUNTRY_CODE_LEN);
+
+	/*
+	* don't program the bogus country codes that we created for Korea in the
+	* MAC. if we see the bogus country codes, program the MAC with the right
+	* country code.
+	*/
+	if (('K' == countryCode[0] && '1' == countryCode[1]) ||
+	    ('K' == countryCode[0] && '2' == countryCode[1]) ||
+	    ('K' == countryCode[0] && '3' == countryCode[1]) ||
+	    ('K' == countryCode[0] && '4' == countryCode[1])) {
+		/*
+		 * replace the alternate Korea country codes, 'K1', 'K2', ..
+		 * with 'KR' for Korea
+		 */
+		cc[1] = 'R';
+	}
+	cfg_set_str(pMac, WNI_CFG_COUNTRY_CODE, cc, WNI_CFG_COUNTRY_CODE_LEN);
+
+	/*
+	 * Need to let HALPHY know about the current domain so it can apply some
+	 * domain-specific settings (TX filter...)
+	 */
+	/*
+	if(CDF_IS_STATUS_SUCCESS(csr_get_regulatory_domain_for_country(
+		pMac, cc, &DomainId))) {
+		halPhySetRegDomain(pMac, DomainId);
+	} */
+}
+
+CDF_STATUS csr_get_country_code(tpAniSirGlobal pMac, uint8_t *pBuf,
+				uint8_t *pbLen)
+{
+	CDF_STATUS status = CDF_STATUS_E_INVAL;
+	uint32_t len;
+
+	if (pBuf && pbLen && (*pbLen >= WNI_CFG_COUNTRY_CODE_LEN)) {
+		len = *pbLen;
+		status = wlan_cfg_get_str(pMac, WNI_CFG_COUNTRY_CODE, pBuf, &len);
+		if (CDF_IS_STATUS_SUCCESS(status)) {
+			*pbLen = (uint8_t) len;
+		}
+	}
+
+	return status;
+}
+
+void csr_set_cfg_scan_control_list(tpAniSirGlobal pMac, uint8_t *countryCode,
+				   tCsrChannel *pChannelList)
+{
+	uint8_t i, j;
+	bool found = false;
+	uint8_t *pControlList = NULL;
+	uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
+
+	pControlList = cdf_mem_malloc(WNI_CFG_SCAN_CONTROL_LIST_LEN);
+	if (pControlList != NULL) {
+		cdf_mem_set((void *)pControlList, WNI_CFG_SCAN_CONTROL_LIST_LEN,
+			    0);
+		if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_str(pMac,
+					WNI_CFG_SCAN_CONTROL_LIST,
+					pControlList, &len))) {
+			for (i = 0; i < pChannelList->numChannels; i++) {
+				for (j = 0; j < len; j += 2) {
+					if (pControlList[j] ==
+					    pChannelList->channelList[i]) {
+						found = true;
+						break;
+					}
+				}
+
+				if (found) {
+					/* insert a pair(channel#, flag) */
+					pControlList[j + 1] =
+						csr_get_scan_type(pMac,
+								  pControlList[j]);
+					found = false;  /* reset the flag */
+				}
+
+			}
+			CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO,
+				  "%s: dump scan control list", __func__);
+			CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_SME,
+					   CDF_TRACE_LEVEL_INFO, pControlList,
+					   len);
+
+			cfg_set_str(pMac, WNI_CFG_SCAN_CONTROL_LIST,
+					pControlList, len);
+		} /* Successfully getting scan control list */
+		cdf_mem_free(pControlList);
+	} /* AllocateMemory */
+}
+
+CDF_STATUS csr_scan_abort_mac_scan(tpAniSirGlobal pMac, uint8_t sessionId,
+				   eCsrAbortReason reason)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	pMac->scan.fDropScanCmd = true;
+	csr_remove_cmd_with_session_id_from_pending_list(pMac,
+			sessionId, &pMac->sme.smeScanCmdPendingList,
+			eSmeCommandScan);
+	pMac->scan.fDropScanCmd = false;
+	csr_abort_scan_from_active_list(pMac,
+			 &pMac->sme.smeScanCmdActiveList, sessionId,
+			eSmeCommandScan, reason);
+
+	return status;
+}
+
+void csr_remove_cmd_with_session_id_from_pending_list(tpAniSirGlobal pMac,
+						uint8_t sessionId,
+						tDblLinkList *pList,
+						eSmeCommandType commandType)
+{
+	tDblLinkList localList;
+	tListElem *pEntry;
+	tSmeCmd *pCommand;
+	tListElem *pEntryToRemove;
+
+	cdf_mem_zero(&localList, sizeof(tDblLinkList));
+	if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
+		sms_log(pMac, LOGE, FL("failed to open list"));
+		return;
+	}
+
+	csr_ll_lock(pList);
+	pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
+	if (pEntry) {
+		/*
+		 * Have to make sure we don't loop back to the head of the list,
+		 * which will happen if the entry is NOT on the list
+		 */
+		while (pEntry) {
+			pEntryToRemove = pEntry;
+			pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+			pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
+
+			if (!((pCommand->command == commandType) &&
+			    (pCommand->sessionId == sessionId)))
+				continue;
+			/* Remove that entry only */
+			if (csr_ll_remove_entry(pList, pEntryToRemove,
+						LL_ACCESS_NOLOCK)) {
+				csr_ll_insert_tail(&localList, pEntryToRemove,
+						   LL_ACCESS_NOLOCK);
+			}
+		}
+	}
+	csr_ll_unlock(pList);
+
+	while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
+		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+		sms_log(pMac, LOG1, FL("Sending abort for scan command ID %d"),
+			pCommand->u.scanCmd.scanID);
+		csr_abort_command(pMac, pCommand, false);
+	}
+
+	csr_ll_close(&localList);
+}
+
+void csr_remove_cmd_from_pending_list(tpAniSirGlobal pMac,
+				      tDblLinkList *pList,
+				      eSmeCommandType commandType)
+{
+	tDblLinkList localList;
+	tListElem *pEntry;
+	tSmeCmd *pCommand;
+	tListElem *pEntryToRemove;
+
+	cdf_mem_zero(&localList, sizeof(tDblLinkList));
+	if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
+		sms_log(pMac, LOGE, FL(" failed to open list"));
+		return;
+	}
+
+	csr_ll_lock(pList);
+	if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) {
+		pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
+		/*
+		 * Have to make sure we don't loop back to the head of the list,
+		 * which will happen if the entry is NOT on the list...
+		 */
+		while (pEntry) {
+			pEntryToRemove = pEntry;
+			pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+			pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
+			/* Remove that entry only that matches cmd type */
+			if (pCommand->command == commandType &&
+			    csr_ll_remove_entry(pList, pEntryToRemove,
+						LL_ACCESS_NOLOCK)) {
+				csr_ll_insert_tail(&localList, pEntryToRemove,
+						   LL_ACCESS_NOLOCK);
+			}
+		}
+	}
+	csr_ll_unlock(pList);
+
+	while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
+		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+		csr_abort_command(pMac, pCommand, false);
+	}
+	csr_ll_close(&localList);
+
+}
+
+CDF_STATUS csr_scan_abort_scan_for_ssid(tpAniSirGlobal pMac, uint32_t sessionId)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	pMac->scan.fDropScanCmd = true;
+	csr_remove_scan_for_ssid_from_pending_list(pMac,
+			&pMac->sme.smeScanCmdPendingList, sessionId);
+	pMac->scan.fDropScanCmd = false;
+	csr_abort_scan_from_active_list(pMac, &pMac->sme.smeScanCmdActiveList,
+		sessionId, eSmeCommandScan, eCSR_SCAN_ABORT_SSID_ONLY);
+	return status;
+}
+
+void csr_remove_scan_for_ssid_from_pending_list(tpAniSirGlobal pMac,
+						tDblLinkList *pList,
+						uint32_t sessionId)
+{
+	tDblLinkList localList;
+	tListElem *pEntry;
+	tSmeCmd *pCommand;
+	tListElem *pEntryToRemove;
+
+	cdf_mem_zero(&localList, sizeof(tDblLinkList));
+	if (!CDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
+		sms_log(pMac, LOGE, FL(" failed to open list"));
+		return;
+	}
+	csr_ll_lock(pList);
+	if (!csr_ll_is_list_empty(pList, LL_ACCESS_NOLOCK)) {
+		pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
+		/*
+		 * Have to make sure we don't loop back to the head of the list,
+		 * which will happen if the entry is NOT on the list...
+		 */
+		while (pEntry) {
+			pEntryToRemove = pEntry;
+			pEntry = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
+			pCommand = GET_BASE_ADDR(pEntryToRemove, tSmeCmd, Link);
+
+			if (!((eSmeCommandScan == pCommand->command) &&
+			    (sessionId == pCommand->sessionId)))
+				continue;
+			if (eCsrScanForSsid != pCommand->u.scanCmd.reason)
+				continue;
+			/* Remove that entry only */
+			if (csr_ll_remove_entry(pList, pEntryToRemove,
+						LL_ACCESS_NOLOCK)) {
+				csr_ll_insert_tail(&localList, pEntryToRemove,
+						   LL_ACCESS_NOLOCK);
+			}
+		}
+	}
+	csr_ll_unlock(pList);
+	while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
+		pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
+		csr_abort_command(pMac, pCommand, false);
+	}
+	csr_ll_close(&localList);
+}
+
+
+/**
+ * csr_send_scan_abort() -  Sends scan abort command to firmware
+ * @mac_ctx: Pointer to Global Mac structure
+ * @session_id: CSR session identification
+ * @scan_id: scan identifier
+ *
+ * .Sends scan abort command to firmware
+ *
+ * Return: None
+ */
+static void csr_send_scan_abort(tpAniSirGlobal mac_ctx,
+	uint32_t session_id, uint32_t scan_id)
+{
+	tSirSmeScanAbortReq *msg;
+	uint16_t msg_len;
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq));
+	msg = cdf_mem_malloc(msg_len);
+	if (NULL == msg) {
+		sms_log(mac_ctx, LOGE,
+			FL("Failed to alloc memory for SmeScanAbortReq"));
+		return;
+	}
+	cdf_mem_zero((void *)msg, msg_len);
+	msg->type = eWNI_SME_SCAN_ABORT_IND;
+	msg->msgLen = msg_len;
+	msg->sessionId = session_id;
+	msg->scan_id = scan_id;
+	sms_log(mac_ctx, LOG2,
+		FL("Abort scan sent to Firmware scan_id %d session %d"),
+		scan_id, session_id);
+	status = cds_send_mb_message_to_mac(msg);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		cdf_mem_free(msg);
+		sms_log(mac_ctx, LOGE,
+			FL("Failed to send abort scan.scan_id %d session %d"),
+			scan_id, session_id);
+	}
+	return;
+}
+
+/**
+ * csr_abort_scan_from_active_list() -  Remove Scan command from active list
+ * @mac_ctx: Pointer to Global Mac structure
+ * @list: pointer to scan active list
+ * @session_id: CSR session identification
+ * @scan_cmd_type: scan command type
+ * @abort_reason: abort reason
+ *
+ * .Remove Scan command from active scan list
+ *
+ * Return: Success - CDF_STATUS_SUCCESS, Failure - error number
+ */
+CDF_STATUS csr_abort_scan_from_active_list(tpAniSirGlobal mac_ctx,
+		tDblLinkList *list, uint32_t session_id,
+		eSmeCommandType scan_cmd_type, eCsrAbortReason abort_reason)
+{
+	tListElem *entry;
+	tSmeCmd *cmd;
+	tListElem *entry_remove;
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	csr_ll_lock(list);
+	if (!csr_ll_is_list_empty(list, LL_ACCESS_NOLOCK)) {
+		entry = csr_ll_peek_head(list, LL_ACCESS_NOLOCK);
+		while (entry) {
+			entry_remove = entry;
+			entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
+			cmd = GET_BASE_ADDR(entry_remove, tSmeCmd, Link);
+
+			/* Skip if command and session id not matched */
+			if (!((scan_cmd_type == cmd->command) &&
+				(session_id == cmd->sessionId)))
+				continue;
+			/*skip if abort reason is for SSID*/
+			if ((abort_reason == eCSR_SCAN_ABORT_SSID_ONLY) &&
+				(eCsrScanForSsid != cmd->u.scanCmd.reason))
+					continue;
+			if (abort_reason == eCSR_SCAN_ABORT_DUE_TO_BAND_CHANGE)
+				cmd->u.scanCmd.abortScanDueToBandChange =
+					true;
+			csr_send_scan_abort(mac_ctx, cmd->sessionId,
+						cmd->u.scanCmd.scanID);
+		}
+	}
+	csr_ll_unlock(list);
+
+	return status;
+}
+
+
+CDF_STATUS csr_scan_abort_mac_scan_not_for_connect(tpAniSirGlobal pMac,
+						   uint8_t sessionId)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	if (!csr_is_scan_for_roam_command_active(pMac)) {
+		/*
+		 * Only abort the scan if it is not used for other roam/connect
+		 * purpose
+		 */
+		status = csr_scan_abort_mac_scan(pMac, sessionId,
+						 eCSR_SCAN_ABORT_DEFAULT);
+	}
+	return status;
+}
+bool csr_roam_is_valid_channel(tpAniSirGlobal pMac, uint8_t channel)
+{
+	bool fValid = false;
+	uint32_t idx_valid_ch;
+	uint32_t len = pMac->roam.numValidChannels;
+
+	for (idx_valid_ch = 0; (idx_valid_ch < len); idx_valid_ch++) {
+		if (channel == pMac->roam.validChannelList[idx_valid_ch]) {
+			fValid = true;
+			break;
+		}
+	}
+	return fValid;
+}
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+CDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac,
+						 tSirPrefNetworkFoundInd *
+						 pPrefNetworkFoundInd)
+{
+	uint32_t uLen = 0;
+	tpSirProbeRespBeacon parsed_frm;
+	tCsrScanResult *pScanResult = NULL;
+	tSirBssDescription *pBssDescr = NULL;
+	bool fDupBss;
+	tDot11fBeaconIEs *local_ie = NULL;
+	tAniSSID tmpSsid;
+	v_TIME_t timer = 0;
+	CDF_STATUS status;
+
+	tpSirMacMgmtHdr macHeader =
+		(tpSirMacMgmtHdr) pPrefNetworkFoundInd->data;
+	parsed_frm =
+	    (tpSirProbeRespBeacon) cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
+
+	if (NULL == parsed_frm) {
+		sms_log(pMac, LOGE, FL("fail to allocate memory for frame"));
+		return CDF_STATUS_E_NOMEM;
+	}
+	if (pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A) {
+		sms_log(pMac, LOGE,
+			FL("Incorrect len(%d)"),
+			pPrefNetworkFoundInd->frameLength);
+		cdf_mem_free(parsed_frm);
+		return CDF_STATUS_E_FAILURE;
+	}
+	if (sir_convert_probe_frame2_struct(pMac,
+		&pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A],
+		pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A,
+		parsed_frm) != eSIR_SUCCESS
+	    || !parsed_frm->ssidPresent) {
+		sms_log(pMac, LOGE, FL("Parse error ProbeResponse, length=%d"),
+			pPrefNetworkFoundInd->frameLength);
+		cdf_mem_free(parsed_frm);
+		return CDF_STATUS_E_FAILURE;
+	}
+	/* 24 byte MAC header and 12 byte to ssid IE */
+	if (pPrefNetworkFoundInd->frameLength >
+	    (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) {
+		uLen = pPrefNetworkFoundInd->frameLength -
+		       (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
+	}
+	pScanResult = cdf_mem_malloc(sizeof(tCsrScanResult) + uLen);
+	if (NULL == pScanResult) {
+		sms_log(pMac, LOGE, FL("fail to allocate memory for frame"));
+		cdf_mem_free(parsed_frm);
+		return CDF_STATUS_E_NOMEM;
+	}
+	cdf_mem_set(pScanResult, sizeof(tCsrScanResult) + uLen, 0);
+	pBssDescr = &pScanResult->Result.BssDescriptor;
+	/*
+	 * Length of BSS desription is without length of length itself and
+	 * length of pointer that holds the next BSS description
+	 */
+	pBssDescr->length = (uint16_t) (sizeof(tSirBssDescription) -
+		sizeof(uint16_t) - sizeof(uint32_t) + uLen);
+	if (parsed_frm->dsParamsPresent)
+		pBssDescr->channelId = parsed_frm->channelNumber;
+	else if (parsed_frm->HTInfo.present)
+		pBssDescr->channelId = parsed_frm->HTInfo.primaryChannel;
+	else
+		pBssDescr->channelId = parsed_frm->channelNumber;
+
+	if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) {
+		int i;
+		/* 11b or 11g packet */
+		/* 11g iff extended Rate IE is present or */
+		/* if there is an A rate in suppRate IE */
+		for (i = 0; i < parsed_frm->supportedRates.numRates; i++) {
+			if (sirIsArate(parsed_frm->supportedRates.rate[i]
+				       & 0x7f)) {
+				pBssDescr->nwType = eSIR_11G_NW_TYPE;
+				break;
+			}
+		}
+		if (parsed_frm->extendedRatesPresent)
+			pBssDescr->nwType = eSIR_11G_NW_TYPE;
+	} else {
+		/* 11a packet */
+		pBssDescr->nwType = eSIR_11A_NW_TYPE;
+	}
+	pBssDescr->sinr = 0;
+	pBssDescr->rssi = -1 * pPrefNetworkFoundInd->rssi;
+	pBssDescr->beaconInterval = parsed_frm->beaconInterval;
+	if (!pBssDescr->beaconInterval) {
+		sms_log(pMac, LOGW, FL("Bcn Interval is Zero , default to 100"
+			MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pBssDescr->bssId));
+		pBssDescr->beaconInterval = 100;
+	}
+	pBssDescr->timeStamp[0] = parsed_frm->timeStamp[0];
+	pBssDescr->timeStamp[1] = parsed_frm->timeStamp[1];
+	pBssDescr->capabilityInfo = *((uint16_t *)&parsed_frm->capabilityInfo);
+	cdf_mem_copy((uint8_t *) &pBssDescr->bssId,
+		     (uint8_t *) macHeader->bssId, sizeof(tSirMacAddr));
+	pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks();
+	sms_log(pMac, LOG2, FL("Bssid= "MAC_ADDRESS_STR" chan= %d, rssi = %d"),
+		MAC_ADDR_ARRAY(pBssDescr->bssId), pBssDescr->channelId,
+		pBssDescr->rssi);
+	/* IEs */
+	if (uLen) {
+		cdf_mem_copy(&pBssDescr->ieFields,
+			pPrefNetworkFoundInd->data + (SIR_MAC_HDR_LEN_3A +
+			SIR_MAC_B_PR_SSID_OFFSET), uLen);
+	}
+	local_ie = (tDot11fBeaconIEs *) (pScanResult->Result.pvIes);
+	status = csr_get_parsed_bss_description_ies(pMac,
+			&pScanResult->Result.BssDescriptor, &local_ie);
+	if (!(local_ie || CDF_IS_STATUS_SUCCESS(status))) {
+		sms_log(pMac, LOGE, FL("Cannot parse IEs"));
+		csr_free_scan_result_entry(pMac, pScanResult);
+		cdf_mem_free(parsed_frm);
+		return CDF_STATUS_E_RESOURCES;
+	}
+
+	fDupBss = csr_remove_dup_bss_description(pMac,
+			&pScanResult->Result.BssDescriptor,
+			local_ie, &tmpSsid, &timer, false);
+	/* Check whether we have reach out limit */
+	if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) {
+		/* Limit reach */
+		sms_log(pMac, LOGE, FL("BSS limit reached"));
+		/* Free the resources */
+		if ((pScanResult->Result.pvIes == NULL) && local_ie)
+			cdf_mem_free(local_ie);
+		csr_free_scan_result_entry(pMac, pScanResult);
+		cdf_mem_free(parsed_frm);
+		return CDF_STATUS_E_RESOURCES;
+	}
+	/* Add to scan cache */
+	csr_scan_add_result(pMac, pScanResult, local_ie,
+			    pPrefNetworkFoundInd->sessionId);
+
+	if ((pScanResult->Result.pvIes == NULL) && local_ie)
+		cdf_mem_free(local_ie);
+	cdf_mem_free(parsed_frm);
+	return CDF_STATUS_SUCCESS;
+}
+#endif /* FEATURE_WLAN_SCAN_PNO */
+
+#ifdef FEATURE_WLAN_LFR
+void csr_init_occupied_channels_list(tpAniSirGlobal pMac, uint8_t sessionId)
+{
+	tListElem *pEntry = NULL;
+	tCsrScanResult *pBssDesc = NULL;
+	tDot11fBeaconIEs *pIes = NULL;
+	tpCsrNeighborRoamControlInfo pNeighborRoamInfo =
+		&pMac->roam.neighborRoamInfo[sessionId];
+
+	if (0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) {
+		/*
+		 * Ini file contains neighbor scan channel list, hence NO need
+		 * to build occupied channel list"
+		 */
+		sms_log(pMac, LOG1, FL("Ini contains neighbor scan ch list"));
+		return;
+	}
+
+	if (!csr_neighbor_roam_is_new_connected_profile(pMac, sessionId)) {
+		/*
+		 * Do not flush occupied list since current roam profile matches
+		 * previous
+		 */
+		sms_log(pMac, LOG2, FL("Current roam profile matches prev"));
+		return;
+	}
+
+	/* Empty occupied channels here */
+	pMac->scan.occupiedChannels[sessionId].numChannels = 0;
+
+	csr_ll_lock(&pMac->scan.scanResultList);
+	pEntry = csr_ll_peek_head(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK);
+	while (pEntry) {
+		pBssDesc = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
+		pIes = (tDot11fBeaconIEs *) (pBssDesc->Result.pvIes);
+		/* At this time, pBssDescription->Result.pvIes may be NULL */
+		if (!pIes && !CDF_IS_STATUS_SUCCESS(
+			csr_get_parsed_bss_description_ies(pMac,
+				&pBssDesc->Result.BssDescriptor, &pIes)))
+			continue;
+		csr_scan_add_to_occupied_channels(pMac, pBssDesc, sessionId,
+				&pMac->scan.occupiedChannels[sessionId], pIes);
+		/*
+		 * Free the memory allocated for pIes in
+		 * csr_get_parsed_bss_description_ies
+		 */
+		if ((pBssDesc->Result.pvIes == NULL) && pIes)
+			cdf_mem_free(pIes);
+		pEntry = csr_ll_next(&pMac->scan.scanResultList, pEntry,
+				     LL_ACCESS_NOLOCK);
+	} /* while */
+	csr_ll_unlock(&pMac->scan.scanResultList);
+}
+#endif
+
+CDF_STATUS csr_scan_create_entry_in_scan_cache(tpAniSirGlobal pMac,
+					       uint32_t sessionId,
+					       struct cdf_mac_addr bssid,
+					       uint8_t channel)
+{
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+	tDot11fBeaconIEs *pNewIes = NULL;
+	tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
+	tSirBssDescription *pNewBssDescriptor = NULL;
+	uint32_t size = 0;
+
+	if (NULL == pSession) {
+		status = CDF_STATUS_E_FAILURE;
+		return status;
+	}
+	sms_log(pMac, LOG2, FL("Current bssid::"MAC_ADDRESS_STR),
+		MAC_ADDR_ARRAY(pSession->pConnectBssDesc->bssId));
+	sms_log(pMac, LOG2, FL("My bssid::"MAC_ADDRESS_STR" channel %d"),
+		MAC_ADDR_ARRAY(bssid.bytes), channel);
+
+	if (!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(
+					pMac, pSession->pConnectBssDesc,
+					&pNewIes))) {
+		sms_log(pMac, LOGE, FL("Failed to parse IEs"));
+		status = CDF_STATUS_E_FAILURE;
+		goto free_mem;
+	}
+	size = pSession->pConnectBssDesc->length +
+		sizeof(pSession->pConnectBssDesc->length);
+	if (!size) {
+		sms_log(pMac, LOGE, FL("length of bss descriptor is 0"));
+		status = CDF_STATUS_E_FAILURE;
+		goto free_mem;
+	}
+	pNewBssDescriptor = cdf_mem_malloc(size);
+	if (NULL == pNewBssDescriptor) {
+		sms_log(pMac, LOGE, FL("memory allocation failed"));
+		status = CDF_STATUS_E_FAILURE;
+		goto free_mem;
+	}
+	cdf_mem_copy(pNewBssDescriptor, pSession->pConnectBssDesc, size);
+	/* change the BSSID & channel as passed */
+	cdf_mem_copy(pNewBssDescriptor->bssId, bssid.bytes,
+			sizeof(tSirMacAddr));
+	pNewBssDescriptor->channelId = channel;
+	if (NULL == csr_scan_append_bss_description(pMac, pNewBssDescriptor,
+						pNewIes, true, sessionId)) {
+		sms_log(pMac, LOGE,
+			FL("csr_scan_append_bss_description failed"));
+		status = CDF_STATUS_E_FAILURE;
+		goto free_mem;
+	}
+	sms_log(pMac, LOGE, FL("entry successfully added in scan cache"));
+
+free_mem:
+	if (pNewIes) {
+		cdf_mem_free(pNewIes);
+	}
+	if (pNewBssDescriptor) {
+		cdf_mem_free(pNewBssDescriptor);
+	}
+	return status;
+}
+
+#ifdef FEATURE_WLAN_ESE
+/*  Update the TSF with the difference in system time */
+void update_cckmtsf(uint32_t *timeStamp0, uint32_t *timeStamp1,
+		    uint32_t *incr)
+{
+	uint64_t timeStamp64 = ((uint64_t) *timeStamp1 << 32) | (*timeStamp0);
+	timeStamp64 = (uint64_t) (timeStamp64 + (uint64_t) *incr);
+	*timeStamp0 = (uint32_t) (timeStamp64 & 0xffffffff);
+	*timeStamp1 = (uint32_t) ((timeStamp64 >> 32) & 0xffffffff);
+}
+#endif
+
+/**
+ * csr_scan_save_roam_offload_ap_to_scan_cache
+ * This function parses the received beacon/probe response
+ * from the firmware as part of the roam synch indication.
+ * The beacon or the probe response is parsed and is also
+ * saved into the scan cache
+ *
+ * @param  pMac Pointer to Global Mac
+ * @param  roam_sync_ind_ptr Roam Synch Indication from
+ *         firmware which also contains the beacon/probe
+ *         response
+ * @return Status
+ */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+CDF_STATUS csr_scan_save_roam_offload_ap_to_scan_cache(tpAniSirGlobal pMac,
+				roam_offload_synch_ind *roam_sync_ind_ptr)
+{
+	uint32_t length = 0;
+	bool dup_bss;
+	tDot11fBeaconIEs *ies_local_ptr = NULL;
+	tAniSSID tmpSsid;
+	v_TIME_t timer = 0;
+	tCsrScanResult *scan_res_ptr = NULL;
+	uint8_t session_id = roam_sync_ind_ptr->roamedVdevId;
+
+	length = roam_sync_ind_ptr->beaconProbeRespLength -
+		(SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
+	scan_res_ptr = cdf_mem_malloc(sizeof(tCsrScanResult) + length);
+	if (scan_res_ptr == NULL) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+				" fail to allocate memory for frame");
+		return CDF_STATUS_E_NOMEM;
+	}
+
+	cdf_mem_zero(scan_res_ptr, sizeof(tCsrScanResult) + length);
+	cdf_mem_copy(&scan_res_ptr->Result.BssDescriptor,
+			roam_sync_ind_ptr->bss_desc_ptr,
+			(sizeof(tSirBssDescription) + length));
+	ies_local_ptr = (tDot11fBeaconIEs *)(scan_res_ptr->Result.pvIes);
+	if (!ies_local_ptr &&
+		(!CDF_IS_STATUS_SUCCESS(csr_get_parsed_bss_description_ies(
+						pMac, &scan_res_ptr->Result.
+						BssDescriptor,
+						&ies_local_ptr)))) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+				"%s:Cannot Parse IEs", __func__);
+		csr_free_scan_result_entry(pMac, scan_res_ptr);
+		return CDF_STATUS_E_RESOURCES;
+	}
+
+	dup_bss = csr_remove_dup_bss_description(pMac,
+			&scan_res_ptr->Result.BssDescriptor,
+			ies_local_ptr, &tmpSsid, &timer, true);
+	if (CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+				"%s:BSS Limit Exceed", __func__);
+		if ((scan_res_ptr->Result.pvIes == NULL) && ies_local_ptr)
+			cdf_mem_free(ies_local_ptr);
+
+		csr_free_scan_result_entry(pMac, scan_res_ptr);
+		return CDF_STATUS_E_RESOURCES;
+	}
+	csr_scan_add_result(pMac, scan_res_ptr, ies_local_ptr, session_id);
+	return CDF_STATUS_SUCCESS;
+}
+#endif
+
+/**
+ * csr_get_bssdescr_from_scan_handle() - This function to extract
+ *                                       first bss description from scan handle
+ * @result_handle: an object for the result.
+ *
+ * This function is written to extract first bss from scan handle.
+ *
+ * Return: first bss descriptor from the scan handle.
+ */
+tSirBssDescription*
+csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle,
+				tSirBssDescription *bss_descr)
+{
+	tListElem *first_element = NULL;
+	tCsrScanResult *scan_result = NULL;
+	tScanResultList *bss_list = (tScanResultList *)result_handle;
+
+	if (NULL == bss_list) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+				FL("Empty bss_list"));
+		return NULL;
+	}
+	if (csr_ll_is_list_empty(&bss_list->List, LL_ACCESS_NOLOCK)) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+				FL("bss_list->List is empty"));
+		cdf_mem_free(bss_list);
+		return NULL;
+	}
+	first_element = csr_ll_peek_head(&bss_list->List, LL_ACCESS_NOLOCK);
+	if (first_element) {
+		scan_result = GET_BASE_ADDR(first_element,
+				tCsrScanResult,
+				Link);
+		cdf_mem_copy(bss_descr,
+				&scan_result->Result.BssDescriptor,
+				sizeof(tSirBssDescription));
+	}
+	return bss_descr;
+}
+
+/**
+ * scan_active_list_cmd_timeout_handle() - To handle scan active command timeout
+ * @userData: scan context
+ *
+ * This routine is to handle scan active command timeout
+ *
+ * Return: None
+ */
+void csr_scan_active_list_timeout_handle(void *userData)
+{
+	tSmeCmd *scan_cmd = (tSmeCmd *) userData;
+	tHalHandle *hal_ctx = cds_get_context(CDF_MODULE_ID_PE);
+	tpAniSirGlobal mac_ctx;
+	uint16_t scan_id;
+	tSirSmeScanAbortReq *msg;
+	uint16_t msg_len;
+	CDF_STATUS status = CDF_STATUS_SUCCESS;
+
+	if (scan_cmd == NULL) {
+		CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+			FL("Scan Timeout: Scan command is NULL"));
+		return;
+	}
+	mac_ctx = PMAC_STRUCT(hal_ctx);
+	scan_id = scan_cmd->u.scanCmd.scanID;
+	sms_log(mac_ctx, LOGE,
+		FL("Scan Timeout:Sending abort to Firmware ID %d session %d "),
+		scan_id, scan_cmd->sessionId);
+	msg_len = (uint16_t)(sizeof(tSirSmeScanAbortReq));
+	msg = cdf_mem_malloc(msg_len);
+	if (NULL == msg) {
+		sms_log(mac_ctx, LOGE,
+			FL("Failed to alloc memory for SmeScanAbortReq"));
+		return;
+	}
+	cdf_mem_zero((void *)msg, msg_len);
+	msg->type = eWNI_SME_SCAN_ABORT_IND;
+	msg->msgLen = msg_len;
+	msg->sessionId = scan_cmd->sessionId;
+	msg->scan_id = scan_id;
+	status = cds_send_mb_message_to_mac(msg);
+	if (!CDF_IS_STATUS_SUCCESS(status)) {
+		sms_log(mac_ctx, LOGE,
+			FL(" Failed to post message to LIM"));
+		cdf_mem_free(msg);
+	}
+	csr_release_scan_command(mac_ctx, scan_cmd, eCSR_SCAN_FAILURE);
+	return;
+}