wlan: LFR2.0 Host Driver Changes

Master Gerrit for WLAN_FEATURE_ROAM_SCAN_OFFLOAD.
Includes all the Host Driver Changes.

Change-Id: I1c7adb30b24b49c6f2b5c3de3394831812b1c6d0
CRs-Fixed: 460568
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 2aaff05..6edbd9a 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -825,6 +825,13 @@
 #define CFG_OKC_FEATURE_ENABLED_DEFAULT                    (1)
 #endif
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define CFG_ROAM_SCAN_OFFLOAD_ENABLED                       "gRoamScanOffloadEnabled"
+#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN                   (0)
+#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX                   (1)
+#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT               (1)
+#endif
+
 #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME                "PktClassificationBasis" // DSCP or 802.1Q
 #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN                  (0)
 #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX                  (1)
@@ -1907,6 +1914,9 @@
 #ifdef FEATURE_WLAN_OKC
    v_BOOL_t                     isOkcIniFeatureEnabled;
 #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+   v_BOOL_t                     isRoamOffloadScanEnabled;
+#endif
    hdd_wmm_classification_t     PktClassificationBasis; // DSCP or 802.1Q
    v_BOOL_t                     bImplicitQosEnabled;
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 15e9a65..5e1baaf 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -181,6 +181,13 @@
     sme_UpdateEnableSSR((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->enableSSR);
 }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+static void cbNotifyUpdateRoamScanOffloadEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId)
+{
+    sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
+}
+#endif
+
 REG_TABLE_ENTRY g_registry_table[] =
 {
    REG_VARIABLE( CFG_RTS_THRESHOLD_NAME, WLAN_PARAM_Integer,
@@ -1083,7 +1090,15 @@
                  CFG_OKC_FEATURE_ENABLED_MAX,
                  cbNotifySetOkcFeatureEnabled, 0 ),
 #endif
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+   REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_OFFLOAD_ENABLED, WLAN_PARAM_Integer,
+                         hdd_config_t, isRoamOffloadScanEnabled,
+                         VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+                         CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT,
+                         CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN,
+                         CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX,
+                         cbNotifyUpdateRoamScanOffloadEnabled, 0),
+#endif
    REG_VARIABLE( CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME , WLAN_PARAM_Integer,
                  hdd_config_t, PktClassificationBasis,
                  VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -3835,7 +3850,9 @@
    smeConfig.csrConfig.nImmediateRoamRssiDiff = pConfig->nImmediateRoamRssiDiff;
    smeConfig.csrConfig.isWESModeEnabled = pConfig->isWESModeEnabled;
 #endif
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+   smeConfig.csrConfig.isRoamOffloadScanEnabled = pConfig->isRoamOffloadScanEnabled;
+#endif
 #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
    smeConfig.csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold;
    smeConfig.csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold;
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 868f9e6..936598a 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -5178,6 +5178,15 @@
 
 #endif //WLAN_BTAMP_FEATURE
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+   if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
+   {
+      hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
+      pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
+      sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
+                       pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
+   }
+#endif
 #ifdef FEATURE_WLAN_SCAN_PNO
    /*SME must send channel update configuration to RIVA*/
    sme_UpdateChannelConfig(pHddCtx->hHal); 
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index 9887ac4..357c134 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -331,6 +331,20 @@
     tLimScanResultNode
            *gLimCachedScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS];
 
+    /// This indicates total length of 'matched' scan results
+    tANI_U16   gLimMlmLfrScanResultLength;
+
+    /// This indicates total length of 'cached' scan results
+    tANI_U16   gLimSmeLfrScanResultLength;
+
+    /**
+     * Hash table definition for storing LFR SCAN results
+     * This is the placed holder for roaming candidates as forwarded
+     * by FW
+     */
+    tLimScanResultNode
+        *gLimCachedLfrScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS];
+
     /// Place holder for current channel ID
     /// being scanned during background scanning
     tANI_U32   gLimBackgroundScanChannelId;
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index eb0e3c7..4fead96 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -763,6 +763,8 @@
 #define SIR_BG_SCAN_PURGE_RESUTLS                      0x80
 #define SIR_BG_SCAN_RETURN_FRESH_RESULTS               0x01
 #define SIR_SCAN_MAX_NUM_SSID                          0x09 
+#define SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS          0x02
+#define SIR_BG_SCAN_PURGE_LFR_RESULTS                  0x40
 
 /// Definition for scan request
 typedef struct sSirSmeScanReq
@@ -3411,6 +3413,18 @@
 #define SIR_PNO_24G_DEFAULT_CH     1
 #define SIR_PNO_5G_DEFAULT_CH      36
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define SIR_ROAM_MAX_CHANNELS            NUM_RF_CHANNELS
+#define SIR_ROAM_SCAN_MAX_PB_REQ_SIZE    450
+#define CHANNEL_LIST_STATIC                   1 /* Occupied channel list remains static */
+#define CHANNEL_LIST_DYNAMIC_INIT             2 /* Occupied channel list can be learnt after init */
+#define CHANNEL_LIST_DYNAMIC_FLUSH            3 /* Occupied channel list can be learnt after flush */
+#define CHANNEL_LIST_DYNAMIC_UPDATE           4 /* Occupied channel list can be learnt after update */
+#define SIR_ROAM_SCAN_24G_DEFAULT_CH     1
+#define SIR_ROAM_SCAN_5G_DEFAULT_CH      36
+#define SIR_ROAM_SCAN_RESERVED_BYTES     64
+#endif
+
 typedef enum
 {
    SIR_PNO_MODE_IMMEDIATE,
@@ -3457,6 +3471,53 @@
   tANI_U8   p5GProbeTemplate[SIR_PNO_MAX_PB_REQ_SIZE]; 
 } tSirPNOScanReq, *tpSirPNOScanReq;
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+typedef struct
+{
+  tSirMacSSid ssId;
+  tANI_U8     currAPbssid[WNI_CFG_BSSID_LEN];
+  tANI_U32    authentication;
+  tANI_U8     encryption;
+  tANI_U8     mcencryption;
+  tANI_U8     ChannelCount;
+  tANI_U8     ChannelCache[SIR_ROAM_MAX_CHANNELS];
+
+} tSirRoamNetworkType;
+
+typedef struct SirMobilityDomainInfo
+{
+  tANI_U8 mdiePresent;
+  tANI_U16 mobilityDomain;
+} tSirMobilityDomainInfo;
+
+typedef struct sSirRoamOffloadScanReq
+{
+  eAniBoolean RoamScanOffloadEnabled;
+  tANI_S8     LookupThreshold;
+  tANI_U8     RoamRssiDiff;
+  tANI_U8     ChannelCacheType;
+  tANI_U8     Command;
+  tANI_U8     StartScanReason;
+  tANI_U16    NeighborScanTimerPeriod;
+  tANI_U16    NeighborRoamScanRefreshPeriod;
+  tANI_U16    NeighborScanChannelMinTime;
+  tANI_U16    NeighborScanChannelMaxTime;
+  tANI_U16    EmptyRefreshScanPeriod;
+  tANI_U8     ValidChannelCount;
+  tANI_U8     ValidChannelList[SIR_ROAM_MAX_CHANNELS];
+  eAniBoolean IsCCXEnabled;
+  tANI_U16  us24GProbeTemplateLen;
+  tANI_U8   p24GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE];
+  tANI_U16  us5GProbeTemplateLen;
+  tANI_U8   p5GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE];
+  tANI_U8   ReservedBytes[SIR_ROAM_SCAN_RESERVED_BYTES]; /*This is to add any additional data in future
+                                                           without changing the interface params on Host
+                                                           and firmware.*/
+  tSirRoamNetworkType ConnectedNetwork;
+  tSirMobilityDomainInfo MDID;
+} tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq;
+#endif
+
 typedef struct sSirSetRSSIFilterReq
 {
   tANI_U8     rssiThreshold;
@@ -4003,6 +4064,13 @@
     tANI_U16       length;
     tSirMacAddr    bssId;
 } tSirResetAPCapsChange, *tpSirResetAPCapsChange;
+/// Definition for Candidate found indication from FW
+typedef struct sSirSmeCandidateFoundInd
+{
+    tANI_U16            messageType; // eWNI_SME_CANDIDATE_FOUND_IND
+    tANI_U16            length;
+    tANI_U8             sessionId;  // Session Identifier
+} tSirSmeCandidateFoundInd, *tpSirSmeCandidateFoundInd;
 
 #ifdef WLAN_FEATURE_11W
 typedef struct sSirWlanExcludeUnencryptParam
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index d5fbd18..76655d4 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -371,7 +371,7 @@
 #ifdef WLAN_FEATURE_GTK_OFFLOAD
     eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP,
 #endif // WLAN_FEATURE_GTK_OFFLOAD
-
+    eWNI_SME_CANDIDATE_FOUND_IND, //ROAM candidate indication from FW
     eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 5f35725..43d9e1b 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -93,7 +93,10 @@
    SAP32STA = 5,
    TDLS = 6,
    P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7,
-   WLANACTIVE_OFFLOAD = 8
+   WLANACTIVE_OFFLOAD = 8,
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+   WLAN_ROAM_SCAN_OFFLOAD = 23,
+#endif
    //MAX_FEATURE_SUPPORTED = 128
 } placeHolderInCapBitmap;
 
@@ -553,7 +556,9 @@
 #define SIR_HAL_TDLS_LINK_ESTABLISH        (SIR_HAL_ITC_MSG_TYPES_BEGIN + 189)
 #define SIR_HAL_TDLS_LINK_TEARDOWN         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 190)
 #endif
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define SIR_HAL_START_ROAM_CANDIDATE_LOOKUP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 191)
+#endif
 #define SIR_HAL_GET_ROAM_RSSI_REQ          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 193)
 #define SIR_HAL_GET_ROAM_RSSI_RSP          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 194)
 
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index fde0fef..f186f20 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -119,6 +119,14 @@
     palZeroMemory(pMac->hHdd, pMac->lim.gLimCachedScanHashTable,
                     sizeof(pMac->lim.gLimCachedScanHashTable));
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+
+    pMac->lim.gLimMlmLfrScanResultLength = 0;
+    pMac->lim.gLimSmeLfrScanResultLength = 0;
+
+    palZeroMemory(pMac->hHdd, pMac->lim.gLimCachedLfrScanHashTable,
+                    sizeof(pMac->lim.gLimCachedLfrScanHashTable));
+#endif
     pMac->lim.gLimBackgroundScanChannelId = 0;
     pMac->lim.gLimBackgroundScanStarted = 0;
     pMac->lim.gLimRestoreCBNumScanInterval = LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT;
@@ -642,6 +650,9 @@
       // By default return unique scan results
       pMac->lim.gLimReturnUniqueResults = true;
       pMac->lim.gLimSmeScanResultLength = 0;
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+      pMac->lim.gLimSmeLfrScanResultLength = 0;
+#endif
    }
    else
    {
@@ -2154,6 +2165,12 @@
         {
             return eMGMT_DROP_NO_DROP;
         }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        else if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo))
+        {
+            return eMGMT_DROP_NO_DROP;
+        }
+#endif
         else if (WDA_IS_RX_IN_SCAN(pRxPacketInfo))
         {
             return eMGMT_DROP_SCAN_MODE_FRAME;
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 7b25aeb..f21a75e 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -549,7 +549,34 @@
     limLog( pMac, LOG4, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"),
             fc.protVer, fc.type, fc.subType, WDA_GET_RX_MAC_RATE_IDX(pRxPacketInfo));
    
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if ( WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo))
+    {
+        limLog( pMac, LOG2, FL("Notify SME with candidate ind"));
+        //send a session 0 for now - TBD
+        limSendSmeCandidateFoundInd(pMac, 0);
+        goto end;
+    }
+    if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))
+    {
+        if (fc.subType == SIR_MAC_MGMT_BEACON)
+        {
+            limLog( pMac, LOG2, FL("Save this beacon in LFR cache"));
+            __limHandleBeacon(pMac, limMsg, NULL);
+        }
+        else if (fc.subType == SIR_MAC_MGMT_PROBE_RSP)
+        {
+            limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache"));
+            limProcessProbeRspFrameNoSession(pMac, pRxPacketInfo);
+        }
+        else
+        {
+            limLog( pMac, LOGE, FL("Wrong frame Type %d, Subtype %d for LFR"),
+                    fc.type, fc.subType);
+        }
+        goto end;
+    }
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
 #ifdef FEATURE_WLAN_CCX
     if (fc.type == SIR_MAC_DATA_FRAME && isFrmFt) 
     {
@@ -808,6 +835,9 @@
 
     } // switch (fc.type)
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+end:
+#endif
     limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr) ;
     return;
 } /*** end limHandle80211Frames() ***/
diff --git a/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c b/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c
index af77b3d..44f180a 100644
--- a/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c
@@ -357,11 +357,19 @@
              WDA_GET_RX_MPDU_LEN(pRxPacketInfo));
     limPrintMacAddr(pMac, pHdr->sa, LOG2);
 
-    if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) ||
+          WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)))
     {
-        palFreeMemory(pMac->hHdd, pProbeRsp);
-        return;
+#endif
+       if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS)
+       {
+          palFreeMemory(pMac->hHdd, pProbeRsp);
+          return;
+       }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
     }
+#endif
      // Validate IE information before processing Probe Response Frame
     if (limValidateIEInformationInProbeRspFrame(pRxPacketInfo) != eSIR_SUCCESS)
     {
@@ -376,9 +384,30 @@
      *   - eLIM_MLM_BSS_STARTED_STATE
      *  Hence, expect Probe Response only when
      *   1. STA is in scan mode waiting for Beacon/Probe response 
+     *   2. LFR logic in FW sends up candidate frames
      *  
      *  Ignore Probe Response frame in all other states
      */
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))
+    {
+        frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+        // Get pointer to Probe Response frame body
+        pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+        if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE)
+        {
+            limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d\n"), frameLen);
+            palFreeMemory(pMac->hHdd, pProbeRsp);
+            return;
+        }
+        limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache"));
+        limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo,
+                                     eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE);
+    }
+    else
+#endif
     if( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) ||
         (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)  ||     //mlm state check should be global - 18th oct
         (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) )
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index b2885d0..8e06ea0 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -384,6 +384,9 @@
         /// By default return unique scan results
         pMac->lim.gLimReturnUniqueResults = true;
         pMac->lim.gLimSmeScanResultLength = 0;
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        pMac->lim.gLimSmeLfrScanResultLength = 0;
+#endif
 
         if (((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd)
         {
@@ -1326,24 +1329,58 @@
             tANI_U16    scanRspLen = sizeof(tSirSmeScanRsp);
 
             pMac->lim.gLimRspReqd = false;
-
-            if (pMac->lim.gLimSmeScanResultLength == 0)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if (pScanReq->returnFreshResults & SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS)
             {
-                limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pScanReq->sessionId, pScanReq->transactionId);
+                pMac->lim.gLimSmeLfrScanResultLength = pMac->lim.gLimMlmLfrScanResultLength;
+                if (pMac->lim.gLimSmeLfrScanResultLength == 0)
+                {
+                    limSendSmeLfrScanRsp(pMac, scanRspLen,
+                                         eSIR_SME_SUCCESS,
+                                         pScanReq->sessionId,
+                                         pScanReq->transactionId);
+                }
+                else
+                {
+                    scanRspLen = sizeof(tSirSmeScanRsp) +
+                                 pMac->lim.gLimSmeLfrScanResultLength -
+                                 sizeof(tSirBssDescription);
+                    limSendSmeLfrScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS,
+                               pScanReq->sessionId, pScanReq->transactionId);
+                }
             }
             else
             {
-                scanRspLen = sizeof(tSirSmeScanRsp) +
-                             pMac->lim.gLimSmeScanResultLength -
-                             sizeof(tSirBssDescription);
-                limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pScanReq->sessionId, pScanReq->transactionId);
+#endif
+               if (pMac->lim.gLimSmeScanResultLength == 0)
+               {
+                  limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS,
+                          pScanReq->sessionId, pScanReq->transactionId);
+               }
+               else
+               {
+                  scanRspLen = sizeof(tSirSmeScanRsp) +
+                               pMac->lim.gLimSmeScanResultLength -
+                               sizeof(tSirBssDescription);
+                  limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS,
+                                  pScanReq->sessionId, pScanReq->transactionId);
+               }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
             }
+#endif
 
             if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS)
             {
                 // Discard previously cached scan results
                 limReInitScanResults(pMac);
             }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_LFR_RESULTS)
+            {
+                // Discard previously cached scan results
+                limReInitLfrScanResults(pMac);
+            }
+#endif
 
         } // if (pMac->lim.gLimRspReqd)
     } // else ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ...
diff --git a/CORE/MAC/src/pe/lim/limScanResultUtils.c b/CORE/MAC/src/pe/lim/limScanResultUtils.c
index bd3edf8..4bc027e 100644
--- a/CORE/MAC/src/pe/lim/limScanResultUtils.c
+++ b/CORE/MAC/src/pe/lim/limScanResultUtils.c
@@ -396,12 +396,19 @@
      * a SSID (if it is also set). Ignore the other BSS in that case.
      */
 
-    if ((pMac->lim.gpLimMlmScanReq) && (((fScanning) && ( pMac->lim.gLimReturnAfterFirstMatch & 0x01 ) 
-        && (pMac->lim.gpLimMlmScanReq->numSsid) &&
-                   !limIsScanRequestedSSID(pMac, &pBPR->ssId))
-                   ||  (!fFound && (pMac->lim.gpLimMlmScanReq && pMac->lim.gpLimMlmScanReq->bssId) &&
-                   !palEqualMemory(pMac->hHdd, bssid, &pMac->lim.gpLimMlmScanReq->bssId, 6)))
-                   )
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)))
+    {
+#endif
+      if ((pMac->lim.gpLimMlmScanReq) &&
+         (((fScanning) &&
+           ( pMac->lim.gLimReturnAfterFirstMatch & 0x01 ) &&
+           (pMac->lim.gpLimMlmScanReq->numSsid) &&
+           !limIsScanRequestedSSID(pMac, &pBPR->ssId)) ||
+          (!fFound && (pMac->lim.gpLimMlmScanReq &&
+                       pMac->lim.gpLimMlmScanReq->bssId) &&
+           !palEqualMemory(pMac->hHdd, bssid,
+                           &pMac->lim.gpLimMlmScanReq->bssId, 6))))
     {
         /**
          * Received SSID does not match with
@@ -411,6 +418,9 @@
 
         return;
     }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    }
+#endif
 
     /* There is no point in caching & reporting the scan results for APs
      * which are in the process of switching the channel. So, we are not
@@ -501,8 +511,38 @@
     /**
      * Depending on whether to store unique or all
      * scan results, pass hash update/add parameter
+     * For LFR candidates just add them on it's own cache
      */
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))
+    {
+       limLog(pMac, LOG2, FL(" pHdr->addr1:%02x:%02x:%02x:%02x:%02x:%02x\n"),
+              pHdr->addr1[0],
+              pHdr->addr1[1],
+              pHdr->addr1[2],
+              pHdr->addr1[3],
+              pHdr->addr1[4],
+              pHdr->addr1[5]);
+       limLog(pMac, LOG2, FL(" pHdr->addr2:%02x:%02x:%02x:%02x:%02x:%02x\n"),
+              pHdr->addr2[0],
+              pHdr->addr2[1],
+              pHdr->addr2[2],
+              pHdr->addr2[3],
+              pHdr->addr2[4],
+              pHdr->addr2[5]);
+       limLog(pMac, LOG2, FL(" pHdr->addr3:%02x:%02x:%02x:%02x:%02x:%02x\n"),
+              pHdr->addr3[0],
+              pHdr->addr3[1],
+              pHdr->addr3[2],
+              pHdr->addr3[3],
+              pHdr->addr3[4],
+              pHdr->addr3[5]);
+       limLog( pMac, LOG2, FL("Save this entry in LFR cache"));
+       status = limLookupNaddLfrHashEntry(pMac, pBssDescr, LIM_HASH_ADD, dontUpdateAll);
+    }
+    else
+#endif
     //If it is not scanning, only save unique results
     if (pMac->lim.gLimReturnUniqueResults || (!fScanning))
     {
@@ -814,6 +854,225 @@
 } /****** end limDeleteHashEntry() ******/
 
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ * limInitLfrHashTable()
+ *
+ *FUNCTION:
+ * This function is called upon receiving SME_START_REQ
+ * to initialize global cached Lfr scan hash table
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * NA
+ *
+ * @param  pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void
+limInitLfrHashTable(tpAniSirGlobal pMac)
+{
+    tANI_U16 i;
+    for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++)
+        pMac->lim.gLimCachedLfrScanHashTable[i] = NULL;
+} /****** end limInitLfrHashTable() ******/
+
+
+
+/**
+ * limLookupNaddLfrHashEntry()
+ *
+ *FUNCTION:
+ * This function is called upon receiving a Beacon or
+ * Probe Response frame during Lfr scan phase from FW to store
+ * received BSS description into Lfr scan result hash table.
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * NA
+ *
+ * @param  pMac - Pointer to Global MAC structure
+ * @param  pBssDescr - Pointer to BSS description to be
+ *         added to the Lfr scan result hash table.
+ * @param  action - Indicates action to be performed
+ *         when same BSS description is found. This is
+ *         dependent on whether unique scan result to
+ *         be stored or not.
+ *
+ * @return None
+ */
+
+eHalStatus
+limLookupNaddLfrHashEntry(tpAniSirGlobal pMac,
+                          tLimScanResultNode *pBssDescr, tANI_U8 action,
+                          tANI_U8 dontUpdateAll)
+{
+    tANI_U8                  index, ssidLen = 0;
+    tLimScanResultNode *ptemp, *pprev;
+    tSirMacCapabilityInfo *pSirCap, *pSirCapTemp;
+    int idx, len;
+    tANI_U8 *pbIe;
+    tANI_S8  rssi = 0;
+
+    index = limScanHashFunction(pBssDescr->bssDescription.bssId);
+    ptemp = pMac->lim.gLimCachedLfrScanHashTable[index];
+
+    //ieFields start with TLV of SSID IE
+    ssidLen = * ((tANI_U8 *) &pBssDescr->bssDescription.ieFields + 1);
+    pSirCap = (tSirMacCapabilityInfo *)&pBssDescr->bssDescription.capabilityInfo;
+
+    for (pprev = ptemp; ptemp; pprev = ptemp, ptemp = ptemp->next)
+    {
+        //For infrastructure, check BSSID and SSID. For IBSS, check more
+        pSirCapTemp = (tSirMacCapabilityInfo *)&ptemp->bssDescription.capabilityInfo;
+        if((pSirCapTemp->ess == pSirCap->ess) && //matching ESS type first
+            (palEqualMemory( pMac->hHdd,(tANI_U8 *) pBssDescr->bssDescription.bssId,
+                      (tANI_U8 *) ptemp->bssDescription.bssId,
+                      sizeof(tSirMacAddr))) &&   //matching BSSID
+            (pBssDescr->bssDescription.channelId ==
+                                      ptemp->bssDescription.channelId) &&
+            palEqualMemory( pMac->hHdd,((tANI_U8 *) &pBssDescr->bssDescription.ieFields + 1),
+                           ((tANI_U8 *) &ptemp->bssDescription.ieFields + 1),
+                           (tANI_U8) (ssidLen + 1)) &&
+            ((pSirCapTemp->ess) || //we are done for infrastructure
+            //For IBSS, nwType and channelId
+            (((pBssDescr->bssDescription.nwType ==
+                                         ptemp->bssDescription.nwType) &&
+            (pBssDescr->bssDescription.channelId ==
+                                      ptemp->bssDescription.channelId))))
+        )
+        {
+            // Found the same BSS description
+            if (action == LIM_HASH_UPDATE)
+            {
+                if(dontUpdateAll)
+                {
+                   rssi = ptemp->bssDescription.rssi;
+                }
+
+                if(pBssDescr->bssDescription.fProbeRsp != ptemp->bssDescription.fProbeRsp)
+                {
+                    //We get a different, save the old frame WSC IE if it is there
+                    idx = 0;
+                    len = ptemp->bssDescription.length - sizeof(tSirBssDescription) +
+                       sizeof(tANI_U16) + sizeof(tANI_U32) - DOT11F_IE_WSCPROBERES_MIN_LEN - 2;
+                    pbIe = (tANI_U8 *)ptemp->bssDescription.ieFields;
+                    //Save WPS IE if it exists
+                    pBssDescr->bssDescription.WscIeLen = 0;
+                    while(idx < len)
+                    {
+                        if((DOT11F_EID_WSCPROBERES == pbIe[0]) &&
+                           (0x00 == pbIe[2]) && (0x50 == pbIe[3]) &&
+                           (0xf2 == pbIe[4]) && (0x04 == pbIe[5]))
+                        {
+                            //Found it
+                            if((DOT11F_IE_WSCPROBERES_MAX_LEN - 2) >= pbIe[1])
+                            {
+                                palCopyMemory(pMac->hHdd, pBssDescr->bssDescription.WscIeProbeRsp,
+                                   pbIe, pbIe[1] + 2);
+                                pBssDescr->bssDescription.WscIeLen = pbIe[1] + 2;
+                            }
+                            break;
+                        }
+                        idx += pbIe[1] + 2;
+                        pbIe += pbIe[1] + 2;
+                    }
+                }
+
+
+                if(NULL != pMac->lim.gpLimMlmScanReq)
+                {
+                   if((pMac->lim.gpLimMlmScanReq->numSsid)&&
+                      ( limIsNullSsid((tSirMacSSid *)((tANI_U8 *)
+                      &pBssDescr->bssDescription.ieFields + 1))))
+                      return eHAL_STATUS_FAILURE;
+                }
+
+                // Delete this entry
+                if (ptemp == pMac->lim.gLimCachedLfrScanHashTable[index])
+                    pprev = pMac->lim.gLimCachedLfrScanHashTable[index] = ptemp->next;
+                else
+                    pprev->next = ptemp->next;
+
+                pMac->lim.gLimMlmLfrScanResultLength -=
+                    ptemp->bssDescription.length + sizeof(tANI_U16);
+
+                palFreeMemory( pMac->hHdd, (tANI_U8 *) ptemp);
+            }
+            break;
+        }
+    }
+
+    //for now, only rssi, we can add more if needed
+    if ((action == LIM_HASH_UPDATE) && dontUpdateAll && rssi)
+    {
+        pBssDescr->bssDescription.rssi = rssi;
+    }
+
+    // Add this BSS description at same index
+    if (pprev == pMac->lim.gLimCachedLfrScanHashTable[index])
+    {
+        pBssDescr->next = pMac->lim.gLimCachedLfrScanHashTable[index];
+        pMac->lim.gLimCachedLfrScanHashTable[index] = pBssDescr;
+    }
+    else
+    {
+        pBssDescr->next = pprev->next;
+        pprev->next = pBssDescr;
+    }
+    pMac->lim.gLimMlmLfrScanResultLength +=
+        pBssDescr->bssDescription.length + sizeof(tANI_U16);
+
+    PELOG2(limLog(pMac, LOG2, FL("Added new BSS description size %d TOT %d BSS id\n"),
+           pBssDescr->bssDescription.length,
+           pMac->lim.gLimMlmLfrScanResultLength);
+    limPrintMacAddr(pMac, pBssDescr->bssDescription.bssId, LOG2);)
+
+    //
+    // TODO: IF applicable, do we need to send:
+    // Mesg - eWNI_SME_WM_STATUS_CHANGE_NTF
+    // Status change code - eSIR_SME_CB_LEGACY_BSS_FOUND_BY_AP
+    //
+    return eHAL_STATUS_SUCCESS;
+}
+
+
+
+/**
+ * limDeleteLfrHashEntry()
+ *
+ *FUNCTION:
+ * This function is called upon to delete
+ * a BSS description from LFR scan result hash table.
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * Yet to find the utility of the function
+ *
+ * @param  pBssDescr - Pointer to BSS description to be
+ *         deleted from the LFR scan result hash table.
+ *
+ * @return None
+ */
+
+void    limDeleteLfrHashEntry(tLimScanResultNode *pBssDescr)
+{
+} /****** end limDeleteLfrHashEntry() ******/
+
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
 
 /**
  * limCopyScanResult()
@@ -938,3 +1197,82 @@
     pMac->lim.gLimMlmScanResultLength = 0;
 
 } /****** end limReInitScanResults() ******/
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ * limDeleteCachedLfrScanResults()
+ *
+ *FUNCTION:
+ * This function is called by limProcessSmeMessages() upon receiving
+ * SME_SCAN_REQ with flush scan result flag set for LFR.
+ *
+ *LOGIC:
+ * This function traverses the scan list stored in lfr scan hash
+ * table and deletes the entries if any
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * NA
+ *
+ * @param  pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void
+limDeleteCachedLfrScanResults(tpAniSirGlobal pMac)
+{
+    tLimScanResultNode    *pNode, *pNextNode;
+    tANI_U16 i;
+    for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++)
+    {
+        if ((pNode = pMac->lim.gLimCachedLfrScanHashTable[i]) != NULL)
+        {
+            while (pNode)
+            {
+                pNextNode = pNode->next;
+
+                // Delete the current node
+                palFreeMemory( pMac->hHdd, (tANI_U8 *) pNode);
+
+                pNode = pNextNode;
+            }
+        }
+    }
+
+    pMac->lim.gLimSmeLfrScanResultLength = 0;
+} /****** end limDeleteCachedLfrScanResults() ******/
+
+
+
+/**
+ * limReInitLfrScanResults()
+ *
+ *FUNCTION:
+ * This function is called delete exisiting scan results
+ * and initialize the lfr scan hash table
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * NA
+ *
+ * @param  pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void
+limReInitLfrScanResults(tpAniSirGlobal pMac)
+{
+    limDeleteCachedLfrScanResults(pMac);
+    limInitLfrHashTable(pMac);
+
+    // !!LAC - need to clear out the global scan result length
+    // since the list was just purged from the hash table.
+    pMac->lim.gLimMlmLfrScanResultLength = 0;
+
+} /****** end limReInitLfrScanResults() ******/
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
diff --git a/CORE/MAC/src/pe/lim/limScanResultUtils.h b/CORE/MAC/src/pe/lim/limScanResultUtils.h
index 9ad88bf..fc17886 100644
--- a/CORE/MAC/src/pe/lim/limScanResultUtils.h
+++ b/CORE/MAC/src/pe/lim/limScanResultUtils.h
@@ -39,6 +39,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+
 /*
  * Airgo Networks, Inc proprietary. All rights reserved.
  * This file limScanResultUtils.h contains the utility definitions
@@ -65,6 +66,14 @@
 void    limRestorePreScanState(tpAniSirGlobal);
 void    limCopyScanResult(tpAniSirGlobal, tANI_U8 *);
 void    limReInitScanResults(tpAniSirGlobal);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+void    limInitLfrHashTable(tpAniSirGlobal);
+eHalStatus
+   limLookupNaddLfrHashEntry(tpAniSirGlobal, tLimScanResultNode *, tANI_U8, tANI_U8);
+void    limDeleteLfrHashEntry(tLimScanResultNode *);
+void    limDeleteCachedLfrScanResults(tpAniSirGlobal);
+void    limReInitLfrScanResults(tpAniSirGlobal);
+#endif
 tANI_U32 limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal);
 void    limCheckAndAddBssDescription(tpAniSirGlobal, tpSirProbeRespBeacon, tANI_U8 *, tANI_BOOLEAN, tANI_U8);
 #if defined WLAN_FEATURE_VOWIFI
diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
index c907ef7..d91c595 100644
--- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
@@ -772,6 +772,169 @@
 
 } /*** end limSendSmeScanRsp() ***/
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ * limSendSmeLfrScanRsp()
+ *
+ *FUNCTION:
+ * This function is called by limProcessSmeReqMessages() to send
+ * eWNI_SME_SCAN_RSP message to applications above MAC Software
+ * only for sending up the roam candidates.
+ *
+ *PARAMS:
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * NA
+ *
+ * @param pMac         Pointer to Global MAC structure
+ * @param length       Indicates length of message
+ * @param resultCode   Indicates the result of previously issued
+ *                     eWNI_SME_SCAN_REQ message
+ *
+ * @return None
+ */
+
+void
+limSendSmeLfrScanRsp(tpAniSirGlobal pMac, tANI_U16 length,
+                     tSirResultCodes resultCode,tANI_U8  smesessionId,tANI_U16 smetranscationId)
+{
+    tSirMsgQ              mmhMsg;
+    tpSirSmeScanRsp       pSirSmeScanRsp=NULL;
+    tLimScanResultNode    *ptemp = NULL;
+    tANI_U16              msgLen, allocLength, curMsgLen = 0;
+    tANI_U16              i, bssCount;
+    tANI_U8               *pbBuf;
+    tSirBssDescription    *pDesc;
+
+    PELOG1(limLog(pMac, LOG1,
+       FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s\n"),
+       length, limResultCodeStr(resultCode));)
+
+    if (resultCode != eSIR_SME_SUCCESS)
+    {
+        limPostSmeScanRspMessage(pMac, length, resultCode,smesessionId,smetranscationId);
+        return;
+    }
+
+    mmhMsg.type = eWNI_SME_SCAN_RSP;
+    i = 0;
+    bssCount = 0;
+    msgLen = 0;
+    allocLength = LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED * LIM_SIZE_OF_EACH_BSS;
+    if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+                                (void **)&pSirSmeScanRsp, allocLength))
+    {
+        // Log error
+        limLog(pMac, LOGP,
+                   FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n"));
+
+        return;
+    }
+    for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++)
+    {
+        //when ptemp is not NULL it is a left over
+        ptemp = pMac->lim.gLimCachedLfrScanHashTable[i];
+        while(ptemp)
+        {
+            pbBuf = ((tANI_U8 *)pSirSmeScanRsp) + msgLen;
+            if(0 == bssCount)
+            {
+                msgLen = sizeof(tSirSmeScanRsp) -
+                           sizeof(tSirBssDescription) +
+                           ptemp->bssDescription.length +
+                           sizeof(ptemp->bssDescription.length);
+                pDesc = pSirSmeScanRsp->bssDescription;
+            }
+            else
+            {
+                msgLen += ptemp->bssDescription.length +
+                          sizeof(ptemp->bssDescription.length);
+                pDesc = (tSirBssDescription *)pbBuf;
+            }
+            if ( (allocLength < msgLen) ||
+                 (LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED <= bssCount++) )
+            {
+                pSirSmeScanRsp->statusCode  =
+                    eSIR_SME_MORE_SCAN_RESULTS_FOLLOW;
+                pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP;
+                pSirSmeScanRsp->length      = curMsgLen;
+                mmhMsg.bodyptr = pSirSmeScanRsp;
+                mmhMsg.bodyval = 0;
+                MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type));
+                limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+                if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,
+                                                   (void **)&pSirSmeScanRsp,
+                                                   allocLength))
+                {
+                    // Log error
+                    limLog(pMac, LOGP,
+                                 FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n"));
+                    return;
+                }
+                msgLen = sizeof(tSirSmeScanRsp) -
+                           sizeof(tSirBssDescription) +
+                           ptemp->bssDescription.length +
+                           sizeof(ptemp->bssDescription.length);
+                pDesc = pSirSmeScanRsp->bssDescription;
+                bssCount = 1;
+            }
+            curMsgLen = msgLen;
+
+            PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"),
+                          msgLen, ptemp->bssDescription.length);)
+            pDesc->length
+                    = ptemp->bssDescription.length;
+            palCopyMemory( pMac->hHdd, (tANI_U8 *) &pDesc->bssId,
+                              (tANI_U8 *) &ptemp->bssDescription.bssId,
+                              ptemp->bssDescription.length);
+
+            PELOG2(limLog(pMac, LOG2, FL("BssId "));
+            limPrintMacAddr(pMac, ptemp->bssDescription.bssId, LOG2);)
+
+            pSirSmeScanRsp->sessionId   = smesessionId;
+            pSirSmeScanRsp->transcationId = smetranscationId;
+
+            ptemp = ptemp->next;
+        } //while(ptemp)
+    } //for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++)
+
+    if (0 == bssCount)
+    {
+       limPostSmeScanRspMessage(pMac, length, resultCode, smesessionId, smetranscationId);
+       if (NULL != pSirSmeScanRsp)
+       {
+           palFreeMemory( pMac->hHdd, pSirSmeScanRsp);
+           pSirSmeScanRsp = NULL;
+       }
+    }
+    else
+    {
+        // send last message
+        pSirSmeScanRsp->statusCode  = eSIR_SME_SUCCESS;
+        pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP;
+        pSirSmeScanRsp->length = curMsgLen;
+
+        /* Update SME session Id and SME transcation Id */
+        pSirSmeScanRsp->sessionId   = smesessionId;
+        pSirSmeScanRsp->transcationId = smetranscationId;
+
+        mmhMsg.type = eWNI_SME_SCAN_RSP;
+        mmhMsg.bodyptr = pSirSmeScanRsp;
+        mmhMsg.bodyval = 0;
+        MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type));
+        limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+        PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS\n"));)
+    }
+
+    return;
+
+} /*** end limSendSmeLfrScanRsp() ***/
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
 
 /**
  * limPostSmeScanRspMessage()
@@ -2525,3 +2688,46 @@
 
     return;
 }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/** -----------------------------------------------------------------
+  \brief limSendSmeCandidateFoundInd() - sends
+         eWNI_SME_CANDIDATE_FOUND_IND
+
+  After receiving candidate found indication frame from FW, this
+  function sends a eWNI_SME_CANDIDATE_FOUND_IND to SME to notify
+  roam candidate(s) are available.
+
+  \param pMac - global mac structure
+  \param psessionEntry - session info
+  \return none
+  \sa
+  ----------------------------------------------------------------- */
+void
+limSendSmeCandidateFoundInd(tpAniSirGlobal pMac, tANI_U8  sessionId)
+{
+    tSirMsgQ  mmhMsg;
+    tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd;
+
+    if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+                                             (void **)&pSirSmeCandidateFoundInd,
+                                             sizeof(tSirSmeCandidateFoundInd)))
+    {
+        limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_CANDIDATE_FOUND_IND\n"));
+        return;
+    }
+
+    pSirSmeCandidateFoundInd->messageType = eWNI_SME_CANDIDATE_FOUND_IND;
+    pSirSmeCandidateFoundInd->length = sizeof(tSirSmeDisassocInd);
+
+    pSirSmeCandidateFoundInd->sessionId     =  sessionId;
+
+
+    limLog( pMac, LOGE, FL("posting candidate ind to SME"));
+    mmhMsg.type = eWNI_SME_CANDIDATE_FOUND_IND;
+    mmhMsg.bodyptr = pSirSmeCandidateFoundInd;
+    mmhMsg.bodyval = 0;
+
+    limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+
+} /*** end limSendSmeCandidateFoundInd() ***/
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h
index a2e5c47..3ef5351 100644
--- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h
+++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h
@@ -63,6 +63,9 @@
 void limSendSmeRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes, tANI_U8 , tANI_U16);
 void limSendSmeStartBssRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tpPESession,tANI_U8,tANI_U16);
 void limSendSmeScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+void limSendSmeLfrScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16);
+#endif
 void limPostSmeScanRspMessage(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8,tANI_U16); 
 void limSendSmeAuthRsp(tpAniSirGlobal, tSirResultCodes,
                        tSirMacAddr, tAniAuthType, tANI_U16,tpPESession,tANI_U8,tANI_U16);
@@ -72,8 +75,9 @@
 void limSendSmeDeauthNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U16, tANI_U16, tANI_U8, tANI_U16);
 void limSendSmeDisassocInd(tpAniSirGlobal, tpDphHashNode,tpPESession);
 void limSendSmeDeauthInd(tpAniSirGlobal, tpDphHashNode, tpPESession psessionEntry);
-
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+void limSendSmeCandidateFoundInd(tpAniSirGlobal, tANI_U8);
+#endif
 
 void limSendSmeWmStatusChangeNtf(tpAniSirGlobal, tSirSmeStatusChangeCode, tANI_U32 *, tANI_U16, tANI_U8);
 void limSendSmeSetContextRsp(tpAniSirGlobal,
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 3c0b34b..b72bbf2 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -80,6 +80,11 @@
 static const tANI_U8 abChannel[]= {36,40,44,48,52,56,60,64,100,104,108,112,116,
             120,124,128,132,136,140,149,153,157,161,165};
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+static const tANI_U8 aUnsortedChannelList[]= {52,56,60,64,100,104,108,112,116,
+            120,124,128,132,136,140,36,40,44,48,149,153,157,161,165};
+#endif
+
 //#define LIM_MAX_ACTIVE_SESSIONS 3  //defined temporarily for BT-AMP SUPPORT 
 #define SUCCESS 1                   //defined temporarily for BT-AMP
 
@@ -898,6 +903,13 @@
     /// Initialize scan result hash table
     limReInitScanResults(pMac); //sep26th review
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    /// Initialize lfr scan result hash table
+    // Could there be a problem in multisession with SAP/P2P GO, when in the
+    // middle of FW bg scan, SAP started; Again that could be a problem even on
+    // infra + SAP/P2P GO too - TBD
+    limReInitLfrScanResults(pMac);
+#endif
   
     /// Initialize number of pre-auth contexts
     pMac->lim.gLimNumPreAuthContexts = 0;
@@ -1088,6 +1100,10 @@
 
     /// Cleanup cached scan list
     limReInitScanResults(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    /// Cleanup cached scan list
+    limReInitLfrScanResults(pMac);
+#endif
 
 } /*** end limCleanupMlm() ***/
 
@@ -7309,6 +7325,11 @@
 tANI_U8 limUnmapChannel(tANI_U8 mapChannel)
 {
    if( mapChannel > 0 && mapChannel < 25 )
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+       if (IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE)
+           return aUnsortedChannelList[mapChannel -1];
+       else
+#endif
      return abChannel[mapChannel -1];
    else
      return 0;
diff --git a/CORE/MAC/src/pe/sch/schBeaconProcess.c b/CORE/MAC/src/pe/sch/schBeaconProcess.c
index ab66fa2..16a0a0a 100644
--- a/CORE/MAC/src/pe/sch/schBeaconProcess.c
+++ b/CORE/MAC/src/pe/sch/schBeaconProcess.c
@@ -38,6 +38,8 @@
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  * PERFORMANCE OF THIS SOFTWARE.
  */
+
+
 /*
  * Airgo Networks, Inc proprietary. All rights reserved.
  * This file schBeaconProcess.cc contains beacon processing related
@@ -656,7 +658,11 @@
     * 
     */
     
-    if((pAPSession = limIsApSessionActive(pMac)) != NULL)
+    if (((pAPSession = limIsApSessionActive(pMac)) != NULL)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+          && (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)))
+#endif
+    )
     {
         beaconParams.bssIdx = pAPSession->bssIdx;
         if (pAPSession->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index 61ae661..2f195cf 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -1092,6 +1092,10 @@
     tANI_BOOLEAN nRoamIntraBand;
 #endif
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    tANI_BOOLEAN isRoamOffloadScanEnabled;
+#endif
+
     tANI_U8 scanCfgAgingTime;
 
     tANI_U8   enableTxLdpc;
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index c5d0e73..cfa782e 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -105,6 +105,13 @@
 )
 #endif
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define CSR_IS_ROAM_SCAN_OFFLOAD_ENABLED( pMac ) \
+( \
+   (((pMac)->roam.configParam.isRoamOffloadScanEnabled)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \
+)
+#endif
+
 //Support for "Fast roaming" (i.e., CCX, LFR, or 802.11r.)
 #define CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15
 
@@ -166,7 +173,8 @@
     eCsrScanProbeBss, // directed probe on an entry from the candidate list - HO
     eCsrScanAbortBgScan,    //aborting a BG scan (meaning the scan is triggered by LIM timer)
     eCsrScanAbortNormalScan, //aborting a normal scan (the scan is trigger by eWNI_SME_SCAN_REQ)
-    eCsrScanP2PFindPeer
+    eCsrScanP2PFindPeer,
+    eCsrScanGetLfrResult, // get the LFR candidates from PE scan cache
 }eCsrScanReason;
 
 typedef enum
@@ -592,6 +600,9 @@
 
 #ifdef FEATURE_WLAN_LFR
     tANI_U8   isFastRoamIniFeatureEnabled;
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    tANI_U8   isRoamOffloadScanEnabled;
+#endif
 #endif
 
 #ifdef FEATURE_WLAN_CCX
@@ -1320,7 +1331,15 @@
 #ifdef FEATURE_WLAN_LFR
 //Returns whether "Legacy Fast Roaming" is enabled...or not
 tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac);
+#endif
 tANI_BOOLEAN csrIsChannelPresentInList( tANI_U8 *pChannelList, int  numChannels, tANI_U8   channel );
 VOS_STATUS csrAddToChannelListFront( tANI_U8 *pChannelList, int  numChannels, tANI_U8   channel );
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId,
+                                   csrScanCompleteCallback callback, void *pContext);
+#endif
+tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId);
 #endif
 
diff --git a/CORE/SME/inc/csrNeighborRoam.h b/CORE/SME/inc/csrNeighborRoam.h
index 1f5cb5f..289a1fd 100644
--- a/CORE/SME/inc/csrNeighborRoam.h
+++ b/CORE/SME/inc/csrNeighborRoam.h
@@ -245,6 +245,29 @@
                       tANI_U8*  pOutputChannelList,
                       int*      pMergedOutputNumOfChannels
                       );
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define ROAM_SCAN_OFFLOAD_START                     1
+#define ROAM_SCAN_OFFLOAD_STOP                      2
+#define ROAM_SCAN_OFFLOAD_RESTART                   3
+#define ROAM_SCAN_OFFLOAD_UPDATE_CFG                4
+
+#define REASON_CONNECT                              1
+#define REASON_CHANNEL_LIST_CHANGED                 2
+#define REASON_LOOKUP_THRESH_CHANGED                3
+#define REASON_DISCONNECTED                         4
+#define REASON_RSSI_DIFF_CHANGED                    5
+#define REASON_CCX_INI_CFG_CHANGED                  6
+#define REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED 7
+#define REASON_VALID_CHANNEL_LIST_CHANGED           8
+#define REASON_FLUSH_CHANNEL_LIST                   9
+#define REASON_EMPTY_SCAN_REF_PERIOD_CHANGED        10
+#define REASON_PREAUTH_FAILED_FOR_ALL               11
+#define REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW     12
+
+eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason);
+eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg);
+#endif
+
 
 #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 8762a80..f697ed3 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -2648,6 +2648,22 @@
 
 #endif
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/*--------------------------------------------------------------------------
+  \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload feaure
+  It is used at in the REG_DYNAMIC_VARIABLE macro definition of
+  gRoamScanOffloadEnabled.
+  This is a synchronous call
+  \param hHal - The handle returned by macOpen.
+  \return eHAL_STATUS_SUCCESS - SME update config successfully.
+          Other status means SME is failed to update.
+  \sa
+  --------------------------------------------------------------------------*/
+
+eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, v_BOOL_t nRoamScanOffloadEnabled);
+#endif
+
+
 /* ---------------------------------------------------------------------------
     \fn sme_IsFeatureSupportedByFW
     \brief  Check if an feature is enabled by FW
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 0aaf483..6ff3105 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -1199,7 +1199,6 @@
         *pNumChannels = 0;
         return eHAL_STATUS_RESOURCES;
     }
-
     /* Update the roam global structure */
     palCopyMemory(pMac->hHdd, *pOutChannelList, pChannelList, *pNumChannels);
     return status;
@@ -1542,7 +1541,10 @@
         pMac->roam.configParam.nRoamIntraBand = pParam->nRoamIntraBand;
         pMac->roam.configParam.isWESModeEnabled = pParam->isWESModeEnabled;
 #endif
-#ifdef FEATURE_WLAN_LFR 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        pMac->roam.configParam.isRoamOffloadScanEnabled = pParam->isRoamOffloadScanEnabled;
+#endif
+#ifdef FEATURE_WLAN_LFR
         pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled;
 #endif
 
@@ -4349,8 +4351,8 @@
     switch ( pCommand->u.roamCmd.roamReason )
     {
     case eCsrForcedDisassoc:
-        csrFreeRoamProfile(pMac, sessionId);
         status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE );
+        csrFreeRoamProfile(pMac, sessionId);
         break;
      case eCsrSmeIssuedDisassocForHandoff:
         //Not to free pMac->roam.pCurRoamProfile (via csrFreeRoamProfile) because it is needed after disconnect
@@ -4362,12 +4364,12 @@
 
         break;
     case eCsrForcedDisassocMICFailure:
-        csrFreeRoamProfile(pMac, sessionId);
         status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, TRUE );
+        csrFreeRoamProfile(pMac, sessionId);
         break;
     case eCsrForcedDeauth:
-        csrFreeRoamProfile(pMac, sessionId);
         status = csrRoamProcessDisassocDeauth( pMac, pCommand, FALSE, FALSE );
+        csrFreeRoamProfile(pMac, sessionId);
         break;
     case eCsrHddIssuedReassocToSameAP:
     case eCsrSmeIssuedReassocToSameAP:
@@ -4878,6 +4880,13 @@
     return (pMac->roam.configParam.isFastRoamIniFeatureEnabled &&
             (!csrIsConcurrentSessionRunning(pMac)));
 }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+//Returns whether "FW based BG scan" is currently enabled...or not
+tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac)
+{
+    return (pMac->roam.configParam.isRoamOffloadScanEnabled);
+}
+#endif
 #endif
 
 //Return true means the command can be release, else not
@@ -9480,6 +9489,12 @@
             smsLog( pMac, LOG1, FL("RSSI indication from TL serialized through MC thread"));
             csrRoamRssiIndHdlr( pMac, pSirMsg );
         break;
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        case eWNI_SME_CANDIDATE_FOUND_IND:
+            smsLog( pMac, LOG2, FL("Candidate found indication from PE"));
+            csrNeighborRoamCandidateFoundIndHdlr( pMac, pSirMsg );
+        break;
+#endif
 
         default:
             break;
@@ -14534,6 +14549,341 @@
    return eHAL_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+
+static tSirRetStatus
+csrRoamScanOffloadPopulateMacHeader(tpAniSirGlobal pMac,
+                                    tANI_U8* pBD,
+                                    tANI_U8 type,
+                                    tANI_U8 subType,
+                                    tSirMacAddr peerAddr,
+                                    tSirMacAddr selfMacAddr)
+{
+        tSirRetStatus   statusCode = eSIR_SUCCESS;
+        tpSirMacMgmtHdr pMacHdr;
+
+        /* Prepare MAC management header */
+        pMacHdr = (tpSirMacMgmtHdr) (pBD);
+
+        /* Prepare FC */
+        pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
+        pMacHdr->fc.type    = type;
+        pMacHdr->fc.subType = subType;
+
+        /* Prepare Address 1 */
+        palCopyMemory( pMac->hHdd,
+                        (tANI_U8 *) pMacHdr->da,
+                        (tANI_U8 *) peerAddr,
+                        sizeof( tSirMacAddr ));
+
+        sirCopyMacAddr(pMacHdr->sa,selfMacAddr);
+
+        /* Prepare Address 3 */
+        palCopyMemory( pMac->hHdd,
+                        (tANI_U8 *) pMacHdr->bssId,
+                        (tANI_U8 *) peerAddr,
+                        sizeof( tSirMacAddr ));
+        return statusCode;
+} /*** csrRoamScanOffloadPopulateMacHeader() ***/
+
+static tSirRetStatus
+csrRoamScanOffloadPrepareProbeReqTemplate(tpAniSirGlobal pMac,
+                                          tANI_U8 nChannelNum,
+                                          tANI_U32 dot11mode,
+                                          tSirMacAddr selfMacAddr,
+                                          tANI_U8 *pFrame,
+                                          tANI_U16 *pusLen)
+{
+        tDot11fProbeRequest pr;
+        tANI_U32            nStatus, nBytes, nPayload;
+        tSirRetStatus       nSirStatus;
+        /*Bcast tx*/
+        tSirMacAddr         bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+        /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+
+        palZeroMemory( pMac->hHdd, ( tANI_U8* )&pr, sizeof( pr ) );
+
+        PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL);
+
+        if ( WNI_CFG_DOT11_MODE_11B != dot11mode )
+        {
+                PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates );
+        }
+
+
+        if (IS_DOT11_MODE_HT(dot11mode))
+        {
+                PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps );
+        }
+
+
+        nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload );
+        if ( DOT11F_FAILED( nStatus ) )
+        {
+                VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                                "Failed to calculate the packed size f"
+                                "or a Probe Request (0x%08x).\n", nStatus );
+
+
+                nPayload = sizeof( tDot11fProbeRequest );
+        }
+        else if ( DOT11F_WARNED( nStatus ) )
+        {
+                VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                                "There were warnings while calculating"
+                                "the packed size for a Probe Request ("
+                                "0x%08x).\n", nStatus );
+        }
+
+        nBytes = nPayload + sizeof( tSirMacMgmtHdr );
+
+        /* Prepare outgoing frame*/
+        palZeroMemory( pMac->hHdd, pFrame, nBytes );
+
+
+        nSirStatus = csrRoamScanOffloadPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
+                        SIR_MAC_MGMT_PROBE_REQ, bssId ,selfMacAddr);
+
+        if ( eSIR_SUCCESS != nSirStatus )
+        {
+                VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                                "Failed to populate the buffer descriptor for a Probe Request (%d).\n",
+                                nSirStatus );
+                return nSirStatus;
+        }
+
+
+        nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame +
+                        sizeof( tSirMacMgmtHdr ),
+                        nPayload, &nPayload );
+        if ( DOT11F_FAILED( nStatus ) )
+        {
+                VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                                "Failed to pack a Probe Request (0x%08x).\n", nStatus );
+                return eSIR_FAILURE;
+        }
+        else if ( DOT11F_WARNED( nStatus ) )
+        {
+                VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                                "There were warnings while packing a Probe Request (0x%08x).\n" );
+        }
+
+        *pusLen = nPayload + sizeof(tSirMacMgmtHdr);
+        return eSIR_SUCCESS;
+}
+
+eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason)
+{
+   vos_msg_t msg;
+   tSirRoamOffloadScanReq *pRequestBuf;
+   tpCsrNeighborRoamControlInfo    pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+   tCsrRoamSession *pSession;
+   tANI_U8 i,num_channels = 0, ucDot11Mode;
+   tANI_U8 *ChannelList = NULL;
+   tANI_U32 sessionId;
+   eHalStatus status = eHAL_STATUS_SUCCESS;
+   tpCsrChannelInfo    currChannelListInfo;
+   currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo;
+
+   if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled)
+   {
+      return eHAL_STATUS_FAILURE;
+   }
+   status = csrRoamGetSessionIdFromBSSID(pMac,
+                            (tCsrBssid *)pNeighborRoamInfo->currAPbssid,
+                                        &sessionId);
+   /*The Dynamic Config Items Update may happen even if the state is in INIT.
+    * It is important to ensure that the command is passed down to the FW only
+    * if the Infra Station is in a connected state.A connected station could also be
+    * in a PREAUTH or REASSOC states.So, consider not sending the command down in INIT state.
+    * We also have to ensure that if there is a STOP command we always have to inform Riva,
+    * irrespective of whichever state we are in.*/
+   if ((pMac->roam.neighborRoamInfo.neighborRoamState == eCSR_NEIGHBOR_ROAM_STATE_INIT) &&
+       (command != ROAM_SCAN_OFFLOAD_STOP))
+   {
+      VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Scan Command not sent to FW with state = %d and cmd = %d\n",
+              pMac->roam.neighborRoamInfo.neighborRoamState, command);
+      return eHAL_STATUS_FAILURE;
+   }
+
+   if ( !HAL_STATUS_SUCCESS( status ) )
+   {
+      VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to find the sessionId for Roam Offload scan request", __func__);
+      return eHAL_STATUS_FAILURE;
+   }
+   pSession = CSR_GET_SESSION( pMac, sessionId );
+   pRequestBuf = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq));
+   if (NULL == pRequestBuf)
+   {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for Roam Offload scan request", __func__);
+           return eHAL_STATUS_FAILED_ALLOC;
+   }
+
+    vos_mem_zero(pRequestBuf,sizeof(tSirRoamOffloadScanReq));
+    /* If command is STOP, then pass down ScanOffloadEnabled as Zero.This will handle the case of
+     * host driver reloads, but Riva still up and running*/
+    if(command == ROAM_SCAN_OFFLOAD_STOP)
+       pRequestBuf->RoamScanOffloadEnabled = 0;
+    else
+       pRequestBuf->RoamScanOffloadEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled;
+    vos_mem_copy(pRequestBuf->ConnectedNetwork.currAPbssid, pNeighborRoamInfo->currAPbssid,
+                 sizeof(tCsrBssid));
+    pRequestBuf->ConnectedNetwork.ssId.length =
+            pMac->roam.roamSession[sessionId].connectedProfile.SSID.length;
+    vos_mem_copy(pRequestBuf->ConnectedNetwork.ssId.ssId,
+                 pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId,
+                 pRequestBuf->ConnectedNetwork.ssId.length);
+    pRequestBuf->ConnectedNetwork.authentication =
+            pMac->roam.roamSession[sessionId].connectedProfile.AuthType;
+    pRequestBuf->ConnectedNetwork.encryption =
+            pMac->roam.roamSession[sessionId].connectedProfile.EncryptionType;
+    pRequestBuf->ConnectedNetwork.mcencryption =
+            pMac->roam.roamSession[sessionId].connectedProfile.mcEncryptionType;
+    pRequestBuf->LookupThreshold =
+            (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1);
+    pRequestBuf->RoamRssiDiff =
+            pMac->roam.configParam.RoamRssiDiff;
+    pRequestBuf->Command = command;
+    pRequestBuf->StartScanReason = reason;
+    pRequestBuf->NeighborScanTimerPeriod =
+            pNeighborRoamInfo->cfgParams.neighborScanPeriod;
+    pRequestBuf->NeighborRoamScanRefreshPeriod =
+            pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod;
+    pRequestBuf->NeighborScanChannelMinTime =
+            pNeighborRoamInfo->cfgParams.minChannelScanTime;
+    pRequestBuf->NeighborScanChannelMaxTime =
+            pNeighborRoamInfo->cfgParams.maxChannelScanTime;
+    pRequestBuf->EmptyRefreshScanPeriod =
+            pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod;
+#ifdef FEATURE_WLAN_CCX
+    pRequestBuf->IsCCXEnabled = pMac->roam.configParam.isCcxIniFeatureEnabled;
+#endif
+    if (
+#ifdef FEATURE_WLAN_CCX
+       ((pNeighborRoamInfo->isCCXAssoc) &&
+        (pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived ==
+         eANI_BOOLEAN_FALSE)) ||
+        (pNeighborRoamInfo->isCCXAssoc == eANI_BOOLEAN_FALSE) ||
+#endif // CCX
+        currChannelListInfo->numOfChannels == 0)
+    {
+
+    /*Retreive the Channel Cache either from ini or from the Occupied Channels list.
+     * Give Preference to INI Channels.*/
+    if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels)
+    {
+      ChannelList = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList;
+      for (i=0; i<pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels ;i++)
+          {
+             if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList)
+               {
+                  pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList;
+               }
+                  ChannelList++;
+          }
+          pRequestBuf->ConnectedNetwork.ChannelCount = num_channels;
+          pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC;
+    }
+    else{
+          ChannelList = pMac->scan.occupiedChannels.channelList;
+          for(i=0; i<pMac->scan.occupiedChannels.numChannels; i++)
+          {
+              if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList)
+              {
+                pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList;
+              }
+              ChannelList++;
+          }
+          pRequestBuf->ConnectedNetwork.ChannelCount = num_channels;
+          /* If the profile changes as to what it was earlier, inform the FW through
+           * FLUSH as ChannelCacheType in which case, the FW will flush the occupied channels
+           * for the earlier profile and try to learn them afresh.*/
+          if (reason == REASON_FLUSH_CHANNEL_LIST)
+              pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_FLUSH;
+          else {
+                if (csrNeighborRoamIsNewConnectedProfile(pMac))
+                    pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_INIT;
+                else
+                    pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE;
+          }
+        }
+    }
+#ifdef FEATURE_WLAN_CCX
+    else
+    {
+      /* If CCX is enabled, and a neighbor Report is received,then
+       * Ignore the INI Channels or the Occupied Channel List. Consider
+       * the channels in the neighbor list sent by the CCX AP.*/
+      if (currChannelListInfo->numOfChannels != 0)
+      {
+         ChannelList = currChannelListInfo->ChannelList;
+         for (i=0;i<currChannelListInfo->numOfChannels;i++)
+         {
+          if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList)
+          {
+           pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList;
+          }
+          ChannelList++;
+         }
+         pRequestBuf->ConnectedNetwork.ChannelCount = num_channels;
+         pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC;
+      }
+    }
+#endif
+    num_channels = 0;
+    ChannelList = NULL;
+
+    /* Maintain the Valid Channels List*/
+    if (0 == strncmp(pMac->scan.countryCodeCurrent, "KR", 2))
+    {
+       ChannelList = pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList;
+       for(i=0; i<pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.numOfChannels; i++)
+          {
+            if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList)
+              {
+                 pRequestBuf->ValidChannelList[num_channels++] = *ChannelList;
+              }
+                 ChannelList++;
+          }
+          pRequestBuf->ValidChannelCount = num_channels;
+    } else {
+       ChannelList = pMac->roam.validChannelList;
+       for(i=0; i<pMac->roam.numValidChannels; i++)
+          {
+            if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList)
+              {
+                 pRequestBuf->ValidChannelList[num_channels++] = *ChannelList;
+              }
+                 ChannelList++;
+          }
+          pRequestBuf->ValidChannelCount = num_channels;
+    }
+    pRequestBuf->MDID.mdiePresent = pMac->roam.roamSession[sessionId].connectedProfile.MDID.mdiePresent;
+    pRequestBuf->MDID.mobilityDomain = pMac->roam.roamSession[sessionId].connectedProfile.MDID.mobilityDomain;
+   /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/
+    ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac,
+                                                           csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode ));
+   csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
+                                             pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen);
+
+   csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
+                                             pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen);
+   msg.type     = WDA_START_ROAM_CANDIDATE_LOOKUP_REQ;
+   msg.reserved = 0;
+   msg.bodyptr  = pRequestBuf;
+   if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+   {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_START_ROAM_CANDIDATE_LOOKUP_REQ message to WDA", __func__);
+           vos_mem_free(pRequestBuf);
+           return eHAL_STATUS_FAILURE;
+   }
+
+   VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Roam Scan Offload Command %d, Reason %d", command, reason);
+   return status;
+}
+#endif
+
 tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32  statsMask, 
                                                 tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId)
 {
@@ -14949,6 +15299,9 @@
         {
             switch( pCommand->u.scanCmd.reason )
             {
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            case eCsrScanGetLfrResult:
+#endif
             case eCsrScanGetResult:
             case eCsrScanBGScanAbort:
             case eCsrScanBGScanEnable:
@@ -15531,3 +15884,43 @@
    }
    return status;
 }
+
+/* Returns whether a session is in VOS_STA_MODE...or not */
+tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId)
+{
+  tCsrRoamSession *pSession = NULL;
+  pSession = CSR_GET_SESSION ( pMac, sessionId );
+  if(!pSession)
+  {
+    smsLog(pMac, LOGE, FL(" %s: session %d not found "), __func__, sessionId);
+    return eANI_BOOLEAN_FALSE;
+  }
+  if ( !CSR_IS_SESSION_VALID ( pMac, sessionId ) )
+  {
+    smsLog(pMac, LOGE, FL(" %s: Inactive session"), __func__);
+    return eANI_BOOLEAN_FALSE;
+  }
+  if ( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType )
+  {
+     return eANI_BOOLEAN_FALSE;
+  }
+  /* There is a possibility that the above check may fail,because
+   * P2P CLI also uses the same BSSType (eCSR_BSS_TYPE_INFRASTRUCTURE)
+   * when it is connected.So,we may sneak through the above check even
+   * if we are not a STA mode INFRA station. So, if we sneak through
+   * the above condition, we can use the following check if we are
+   * really in STA Mode.*/
+
+  if ( NULL != pSession->pCurRoamProfile )
+  {
+    if ( pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE )
+    {
+      return eANI_BOOLEAN_TRUE;
+    } else {
+            smsLog(pMac, LOGE, FL(" %s: pCurRoamProfile is NULL\n"), __func__);
+            return eANI_BOOLEAN_FALSE;
+           }
+    }
+
+  return eANI_BOOLEAN_FALSE;
+}
diff --git a/CORE/SME/src/csr/csrApiScan.c b/CORE/SME/src/csr/csrApiScan.c
index 0e37471..cfe1481 100644
--- a/CORE/SME/src/csr/csrApiScan.c
+++ b/CORE/SME/src/csr/csrApiScan.c
@@ -969,6 +969,44 @@
     return (status);
 }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId,
+                                   csrScanCompleteCallback callback, void *pContext)
+{
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+    tSmeCmd *pScanCmd;
+
+    if (pMac->scan.fScanEnable)
+    {
+        pScanCmd = csrGetCommandBuffer(pMac);
+        if (pScanCmd)
+        {
+            pScanCmd->command = eSmeCommandScan;
+            pScanCmd->sessionId = sessionId;
+            palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd));
+            pScanCmd->u.scanCmd.callback = callback;
+            pScanCmd->u.scanCmd.pContext = pContext;
+            pScanCmd->u.scanCmd.reason = eCsrScanGetLfrResult;
+            //Need to make the following atomic
+            pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around
+            status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_TRUE);
+            if ( !HAL_STATUS_SUCCESS( status ) )
+            {
+                smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status );
+                csrReleaseCommandScan(pMac, pScanCmd);
+            }
+        }
+        else
+        {
+            //log error
+            smsLog(pMac, LOGE, FL("can not obtain a common buffer\n"));
+            status = eHAL_STATUS_RESOURCES;
+        }
+    }
+
+    return (status);
+}
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
 
 eHalStatus csrScanAllChannels(tpAniSirGlobal pMac, eCsrRequestType reqType)
 {
@@ -2754,7 +2792,7 @@
 #endif
 
 
-static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac )
+static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac, tANI_U8 reason )
 {
     tListElem *pEntry;
     tCsrScanResult *pBssDescription;
@@ -2792,8 +2830,12 @@
             continue;
         }
         fDupBss = csrRemoveDupBssDescription( pMac, &pBssDescription->Result.BssDescriptor, pIesLocal, &tmpSsid , &timer );
-        //Check whether we have reach out limit
-        if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) )
+        //Check whether we have reach out limit, but don't lose the LFR candidates came from FW
+        if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            && !( eCsrScanGetLfrResult == reason )
+#endif
+          )
         {
             //Limit reach
             smsLog(pMac, LOGW, FL("  BSS limit reached"));
@@ -3819,7 +3861,7 @@
 }
 
 
-static void csrSaveScanResults( tpAniSirGlobal pMac )
+static void csrSaveScanResults( tpAniSirGlobal pMac, tANI_U8 reason )
 {
     // initialize this to FALSE. profMoveInterimScanResultsToMainList() routine
     // will set this to the channel where an .11d beacon is seen
@@ -3831,7 +3873,7 @@
     // only if the applied 11d info could be found in one of the scan results
     pMac->scan.fCurrent11dInfoMatch = eANI_BOOLEAN_FALSE;
     // move the scan results from interim list to the main scan list
-    csrMoveTempScanResultsToMainList( pMac );
+    csrMoveTempScanResultsToMainList( pMac, reason );
 
     // Now check if we gathered any domain/country specific information
     // If so, we should update channel list and apply Tx power settings
@@ -4048,7 +4090,7 @@
                 //This check only valid here because csrSaveScanresults is not yet called
                 fSuccess = (!csrLLIsListEmpty(&pMac->scan.tempScanResults, LL_ACCESS_LOCK));
             }
-            csrSaveScanResults(pMac);
+            csrSaveScanResults(pMac, pCommand->u.scanCmd.reason);
 
 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
             {
@@ -4506,6 +4548,14 @@
             tANI_U8 cChannels = 0;
 
             //Different scan type can reach this point, we need to distinguish it
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if( eCsrScanGetLfrResult == pCommand->u.scanCmd.reason )
+            {
+                pChannelList = NULL;
+                cChannels = 0;
+            }
+            else
+#endif
             if( eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason )
             {
                 //eCsrScanSetBGScanParam uses different structure
@@ -4594,6 +4644,9 @@
             //HO bg scan/probe failed no need to try autonomously
             if(eCsrScanBgScan == pCommand->u.scanCmd.reason ||
                eCsrScanProbeBss == pCommand->u.scanCmd.reason ||
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+               eCsrScanGetLfrResult == pCommand->u.scanCmd.reason ||
+#endif
                eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason)
             {
                 fRemoveCommand = eANI_BOOLEAN_TRUE;
@@ -4713,7 +4766,11 @@
                 {
                     //Not to get channel info if the scan is not a wildcard scan because
                     //it may cause scan results got aged out incorrectly.
-                    if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) )
+                    if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+                        && (pCommand->u.scanCmd.reason != eCsrScanGetLfrResult)
+#endif
+                      )
                     {
                         //Get the list of channels scanned
                        if( pCommand->u.scanCmd.reason != eCsrScanUserRequest)
@@ -5114,7 +5171,7 @@
     return( status );
 }
 
-eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tScanReqParam *pScanReqParam )
+eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tANI_U32 sessionId, tScanReqParam *pScanReqParam )
 {
     eHalStatus status = eHAL_STATUS_SUCCESS;
     tSirSmeScanReq *pMsg;
@@ -5127,12 +5184,18 @@
         palZeroMemory(pMac->hHdd, pMsg, msgLen);
         pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ);
         pMsg->length = pal_cpu_to_be16(msgLen);
-        pMsg->sessionId = 0;
+        pMsg->sessionId = sessionId;
+        pMsg->transactionId = 0;
         pMsg->returnFreshResults = pScanReqParam->freshScan;
         //Always ask for unique result
         pMsg->returnUniqueResults = pScanReqParam->fUniqueResult;
         pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch;
         status = palSendMBMessage(pMac->hHdd, pMsg);
+        if (!HAL_STATUS_SUCCESS(status))
+        {
+            smsLog( pMac, LOGE, FL(" failed to send down scan req with status = %d\n"), status );
+        }
+
     }                             
 
     return( status );
@@ -5212,18 +5275,30 @@
 }
 
 
-eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac)
+eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac, tSmeCmd *pCommand)
 {
     eHalStatus status = eHAL_STATUS_FAILURE;
     tScanReqParam scanReq;
     
     do
     {    
-        //not a fresh scan
-        scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE;
-        scanReq.fUniqueResult = TRUE;
-        scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
-        status = csrSendMBScanResultReq(pMac, &scanReq);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        if (eCsrScanGetLfrResult == pCommand->u.scanCmd.reason)
+        {
+            //to get the LFR candidates from PE cache
+            scanReq.freshScan = SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS|SIR_BG_SCAN_PURGE_LFR_RESULTS;
+            scanReq.fUniqueResult = TRUE;
+            scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
+        }
+        else
+#endif
+        {
+           //not a fresh scan
+           scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE;
+           scanReq.fUniqueResult = TRUE;
+           scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS;
+        }
+        status = csrSendMBScanResultReq(pMac, pCommand->sessionId, &scanReq);
     }while(0);
     
     return (status);
@@ -5248,9 +5323,12 @@
 
     switch(pCommand->u.scanCmd.reason)
     {
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    case eCsrScanGetLfrResult:
+#endif
     case eCsrScanGetResult:
     case eCsrScanForCapsChange:     //For cap change, LIM already save BSS description
-        status = csrScanRetrieveResult(pMac);
+        status = csrScanRetrieveResult(pMac, pCommand);
         break;
     case eCsrScanSetBGScanParam:
         status = csrProcessSetBGScanParam(pMac, pCommand);
@@ -6366,6 +6444,9 @@
         {
             switch(pCommand->u.scanCmd.reason)
             {
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            case eCsrScanGetLfrResult:
+#endif
             case eCsrScanGetResult:
             case eCsrScanSetBGScanParam:
             case eCsrScanBGScanAbort:
diff --git a/CORE/SME/src/csr/csrNeighborRoam.c b/CORE/SME/src/csr/csrNeighborRoam.c
index ee5f5da..2ab9543 100644
--- a/CORE/SME/src/csr/csrNeighborRoam.c
+++ b/CORE/SME/src/csr/csrNeighborRoam.c
@@ -270,7 +270,11 @@
                                           tpCsrNeighborRoamControlInfo pNeighborRoamInfo)
 {
 #ifdef WLAN_FEATURE_VOWIFI_11R
-    if (pNeighborRoamInfo->is11rAssoc)
+    if ((pNeighborRoamInfo->is11rAssoc)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+     && !csrRoamIsRoamOffloadScanEnabled(pMac)
+#endif
+    )
     {
         if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
         {
@@ -286,7 +290,11 @@
 #endif
 
 #ifdef FEATURE_WLAN_CCX
-        if (pNeighborRoamInfo->isCCXAssoc)
+        if ((pNeighborRoamInfo->isCCXAssoc)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        && !csrRoamIsRoamOffloadScanEnabled(pMac)
+#endif
+        )
         {
             if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
             {
@@ -303,7 +311,11 @@
 #ifdef FEATURE_WLAN_LFR
             if (csrRoamIsFastRoamEnabled(pMac, CSR_SESSION_ID_INVALID))
             {
-                if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+                if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+                || csrRoamIsRoamOffloadScanEnabled(pMac)
+#endif
+                )
                 {
                     csrNeighborRoamIssuePreauthReq(pMac);
                 }
@@ -858,6 +870,12 @@
     tANI_U8 i = 0;
     tpCsrNeighborRoamControlInfo    pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (csrRoamIsRoamOffloadScanEnabled(pMac))
+    {
+        return eANI_BOOLEAN_TRUE;
+    }
+#endif
     if (0 == pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress)
         return eANI_BOOLEAN_TRUE;
     
@@ -1053,32 +1071,43 @@
         if (eHAL_STATUS_SUCCESS == csrNeighborRoamIssuePreauthReq(pMac))
         goto DEQ_PREAUTH; 
 
-        CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN);
-
-        /* Register Neighbor Lookup threshold callback with TL for UP event now */
-        NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-"
-                "register UP indication with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1));
-
-        vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext,
-                            (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1),
-                            WLANTL_HO_THRESHOLD_UP,
-                            csrNeighborRoamNeighborLookupUPCallback,
-                            VOS_MODULE_ID_SME, pMac);
-        if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        if (csrRoamIsRoamOffloadScanEnabled(pMac))
         {
-            //err msg
-            smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status);
-        }
-
-        /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */
-        status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer, 
-                        pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT, 
-                        eANI_BOOLEAN_FALSE);
-        if (eHAL_STATUS_SUCCESS != status)
+          csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_RESTART, REASON_PREAUTH_FAILED_FOR_ALL);
+          CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED);
+        } else
         {
-            smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status);
+#endif
+          CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN);
+
+          /* Register Neighbor Lookup threshold callback with TL for UP event now */
+          NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-"
+                  "register UP indication with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1));
+
+          vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext,
+                              (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1),
+                              WLANTL_HO_THRESHOLD_UP,
+                              csrNeighborRoamNeighborLookupUPCallback,
+                              VOS_MODULE_ID_SME, pMac);
+          if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+          {
+              //err msg
+              smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status);
+          }
+
+          /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */
+          status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer,
+                          pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT,
+                          eANI_BOOLEAN_FALSE);
+          if (eHAL_STATUS_SUCCESS != status)
+          {
+             smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status);
+          }
         }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
     }
+#endif
 
 DEQ_PREAUTH:
     csrRoamDequeuePreauth(pMac);
@@ -1280,7 +1309,11 @@
 
        /* This condition is to ensure to roam to an AP with better RSSI. if the value of RoamRssiDiff is Zero, this feature
         * is disabled and we continue to roam without any check*/
-       if(RoamRssiDiff > 0)
+       if ((RoamRssiDiff > 0)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+       && !csrRoamIsRoamOffloadScanEnabled(pMac)
+#endif
+       )
        {
                /*
                * If RSSI is lower than the lookup threshold, then continue.
@@ -1336,51 +1369,58 @@
 #endif /* WLAN_FEATURE_VOWIFI_11R */
 
 #ifdef FEATURE_WLAN_CCX
-        if (pNeighborRoamInfo->isCCXAssoc)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        if (!csrRoamIsRoamOffloadScanEnabled(pMac))
         {
-            if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId))
-            {
-                smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring"));
-                continue;
-            }
+#endif
+          if (pNeighborRoamInfo->isCCXAssoc)
+          {
+              if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId))
+              {
+                  smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring"));
+                  continue;
+              }
+          }
+          if ((pScanResult->BssDescriptor.QBSSLoad_present) &&
+               (pScanResult->BssDescriptor.QBSSLoad_avail))
+          {
+              if (pNeighborRoamInfo->isVOAdmitted)
+              {
+                  smsLog(pMac, LOG1, FL("New AP has %x BW available"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail);
+                  smsLog(pMac, LOG1, FL("We need %x BW available"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired);
+                  if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired)
+                  {
+                      VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+                          "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list",
+                          pScanResult->BssDescriptor.bssId[0],
+                          pScanResult->BssDescriptor.bssId[1],
+                          pScanResult->BssDescriptor.bssId[2],
+                          pScanResult->BssDescriptor.bssId[3],
+                          pScanResult->BssDescriptor.bssId[4],
+                          pScanResult->BssDescriptor.bssId[5]);
+                      continue;
+                  }
+              }
+          }
+          else
+          {
+              smsLog(pMac, LOGE, FL("No QBss %x %x"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present);
+              if (pNeighborRoamInfo->isVOAdmitted)
+              {
+                  VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+                      "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list",
+                      pScanResult->BssDescriptor.bssId[0],
+                      pScanResult->BssDescriptor.bssId[1],
+                      pScanResult->BssDescriptor.bssId[2],
+                      pScanResult->BssDescriptor.bssId[3],
+                      pScanResult->BssDescriptor.bssId[4],
+                      pScanResult->BssDescriptor.bssId[5]);
+                  continue;
+              }
+          }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
         }
-        if ((pScanResult->BssDescriptor.QBSSLoad_present) &&
-             (pScanResult->BssDescriptor.QBSSLoad_avail))
-        {
-            if (pNeighborRoamInfo->isVOAdmitted)
-            {
-                smsLog(pMac, LOG1, FL("New AP has %x BW available"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail);
-                smsLog(pMac, LOG1, FL("We need %x BW available"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired);
-                if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired) 
-                {
-                    VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, 
-                        "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list",
-                        pScanResult->BssDescriptor.bssId[0],
-                        pScanResult->BssDescriptor.bssId[1],
-                        pScanResult->BssDescriptor.bssId[2],
-                        pScanResult->BssDescriptor.bssId[3],
-                        pScanResult->BssDescriptor.bssId[4],
-                        pScanResult->BssDescriptor.bssId[5]);
-                    continue;
-                }
-            }
-        }
-        else
-        {
-            smsLog(pMac, LOGE, FL("No QBss %x %x"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present);
-            if (pNeighborRoamInfo->isVOAdmitted)
-            {
-                VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, 
-                    "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list",
-                    pScanResult->BssDescriptor.bssId[0],
-                    pScanResult->BssDescriptor.bssId[1],
-                    pScanResult->BssDescriptor.bssId[2],
-                    pScanResult->BssDescriptor.bssId[3],
-                    pScanResult->BssDescriptor.bssId[4],
-                    pScanResult->BssDescriptor.bssId[5]);
-                continue;
-            }
-        }
+#endif
 #endif /* FEATURE_WLAN_CCX */
 
 #ifdef FEATURE_WLAN_LFR
@@ -1398,7 +1438,11 @@
 
         /* If the received timestamp in BSS description is earlier than the scan request timestamp, skip 
          * this result */
-        if (pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime)
+        if ((pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            && !csrRoamIsRoamOffloadScanEnabled(pMac)
+#endif
+        )
         {
             smsLog(pMac, LOGE, FL("Ignoring BSS as it is older than the scan request timestamp"));
             continue;
@@ -1430,7 +1474,11 @@
         csrLLInsertTail(&pNeighborRoamInfo->roamableAPList, &pBssInfo->List, LL_ACCESS_LOCK);
 
 #if  defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
-        if (abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)) >= immediateRoamRssiDiff)
+        if ((abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)) >= immediateRoamRssiDiff)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            && !csrRoamIsRoamOffloadScanEnabled(pMac)
+#endif
+        )
         {
             VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
                        "%s: [INFOLOG] potential candidate to roam immediately (diff=%d, expected=%d)", 
@@ -1438,6 +1486,14 @@
                        immediateRoamRssiDiff);
             roamNow = eANI_BOOLEAN_TRUE;
         }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        /* If we are here means, FW already found candidates to roam, so we are
+           good to go with pre-auth */
+        if(csrRoamIsRoamOffloadScanEnabled(pMac))
+        {
+            roamNow = eANI_BOOLEAN_TRUE;
+        }
+#endif
 #endif
     }
 
@@ -1681,7 +1737,11 @@
 #if  defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
         /* If the state is REPORT_SCAN, then this must be the scan after the REPORT_QUERY state. So, we 
            should use the BSSID filter made out of neighbor reports */
-        if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+        if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        && (!csrRoamIsRoamOffloadScanEnabled(pMac))
+#endif
+        )
         {
             hstatus = csrNeighborRoamBssIdScanFilter(pMac, &scanFilter);
             NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R or CCX Association: Prepare scan filter status  with neighbor AP = %d"), hstatus);
@@ -1711,8 +1771,12 @@
 
         tempVal = csrLLCount(&pNeighborRoamInfo->roamableAPList);
 
-        switch(pNeighborRoamInfo->neighborRoamState)
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        if(!csrRoamIsRoamOffloadScanEnabled(pMac))
         {
+#endif
+         switch(pNeighborRoamInfo->neighborRoamState)
+         {
             case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN:
                 if (tempVal)
                 {
@@ -1791,7 +1855,10 @@
 
                 // Lets just exit out silently.
                 return eHAL_STATUS_SUCCESS;
+         }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
         }
+#endif
 
         if (tempVal)
         {
@@ -1799,21 +1866,28 @@
 
             if (roamNow)
             {
-                NEIGHBOR_ROAM_DEBUG(pMac, LOG2,
-                    FL("Immediate roam-deregister UP indication. RSSI = %d"),
-                    NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1));
-
-                vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext,
-                        (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1),
-                        WLANTL_HO_THRESHOLD_UP,
-                        csrNeighborRoamNeighborLookupUPCallback,
-                        VOS_MODULE_ID_SME);
-                
-                if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+                if(!csrRoamIsRoamOffloadScanEnabled(pMac))
                 {
-                    smsLog(pMac, LOGW,
-                        FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus);
+#endif
+                  NEIGHBOR_ROAM_DEBUG(pMac, LOG2,
+                      FL("Immediate roam-deregister UP indication. RSSI = %d"),
+                      NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1));
+
+                  vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext,
+                          (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1),
+                          WLANTL_HO_THRESHOLD_UP,
+                          csrNeighborRoamNeighborLookupUPCallback,
+                          VOS_MODULE_ID_SME);
+
+                  if(!VOS_IS_STATUS_SUCCESS(vosStatus))
+                  {
+                      smsLog(pMac, LOGW,
+                          FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus);
+                  }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
                 }
+#endif
 
                 csrNeighborRoamTriggerHandoff(pMac, pNeighborRoamInfo);
                 return eHAL_STATUS_SUCCESS;
@@ -1849,6 +1923,18 @@
  
         }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+if (csrRoamIsRoamOffloadScanEnabled(pMac))
+   {
+    if (!tempVal || !roamNow)
+    {
+      /* There is no candidate or We are not roaming Now.
+       * Inform the FW to restart Roam Offload Scan  */
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_RESTART, REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW);
+       CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED);
+    }
+   }
+#endif
     return eHAL_STATUS_SUCCESS;
 
 }
@@ -1942,6 +2028,54 @@
     return eHAL_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/* ---------------------------------------------------------------------------
+
+    \fn csrNeighborRoamScanResultRequestCallback
+
+    \brief  This function is the callback function registered in csrScanRequestLfrResult() to
+            indicate the completion of scan. If scan is completed for all the channels in
+            the channel list, this function gets the scan result and treats them as candidates
+
+    \param  halHandle - The handle returned by macOpen.
+            pContext - not used
+            scanId - not used
+            status - not used
+
+    \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+static eHalStatus csrNeighborRoamScanResultRequestCallback(tHalHandle halHandle, void *pContext,
+                                                           tANI_U32 scanId, eCsrScanStatus status)
+{
+    tpAniSirGlobal                  pMac = (tpAniSirGlobal) halHandle;
+    tpCsrNeighborRoamControlInfo    pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+    eHalStatus              hstatus;
+
+    smsLog(pMac, LOG2, FL("called "));
+    pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE;
+
+    /* we must be in connected state, if not ignore it */
+    if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState)
+    {
+        smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it"));
+        return eHAL_STATUS_SUCCESS;
+    }
+
+    /* Now we have completed scanning the channel list. We have get the result by applying appropriate filter
+       sort the results based on neighborScore and RSSI and select the best candidate out of the list */
+
+    hstatus = csrNeighborRoamProcessScanComplete(pMac);
+
+    if (eHAL_STATUS_SUCCESS != hstatus)
+    {
+        smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus);
+        return eHAL_STATUS_FAILURE;
+    }
+    return eHAL_STATUS_SUCCESS;
+}
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+
 #ifdef FEATURE_WLAN_LFR
 static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHandle, 
         void *pContext, tANI_U32 scanId, eCsrScanStatus status)
@@ -2682,6 +2816,12 @@
         smsLog(pMac, LOG1, FL("IAPP Neighbor list callback received as expected in state %d."),
             pNeighborRoamInfo->neighborRoamState);
         pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_TRUE;
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+        {
+           csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CHANNEL_LIST_CHANGED);
+        }
+#endif
     }
     pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0;
     pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE;
@@ -2885,8 +3025,6 @@
     if (fNew)
     {
         smsLog(pMac, LOG1, FL("Prev roam profile did not match current"));
-        csrRoamFreeConnectProfile(pMac, pPrevProfile);
-        csrRoamGetConnectProfile(pMac, sessionId, pPrevProfile);
     }
     else
     {
@@ -3489,11 +3627,20 @@
 eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessionId)
 {
     tpCsrNeighborRoamControlInfo    pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+#ifdef FEATURE_WLAN_LFR
+    tCsrRoamConnectedProfile *pPrevProfile = &pNeighborRoamInfo->prevConnProfile;
+#endif
 
     smsLog(pMac, LOGE, FL("Disconnect indication on session %d in state %d (sub-state %d)"),
            sessionId, pNeighborRoamInfo->neighborRoamState,
            pMac->roam.curSubState[sessionId]);
  
+#ifdef FEATURE_WLAN_LFR
+    /*Free the current previous profile and move the current profile to prev profile.*/
+    csrRoamFreeConnectProfile(pMac, pPrevProfile);
+    csrRoamGetConnectProfile(pMac, sessionId, pPrevProfile);
+#endif
+
 #ifdef FEATURE_WLAN_CCX
     {
       tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId);
@@ -3537,19 +3684,40 @@
 
         case eCSR_NEIGHBOR_ROAM_STATE_INIT:
             csrNeighborRoamResetInitStateControlInfo(pMac);
-            csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if(!pMac->roam.configParam.isRoamOffloadScanEnabled)
+            {
+#endif
+              csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            }
+#endif
             break; 
 
         case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED:
             CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
             csrNeighborRoamResetConnectedStateControlInfo(pMac);
-            csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if(!pMac->roam.configParam.isRoamOffloadScanEnabled)
+            {
+#endif
+              csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            }
+#endif
             break;
 
         case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN:
             CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT);
             csrNeighborRoamResetCfgListChanScanControlInfo(pMac);
-            csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if (!pMac->roam.configParam.isRoamOffloadScanEnabled)
+            {
+#endif
+              csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            }
+#endif
             break;
 
         case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE:
@@ -3560,7 +3728,14 @@
             CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
             csrNeighborRoamResetPreauthControlInfo(pMac);
             csrNeighborRoamResetReportScanStateControlInfo(pMac);
-            csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            if (!pMac->roam.configParam.isRoamOffloadScanEnabled)
+            {
+#endif
+              csrNeighborRoamDeregAllRssiIndication(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+            }
+#endif
             break;
 
         default:
@@ -3569,6 +3744,11 @@
             CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT)
             break;
     }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    /*Inform the Firmware to STOP Scanning as the host has a disconnect.*/
+    if (csrRoamIsStaMode(pMac, sessionId))
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED);
+#endif
     return eHAL_STATUS_SUCCESS;
 }
 
@@ -3687,6 +3867,16 @@
                 /* Initialize all the data structures needed for the 11r FT Preauth */
                 pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0;
                 csrNeighborRoamPurgePreauthFailedList(pMac);
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+              if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+              {
+                 /*If this is not a INFRA type BSS, then do not send the command
+                  * down to firmware.Do not send the START command for other session
+                  * connections.*/
+                 if(csrRoamIsStaMode(pMac, sessionId))
+                  csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT);
+              } else {
+#endif
 
                 NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold);
                 /* Register Neighbor Lookup threshold callback with TL for DOWN event only */
@@ -3703,6 +3893,9 @@
                    smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vstatus);
                    status = eHAL_STATUS_FAILURE;
                 }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+              }
+#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */
             }
 #endif
             break;
@@ -4236,5 +4429,44 @@
                        (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pMac->roam.neighborRoamInfo.neighborRoamState);
     return (val);
 }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/* ---------------------------------------------------------------------------
 
+    \fn csrNeighborRoamCandidateFoundIndHdlr
+
+    \brief  This function is called by CSR as soon as TL posts the candidate
+            found indication to SME via MC thread
+
+    \param  pMac - The handle returned by macOpen.
+            pMsg - Msg sent by PE
+
+    \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise
+
+---------------------------------------------------------------------------*/
+eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg)
+{
+    tpCsrNeighborRoamControlInfo    pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+    /* we must be in connected state, if not ignore it */
+    if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState)
+    {
+        smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it"));
+        status = eHAL_STATUS_FAILURE;
+    }
+    else
+    {
+        /* We are about to start a fresh scan cycle,
+         * purge non-P2P results from the past */
+        csrScanFlushSelectiveResult(pMac, VOS_FALSE);
+        /* Once it gets the candidates found indication from PE, will issue a scan
+         - req to PE with “freshScan” in scanreq structure set as follows:
+         0x42 - Return & purge LFR scan results
+        */
+        status = csrScanRequestLfrResult(pMac, pNeighborRoamInfo->csrSessionId,
+                                         csrNeighborRoamScanResultRequestCallback, pMac);
+    }
+
+    return status;
+}
+#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD
 #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 9e4a866..caab00b 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -7013,7 +7013,12 @@
         pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff;
         sme_ReleaseGlobalLock( &pMac->sme );
     }
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+    {
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_RSSI_DIFF_CHANGED);
+    }
+#endif
     return status ;
 }
 
@@ -7225,6 +7230,12 @@
           sme_UpdateConfigFwRssiMonitoring(hHal, FALSE);
       }
   }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+    {
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CCX_INI_CFG_CHANGED);
+    }
+#endif
   return eHAL_STATUS_SUCCESS;
 }
 #endif /* FEATURE_WLAN_CCX */
@@ -7288,6 +7299,12 @@
         sme_ReleaseGlobalLock( &pMac->sme );
     }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+    {
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_LOOKUP_THRESH_CHANGED);
+    }
+#endif
     return status;
 }
 
@@ -7368,9 +7385,49 @@
         sme_ReleaseGlobalLock( &pMac->sme );
     }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+    {
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG,
+                          REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED);
+    }
+#endif
     return status ;
 }
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/*--------------------------------------------------------------------------
+  \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload feaure
+  It is used at in the REG_DYNAMIC_VARIABLE macro definition of
+  gRoamScanOffloadEnabled.
+  This is a synchronous call
+  \param hHal - The handle returned by macOpen.
+  \return eHAL_STATUS_SUCCESS - SME update config successfully.
+          Other status means SME is failed to update.
+  \sa
+  --------------------------------------------------------------------------*/
+
+eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal,
+        v_BOOL_t nRoamScanOffloadEnabled)
+{
+    tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+    eHalStatus          status    = eHAL_STATUS_SUCCESS;
+
+    status = sme_AcquireGlobalLock( &pMac->sme );
+    if ( HAL_STATUS_SUCCESS( status ) )
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+                     "%s: gRoamScanOffloadEnabled is changed from %d to %d", __func__,
+                      pMac->roam.configParam.isRoamOffloadScanEnabled,
+                      nRoamScanOffloadEnabled);
+        pMac->roam.configParam.isRoamOffloadScanEnabled = nRoamScanOffloadEnabled;
+        sme_ReleaseGlobalLock( &pMac->sme );
+    }
+
+    return status ;
+}
+#endif
+
 /*--------------------------------------------------------------------------
   \brief sme_getNeighborScanRefreshPeriod() - get neighbor scan results refresh period
   This is a synchronous call
@@ -7629,6 +7686,12 @@
         }
         sme_ReleaseGlobalLock( &pMac->sme );
     }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+    {
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CHANNEL_LIST_CHANGED);
+    }
+#endif
 
     return status ;
 }
@@ -7660,6 +7723,12 @@
         csrInitCountryValidChannelList(pMac, Revision);
         sme_ReleaseGlobalLock( &pMac->sme );
     }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    if (pMac->roam.configParam.isRoamOffloadScanEnabled)
+    {
+       csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_VALID_CHANNEL_LIST_CHANGED);
+    }
+#endif
 
     return status ;
 }
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index ac23456..1bc5d08 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -502,6 +502,9 @@
         CASE_RETURN_STRING(WDA_UPDATE_SCAN_PARAMS_REQ);
         CASE_RETURN_STRING(WDA_SET_PNO_CHANGED_IND);
 #endif // FEATURE_WLAN_SCAN_PNO
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        CASE_RETURN_STRING(WDA_START_ROAM_CANDIDATE_LOOKUP_REQ);
+#endif
 #ifdef WLAN_WAKEUP_EVENTS
         CASE_RETURN_STRING(WDA_WAKE_REASON_IND);
 #endif // WLAN_WAKEUP_EVENTS
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 56d246b..11a0ef3 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -118,6 +118,30 @@
    WDA_INVALID_STA_INDEX,
    WDA_VALID_STA_INDEX
 }WDA_ValidStaIndex;
+typedef enum
+{
+  eWDA_AUTH_TYPE_NONE,    //never used
+  // MAC layer authentication types
+  eWDA_AUTH_TYPE_OPEN_SYSTEM,
+  // Upper layer authentication types
+  eWDA_AUTH_TYPE_WPA,
+  eWDA_AUTH_TYPE_WPA_PSK,
+
+  eWDA_AUTH_TYPE_RSN,
+  eWDA_AUTH_TYPE_RSN_PSK,
+  eWDA_AUTH_TYPE_FT_RSN,
+  eWDA_AUTH_TYPE_FT_RSN_PSK,
+  eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE,
+  eWDA_AUTH_TYPE_WAPI_WAI_PSK,
+  eWDA_AUTH_TYPE_CCKM_WPA,
+  eWDA_AUTH_TYPE_CCKM_RSN,
+  eWDA_AUTH_TYPE_WPA_NONE,
+  eWDA_AUTH_TYPE_AUTOSWITCH,
+  eWDA_AUTH_TYPE_SHARED_KEY,
+  eWDA_NUM_OF_SUPPORT_AUTH_TYPE,
+  eWDA_AUTH_TYPE_FAILED = 0xff,
+  eWDA_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED,
+}WDA_AuthType;
 
 /*--------------------------------------------------------------------------
   Utilities
@@ -137,6 +161,11 @@
 #define IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE 0
 #endif
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE ((WDI_getHostWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD)) & (WDA_getFwWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD)))
+#else
+#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 0
+#endif
 
 /*--------------------------------------------------------------------------
   Definitions for Data path APIs
@@ -641,7 +670,12 @@
 
 /* WDA_IS_RX_IN_SCAN *********************************************************/
 #  define WDA_IS_RX_IN_SCAN(pRxMeta)  (((WDI_DS_RxMetaInfoType*)(pRxMeta))->scan)
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/* WDA_GET_OFFLOADSCANLEARN **************************************************/
+#  define WDA_GET_OFFLOADSCANLEARN(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->offloadScanLearn)
+/* WDA_GET_ROAMCANDIDATEIND **************************************************/
+#  define WDA_GET_ROAMCANDIDATEIND(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->roamCandidateInd)
+#endif
 /* WDA_GET_RX_RSSI_DB ********************************************************/
 // Volans RF
 #  define WDA_RSSI_OFFSET             100
@@ -1001,6 +1035,10 @@
 #define WDA_SET_PNO_CHANGED_IND     SIR_HAL_SET_PNO_CHANGED_IND
 #endif // FEATURE_WLAN_SCAN_PNO
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define WDA_START_ROAM_CANDIDATE_LOOKUP_REQ             SIR_HAL_START_ROAM_CANDIDATE_LOOKUP_REQ
+#endif
+
 #ifdef WLAN_WAKEUP_EVENTS
 #define WDA_WAKE_REASON_IND    SIR_HAL_WAKE_REASON_IND  
 #endif // WLAN_WAKEUP_EVENTS
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 99d93a7..dd3efe8 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -180,6 +180,12 @@
 static VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, tSirSetRSSIFilterReq* pRssiFilterParams);
 static VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, tSirUpdateScanParams *pUpdateScanParams);
 #endif // FEATURE_WLAN_SCAN_PNO
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+VOS_STATUS WDA_ProcessStartRoamCandidatelookupReq(tWDA_CbContext *pWDA,tSirRoamOffloadScanReq *pRoamOffloadScanReqParams);
+void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData);
+void WDA_ConvertSirAuthToWDIAuth(WDI_AuthType *AuthType, v_U8_t csrAuthType);
+void WDA_ConvertSirEncToWDIEnc(WDI_EdType *EncrType, v_U8_t csrEncrType);
+#endif
 #ifdef WLAN_FEATURE_PACKET_FILTERING
 static VOS_STATUS WDA_Process8023MulticastListReq (
                                        tWDA_CbContext *pWDA,
@@ -10907,6 +10913,13 @@
          break;
       }
 #endif // FEATURE_WLAN_SCAN_PNO
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+      case WDA_START_ROAM_CANDIDATE_LOOKUP_REQ:
+      {
+         WDA_ProcessStartRoamCandidatelookupReq(pWDA, (tSirRoamOffloadScanReq *)pMsg->bodyptr);
+         break;
+      }
+#endif
       case WDA_SET_TX_PER_TRACKING_REQ:
       {
          WDA_ProcessSetTxPerTrackingReq(pWDA, (tSirTxPerTrackingParam *)pMsg->bodyptr);
@@ -12122,6 +12135,238 @@
    }
    return CONVERT_WDI2VOS_STATUS(status) ;
 }
+
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+
+void WDA_ConvertSirAuthToWDIAuth(WDI_AuthType *AuthType, v_U8_t csrAuthType)
+{
+   /*Convert the CSR Auth types to WDI Auth types */
+   switch (csrAuthType)
+   {
+      case eCSR_AUTH_TYPE_OPEN_SYSTEM:
+           *AuthType = eWDA_AUTH_TYPE_OPEN_SYSTEM;
+           break;
+#ifdef FEATURE_WLAN_CCX
+      case eCSR_AUTH_TYPE_CCKM_WPA:
+           *AuthType = eWDA_AUTH_TYPE_CCKM_WPA;
+           break;
+#endif
+      case eCSR_AUTH_TYPE_WPA:
+           *AuthType = eWDA_AUTH_TYPE_WPA;
+           break;
+      case eCSR_AUTH_TYPE_WPA_PSK:
+           *AuthType = eWDA_AUTH_TYPE_WPA_PSK;
+           break;
+#ifdef FEATURE_WLAN_CCX
+      case eCSR_AUTH_TYPE_CCKM_RSN:
+           *AuthType = eWDA_AUTH_TYPE_CCKM_RSN;
+           break;
+#endif
+      case eCSR_AUTH_TYPE_RSN:
+           *AuthType = eWDA_AUTH_TYPE_RSN;
+           break;
+      case eCSR_AUTH_TYPE_RSN_PSK:
+           *AuthType = eWDA_AUTH_TYPE_RSN_PSK;
+           break;
+#if defined WLAN_FEATURE_VOWIFI_11R
+      case eCSR_AUTH_TYPE_FT_RSN:
+           *AuthType = eWDA_AUTH_TYPE_FT_RSN;
+           break;
+      case eCSR_AUTH_TYPE_FT_RSN_PSK:
+           *AuthType = eWDA_AUTH_TYPE_FT_RSN_PSK;
+           break;
+#endif
+#ifdef FEATURE_WLAN_WAPI
+      case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
+           *AuthType = eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
+           break;
+      case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
+           *AuthType = eWDA_AUTH_TYPE_WAPI_WAI_PSK;
+           break;
+#endif /* FEATURE_WLAN_WAPI */
+      case eCSR_AUTH_TYPE_SHARED_KEY:
+      case eCSR_AUTH_TYPE_AUTOSWITCH:
+           *AuthType = eWDA_AUTH_TYPE_OPEN_SYSTEM;
+           break;
+#if 0
+      case eCSR_AUTH_TYPE_SHARED_KEY:
+           *AuthType = eWDA_AUTH_TYPE_SHARED_KEY;
+           break;
+      case eCSR_AUTH_TYPE_AUTOSWITCH:
+           *AuthType = eWDA_AUTH_TYPE_AUTOSWITCH;
+#endif
+      default:
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 "%s: Unknown Auth Type", __func__);
+           break;
+   }
+}
+void WDA_ConvertSirEncToWDIEnc(WDI_EdType *EncrType, v_U8_t csrEncrType)
+{
+   switch (csrEncrType)
+   {
+      case eCSR_ENCRYPT_TYPE_NONE:
+           *EncrType = WDI_ED_NONE;
+           break;
+      case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
+      case eCSR_ENCRYPT_TYPE_WEP40:
+           *EncrType = WDI_ED_WEP40;
+           break;
+      case eCSR_ENCRYPT_TYPE_WEP104:
+      case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
+           *EncrType = WDI_ED_WEP104;
+           break;
+      case eCSR_ENCRYPT_TYPE_TKIP:
+           *EncrType = WDI_ED_TKIP;
+           break;
+      case eCSR_ENCRYPT_TYPE_AES:
+           *EncrType = WDI_ED_CCMP;
+           break;
+#ifdef WLAN_FEATURE_11W
+      case eCSR_ENCRYPT_TYPE_AES_CMAC:
+           *EncrType = WDI_ED_AES_128_CMAC;
+           break;
+#endif
+#ifdef FEATURE_WLAN_WAPI
+      case eCSR_ENCRYPT_TYPE_WPI:
+           *EncrType = WDI_ED_WPI;
+           break;
+#endif
+      case eCSR_ENCRYPT_TYPE_ANY:
+           *EncrType = WDI_ED_ANY;
+           break;
+
+      default:
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 "%s: Unknown Encryption Type", __func__);
+           break;
+   }
+}
+
+/*
+ * FUNCTION: WDA_ProcessStartRoamCandidatelookupReq
+ * Request to WDI to set Roam Offload Scan
+ */
+VOS_STATUS WDA_ProcessStartRoamCandidatelookupReq(tWDA_CbContext *pWDA,
+                                                  tSirRoamOffloadScanReq *pRoamOffloadScanReqParams)
+{
+   WDI_Status status;
+   WDI_RoamCandidateLookupReqParamsType *pwdiRoamCandidateLookupReqParams =
+   (WDI_RoamCandidateLookupReqParamsType *)vos_mem_malloc(sizeof(WDI_RoamCandidateLookupReqParamsType));
+   tWDA_ReqParams *pWdaParams ;
+   v_U8_t csrAuthType;
+   WDI_RoamNetworkType *pwdiRoamNetworkType;
+   WDI_RoamOffloadScanInfo *pwdiRoamOffloadScanInfo;
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+              "------> %s " ,__func__);
+   if (NULL == pwdiRoamCandidateLookupReqParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                           "%s: VOS MEM Alloc Failure", __func__);
+      VOS_ASSERT(0);
+      return VOS_STATUS_E_NOMEM;
+   }
+   pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ;
+   if (NULL == pWdaParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: VOS MEM Alloc Failure", __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pwdiRoamCandidateLookupReqParams);
+      return VOS_STATUS_E_NOMEM;
+   }
+
+   pwdiRoamNetworkType =
+   &pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork;
+   pwdiRoamOffloadScanInfo =
+   &pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo;
+   vos_mem_zero (pwdiRoamCandidateLookupReqParams,sizeof(WDI_RoamCandidateLookupReqParamsType));
+   csrAuthType = pRoamOffloadScanReqParams->ConnectedNetwork.authentication;
+   pwdiRoamOffloadScanInfo->RoamScanOffloadEnabled =
+          pRoamOffloadScanReqParams->RoamScanOffloadEnabled;
+   vos_mem_copy(pwdiRoamNetworkType->currAPbssid,
+                pRoamOffloadScanReqParams->ConnectedNetwork.currAPbssid,
+                sizeof(pwdiRoamNetworkType->currAPbssid));
+   WDA_ConvertSirAuthToWDIAuth(&pwdiRoamNetworkType->authentication,
+                                csrAuthType);
+   WDA_ConvertSirEncToWDIEnc(&pwdiRoamNetworkType->encryption,
+       pRoamOffloadScanReqParams->ConnectedNetwork.encryption);
+   WDA_ConvertSirEncToWDIEnc(&pwdiRoamNetworkType->mcencryption,
+       pRoamOffloadScanReqParams->ConnectedNetwork.mcencryption);
+   pwdiRoamOffloadScanInfo->LookupThreshold =
+           pRoamOffloadScanReqParams->LookupThreshold ;
+   pwdiRoamOffloadScanInfo->RoamRssiDiff =
+           pRoamOffloadScanReqParams->RoamRssiDiff ;
+   pwdiRoamOffloadScanInfo->Command =
+           pRoamOffloadScanReqParams->Command ;
+   pwdiRoamOffloadScanInfo->StartScanReason =
+           pRoamOffloadScanReqParams->StartScanReason ;
+   pwdiRoamOffloadScanInfo->NeighborScanTimerPeriod =
+           pRoamOffloadScanReqParams->NeighborScanTimerPeriod ;
+   pwdiRoamOffloadScanInfo->NeighborRoamScanRefreshPeriod =
+           pRoamOffloadScanReqParams->NeighborRoamScanRefreshPeriod ;
+   pwdiRoamOffloadScanInfo->NeighborScanChannelMinTime =
+           pRoamOffloadScanReqParams->NeighborScanChannelMinTime ;
+   pwdiRoamOffloadScanInfo->NeighborScanChannelMaxTime =
+           pRoamOffloadScanReqParams->NeighborScanChannelMaxTime ;
+   pwdiRoamOffloadScanInfo->EmptyRefreshScanPeriod =
+           pRoamOffloadScanReqParams->EmptyRefreshScanPeriod ;
+   pwdiRoamOffloadScanInfo->IsCCXEnabled =
+           pRoamOffloadScanReqParams->IsCCXEnabled ;
+   vos_mem_copy(&pwdiRoamNetworkType->ssId.sSSID,
+                &pRoamOffloadScanReqParams->ConnectedNetwork.ssId.ssId,
+                pRoamOffloadScanReqParams->ConnectedNetwork.ssId.length);
+   pwdiRoamNetworkType->ssId.ucLength =
+           pRoamOffloadScanReqParams->ConnectedNetwork.ssId.length;
+   vos_mem_copy(pwdiRoamNetworkType->ChannelCache,
+                pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCache,
+                pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCount);
+   pwdiRoamNetworkType->ChannelCount =
+           pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCount;
+   pwdiRoamOffloadScanInfo->ChannelCacheType =
+           pRoamOffloadScanReqParams->ChannelCacheType;
+   vos_mem_copy(pwdiRoamOffloadScanInfo->ValidChannelList,
+                pRoamOffloadScanReqParams->ValidChannelList,
+                pRoamOffloadScanReqParams->ValidChannelCount);
+   pwdiRoamOffloadScanInfo->ValidChannelCount =
+           pRoamOffloadScanReqParams->ValidChannelCount;
+   pwdiRoamOffloadScanInfo->us24GProbeSize =
+    (pRoamOffloadScanReqParams->us24GProbeTemplateLen<WDI_PNO_MAX_PROBE_SIZE)?
+    pRoamOffloadScanReqParams->us24GProbeTemplateLen:WDI_PNO_MAX_PROBE_SIZE;
+   vos_mem_copy(&pwdiRoamOffloadScanInfo->a24GProbeTemplate,
+                pRoamOffloadScanReqParams->p24GProbeTemplate,
+                pwdiRoamOffloadScanInfo->us24GProbeSize);
+   pwdiRoamOffloadScanInfo->us5GProbeSize =
+    (pRoamOffloadScanReqParams->us5GProbeTemplateLen<WDI_PNO_MAX_PROBE_SIZE)?
+    pRoamOffloadScanReqParams->us5GProbeTemplateLen:WDI_PNO_MAX_PROBE_SIZE;
+   vos_mem_copy(&pwdiRoamOffloadScanInfo->a5GProbeTemplate,
+                pRoamOffloadScanReqParams->p5GProbeTemplate,
+                pwdiRoamOffloadScanInfo->us5GProbeSize);
+   pwdiRoamOffloadScanInfo->MDID.mdiePresent =
+           pRoamOffloadScanReqParams->MDID.mdiePresent;
+   pwdiRoamOffloadScanInfo->MDID.mobilityDomain =
+           pRoamOffloadScanReqParams->MDID.mobilityDomain;
+   pwdiRoamCandidateLookupReqParams->wdiReqStatusCB = NULL;
+   /* Store Params pass it to WDI */
+   pWdaParams->wdaWdiApiMsgParam = (void *)pwdiRoamCandidateLookupReqParams;
+   pWdaParams->pWdaContext = pWDA;
+   /* Store param pointer as passed in by caller */
+   pWdaParams->wdaMsgParam = pRoamOffloadScanReqParams;
+   status = WDI_StartRoamCandidateLookupReq(pwdiRoamCandidateLookupReqParams,
+                           (WDI_RoamOffloadScanCb)WDA_RoamOffloadScanReqCallback, pWdaParams);
+   if(IS_WDI_STATUS_FAILURE(status))
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "Failure in Start Roam Candidate Lookup Req WDI API, free all the memory " );
+      vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ;
+      vos_mem_free(pWdaParams->wdaMsgParam);
+      pWdaParams->wdaWdiApiMsgParam = NULL;
+      pWdaParams->wdaMsgParam = NULL;
+   }
+   return CONVERT_WDI2VOS_STATUS(status) ;
+}
+#endif
+
 /*
  * FUNCTION: WDA_RssiFilterRespCallback
  * 
@@ -12334,6 +12579,41 @@
    return CONVERT_WDI2VOS_STATUS(status) ;
 }
 #endif // FEATURE_WLAN_SCAN_PNO
+
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/*
+ * FUNCTION: WDA_RoamOffloadScanReqCallback
+ *
+ */
+void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData)
+{
+   tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData;
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                          "<------ %s " ,__func__);
+    if (NULL == pWdaParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: pWdaParams received NULL", __func__);
+      VOS_ASSERT(0) ;
+      return ;
+   }
+   if ( pWdaParams != NULL )
+   {
+      if ( pWdaParams->wdaWdiApiMsgParam != NULL )
+      {
+         vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
+      }
+      if ( pWdaParams->wdaMsgParam != NULL)
+      {
+         vos_mem_free(pWdaParams->wdaMsgParam);
+      }
+
+      vos_mem_free(pWdaParams) ;
+   }
+   return ;
+}
+#endif
+
 /*
  * FUNCTION: WDA_SetPowerParamsRespCallback
  *
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index b7b4d8c..5c33b34 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -4259,6 +4259,11 @@
 
 #define WDI_PNO_MAX_PROBE_SIZE    450
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define WDI_ROAM_SCAN_MAX_CHANNELS       80 /* NUM_RF_CHANNELS */
+#define WDI_ROAM_SCAN_MAX_PROBE_SIZE     450
+#define WDI_ROAM_SCAN_RESERVED_BYTES     64
+#endif
 
 /*---------------------------------------------------------------------------
   WDI_AuthType
@@ -4426,6 +4431,86 @@
    void*                      pUserData; 
 } WDI_PNOScanReqParamsType;
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+
+typedef struct
+{
+  /*The SSID of the preferred network*/
+  WDI_MacSSid  ssId;
+  wpt_uint8    currAPbssid[WDI_MAC_ADDR_LEN];
+
+  /*The authentication method of the preferred network*/
+  WDI_AuthType authentication;
+
+  /*The encryption method of the preferred network*/
+  WDI_EdType   encryption;
+  WDI_EdType   mcencryption;
+
+  /*SSID broadcast type, normal, hidden or unknown*/
+  //WDI_SSIDBcastType wdiBcastNetworkType;
+
+  /*channel count - 0 for all channels*/
+  wpt_uint8    ChannelCount;
+
+  /*the actual channels*/
+  wpt_uint8    ChannelCache[WDI_ROAM_SCAN_MAX_CHANNELS];
+
+} WDI_RoamNetworkType;
+
+typedef struct WDIMobilityDomainInfo
+{
+ wpt_uint8 mdiePresent;
+ wpt_uint16 mobilityDomain;
+} WDI_MobilityDomainInfo;
+
+/*---------------------------------------------------------------------------
+  WDI_RoamOffloadScanInfo
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  wpt_boolean RoamScanOffloadEnabled;
+  wpt_uint8   LookupThreshold;
+  wpt_uint8   RoamRssiDiff;
+  wpt_uint8   ChannelCacheType;
+  wpt_uint8   Command;
+  wpt_uint8   StartScanReason;
+  wpt_uint16  NeighborScanTimerPeriod;
+  wpt_uint16  NeighborRoamScanRefreshPeriod;
+  wpt_uint16  NeighborScanChannelMinTime;
+  wpt_uint16  NeighborScanChannelMaxTime;
+  wpt_uint16  EmptyRefreshScanPeriod;
+  wpt_uint8   ValidChannelCount;
+  wpt_uint8   ValidChannelList[WDI_ROAM_SCAN_MAX_CHANNELS];
+  wpt_boolean IsCCXEnabled;
+  /*Probe template for 2.4GHz band*/
+  wpt_uint16  us24GProbeSize;
+  wpt_uint8   a24GProbeTemplate[WDI_ROAM_SCAN_MAX_PROBE_SIZE];
+
+  /*Probe template for 5GHz band*/
+  wpt_uint16  us5GProbeSize;
+  wpt_uint8   a5GProbeTemplate[WDI_ROAM_SCAN_MAX_PROBE_SIZE];
+  /*LFR BG Scan will currently look for only on network to which it is initially connected.
+   * As per requirement, later, the following structure can be used as an array of networks.*/
+  WDI_RoamNetworkType     ConnectedNetwork;
+  WDI_MobilityDomainInfo  MDID;
+  wpt_uint8               ReservedBytes[WDI_ROAM_SCAN_RESERVED_BYTES];
+} WDI_RoamOffloadScanInfo;
+
+typedef struct
+{
+   /* Start Roam Candidate Lookup Offload Back Ground Info Type */
+   WDI_RoamOffloadScanInfo        wdiRoamOffloadScanInfo;
+   /* Request status callback offered by UMAC - it is called if the current req
+   has returned PENDING as status; it delivers the status of sending the message
+   over the BUS */
+   WDI_ReqStatusCb            wdiReqStatusCB;
+   /* The user data passed in by UMAC, it will be sent back when the above
+   function pointer will be called */
+   void*                      pUserData;
+} WDI_RoamCandidateLookupReqParamsType;
+
+#endif
+
 /*---------------------------------------------------------------------------
   WDI_SetRssiFilterReqParamsType
   PNO info passed to WDI form WDA
@@ -6334,6 +6419,30 @@
                                         void*       pUserData);
 #endif // FEATURE_WLAN_SCAN_PNO
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/*---------------------------------------------------------------------------
+   WDI_RoamOffloadScanCb
+
+   DESCRIPTION
+
+   This callback is invoked by DAL when it has received a Start Roam Candidate Lookup Req
+   response from the underlying device.
+
+   PARAMETERS
+
+    IN
+    wdiStatus:  response status received from HAL
+    pUserData:  user data
+
+
+
+  RETURN VALUE
+    The result code associated with performing the operation
+---------------------------------------------------------------------------*/
+typedef void  (*WDI_RoamOffloadScanCb)(WDI_Status  wdiStatus,
+                                       void*       pUserData);
+
+#endif
 /*---------------------------------------------------------------------------
    WDI_SetTxPerTrackingRspCb
  
@@ -9004,6 +9113,31 @@
 );
 #endif // FEATURE_WLAN_SCAN_PNO
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ @brief WDI_StartRoamCandidateLookupReq
+
+ @param pwdiRoamCandidateLookupReqParams: Start Roam Candidate Lookup Req as specified
+        by the Device Interface
+
+        wdiRoamOffloadScanCb: callback for passing back the response
+        of the Start Roam Candidate Lookup operation received from the
+        device
+
+        pUserData: user data will be passed back with the
+        callback
+
+ @return Result of the function call
+*/
+WDI_Status
+WDI_StartRoamCandidateLookupReq
+(
+  WDI_RoamCandidateLookupReqParamsType* pwdiRoamCandidateLookupReqParams,
+  WDI_RoamOffloadScanCb                 wdiRoamOffloadScancb,
+  void*                                 pUserData
+);
+#endif
+
 /**
  @brief WDI_SetTxPerTrackingReq will be called when the upper MAC 
         wants to set the Tx Per Tracking configurations. 
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h b/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h
index 22b2a42..10aef2a 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h
@@ -309,38 +309,51 @@
     
         /* 0x10 */
 #ifdef WPT_BIG_BYTE_ENDIAN
-    
-        /** This is the length (in number of bytes) of the entire MPDU 
+
+        /** This is the length (in number of bytes) of the entire MPDU
         (header and data). Note that the length does not include FCS field. */
         wpt_uint32 mpduLength:16;
-    
-#ifdef WCN_PRONTO
-        wpt_uint32 reserved3: 3;
-        wpt_uint32 rxDXEPriorityRouting:1; 
+
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        wpt_uint32 offloadScanLearn:1;
+        wpt_uint32 roamCandidateInd:1;
 #else
-        wpt_uint32 reserved3:4;
+        wpt_uint32 reserved22:2;
+#endif
+
+#ifdef WCN_PRONTO
+        wpt_uint32 reserved3: 1;
+        wpt_uint32 rxDXEPriorityRouting:1;
+#else
+        wpt_uint32 reserved3:2;
 #endif //WCN_PRONTO
-    
-    
+
+
         /** Traffic Identifier
         Indicates the traffic class the frame belongs to. For non QoS frames,
         this field is set to zero. */
         wpt_uint32 tid:4;
-        
+
         wpt_uint32 reserved4:8;
 #else
         wpt_uint32 reserved4:8;
         wpt_uint32 tid:4;
 #ifdef WCN_PRONTO
-        wpt_uint32 rxDXEPriorityRouting:1; 
-        wpt_uint32 reserved3: 3;
+        wpt_uint32 rxDXEPriorityRouting:1;
+        wpt_uint32 reserved3: 1;
 #else
-        wpt_uint32 reserved3:4;
+        wpt_uint32 reserved3:2;
 #endif //WCN_PRONTO
-    
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+        wpt_uint32 roamCandidateInd:1;
+        wpt_uint32 offloadScanLearn:1;
+#else
+        wpt_uint32 reserved22:2;
+#endif
+
         wpt_uint32 mpduLength:16;
 #endif
-    
+
         /* 0x14 */
 #ifdef WPT_BIG_BYTE_ENDIAN
     
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h b/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h
index 646ab57..cea73ce 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h
@@ -299,6 +299,11 @@
 #define WDI_RX_FC_BD_GET_FC( _pvBDHeader )     (((WDI_FcRxBdType*)_pvBDHeader)->fc)
 #define WDI_RX_FC_BD_GET_STA_VALID_MASK( _pvBDHeader )     (((WDI_FcRxBdType*)_pvBDHeader)->fcSTAValidMask)
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+//LFR scan related
+#define WDI_RX_BD_GET_OFFLOADSCANLEARN( _pvBDHeader )         (((WDI_RxBdType*)_pvBDHeader)->offloadScanLearn)
+#define WDI_RX_BD_GET_ROAMCANDIDATEIND( _pvBDHeader )         (((WDI_RxBdType*)_pvBDHeader)->roamCandidateInd)
+#endif
 
 /*------------ RSSI and SNR Information extraction -------------*/
 #define WDI_RX_BD_GET_RSSI0( _pvBDHeader )  \
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index e7a04f2..ca317ba 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -444,7 +444,7 @@
 
   /*WLAN DAL Set Tx Power Request*/
   WDI_SET_TX_POWER_REQ                          = 82,
-
+  WDI_START_ROAM_CANDIDATE_LOOKUP_REQ           = 83,
   WDI_MAX_REQ,
 
   /*Send a suspend Indication down to HAL*/
@@ -710,7 +710,7 @@
   WDI_GET_ROAM_RSSI_RESP                        = 80,
 
   WDI_SET_TX_POWER_RESP                         = 81,
-
+  WDI_START_ROAM_CANDIDATE_LOOKUP_RESP          = 82,
   /*-------------------------------------------------------------------------
     Indications
      !! Keep these last in the enum if possible
@@ -4869,6 +4869,40 @@
 );
 #endif // FEATURE_WLAN_SCAN_PNO
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ @brief Process Start Roam Candidate Lookup Request function
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessStartRoamCandidatelookupReq
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+/**
+ @brief Process Start Roam Candidate Lookup Response function (called when a
+        response is being received over the bus from HAL)
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessStartRoamCandidatelookupRsp
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+#endif
+
 #ifdef WLAN_FEATURE_PACKET_FILTERING
 /**
  @brief Process 8023 Multicast List Request function
@@ -5122,6 +5156,23 @@
   WDI_EventInfoType*     pEventData
 );
 #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ *  @brief WDI_wdiEdTypeEncToEdTypeEnc -
+ *  The firmware expects the Encryption type to be in EdType.
+ *  This function converts the WdiEdType encryption to EdType.
+ *  @param tEdType    : EdType to which the encryption needs to be converted.
+ *  @param WDI_EdType : wdiEdType passed from the upper layer.
+ *  @see
+ *  @return none
+ *  */
+void
+WDI_wdiEdTypeEncToEdTypeEnc
+(
+ tEdType *EdType,
+ WDI_EdType wdiEdType
+);
+#endif
 
 #endif /*WLAN_QCT_WDI_I_H*/
 
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index dbe8195..3af951a 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -143,6 +143,11 @@
 #else
     ,FEATURE_NOT_SUPPORTED
 #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    ,WLAN_ROAM_SCAN_OFFLOAD
+#else
+    ,FEATURE_NOT_SUPPORTED
+#endif
    };
 
 /*-------------------------------------------------------------------------- 
@@ -349,6 +354,11 @@
   NULL,
 #endif
   WDI_ProcessSetTxPowerReq,             /* WDI_SET_TX_POWER_REQ*/
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+  WDI_ProcessStartRoamCandidatelookupReq,  /* WDI_START_ROAM_CANDIDATE_LOOKUP_REQ */
+#else
+  NULL,
+#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */
   /*-------------------------------------------------------------------------
     Indications
   -------------------------------------------------------------------------*/
@@ -527,7 +537,11 @@
   NULL,
 #endif
   WDI_ProcessSetTxPowerRsp,             /* WDI_SET_TX_POWER_RESP */
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    WDI_ProcessStartRoamCandidatelookupRsp, /* WDI_START_ROAM_CANDIDATE_LOOKUP_RESP */
+#else
+    NULL,
+#endif
   /*---------------------------------------------------------------------
     Indications
   ---------------------------------------------------------------------*/
@@ -848,6 +862,9 @@
     CASE_RETURN_STRING( WDI_SET_RSSI_FILTER_REQ );
     CASE_RETURN_STRING( WDI_UPDATE_SCAN_PARAMS_REQ );
   #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    CASE_RETURN_STRING( WDI_START_ROAM_CANDIDATE_LOOKUP_REQ );
+#endif
     CASE_RETURN_STRING( WDI_SET_TX_PER_TRACKING_REQ );
     CASE_RETURN_STRING( WDI_8023_MULTICAST_LIST_REQ );
     CASE_RETURN_STRING( WDI_RECEIVE_FILTER_SET_FILTER_REQ );
@@ -949,6 +966,9 @@
     CASE_RETURN_STRING( WDI_SET_RSSI_FILTER_RESP );
     CASE_RETURN_STRING( WDI_UPDATE_SCAN_PARAMS_RESP );
   #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+    CASE_RETURN_STRING( WDI_START_ROAM_CANDIDATE_LOOKUP_RESP );
+#endif
     CASE_RETURN_STRING( WDI_SET_TX_PER_TRACKING_RESP );
     CASE_RETURN_STRING( WDI_8023_MULTICAST_LIST_RESP );
     CASE_RETURN_STRING( WDI_RECEIVE_FILTER_SET_FILTER_RESP );
@@ -21758,7 +21778,10 @@
 #endif
   case WDI_KEEP_ALIVE_REQ:
     return WLAN_HAL_KEEP_ALIVE_REQ;
-
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+  case WDI_START_ROAM_CANDIDATE_LOOKUP_REQ:
+    return WLAN_START_ROAM_CANDIDATE_LOOKUP_REQ;
+#endif
 #ifdef FEATURE_WLAN_SCAN_PNO
   case WDI_SET_PREF_NETWORK_REQ:
     return WLAN_HAL_SET_PREF_NETWORK_REQ;
@@ -21982,6 +22005,10 @@
   case WLAN_HAL_PREF_NETW_FOUND_IND:
     return WDI_HAL_PREF_NETWORK_FOUND_IND;
 #endif // FEATURE_WLAN_SCAN_PNO
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+  case WLAN_START_ROAM_CANDIDATE_LOOKUP_RSP:
+    return WDI_START_ROAM_CANDIDATE_LOOKUP_RESP;
+#endif
   case WLAN_HAL_SET_TX_PER_TRACKING_RSP:
     return WDI_SET_TX_PER_TRACKING_RESP;
 #ifdef WLAN_FEATURE_PACKET_FILTERING
@@ -23678,7 +23705,322 @@
    return  WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize,
                         wdiRssiFilterCb, pEventData->pUserData, WDI_SET_RSSI_FILTER_RESP);
 }
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+/**
+ @brief WDI_StartRoamCandidateLookupReq
 
+ @param pwdiRoamCandidateLookupReqParams: the  LookupReq as specified
+                      by the Device Interface
+
+        wdiRoamOffloadScancb: callback for passing back the response
+        of the Roam Candidate Lookup Req operation received from the
+        device
+
+        pUserData: user data will be passed back with the
+        callback
+ @return Result of the function call
+*/
+WDI_Status
+WDI_StartRoamCandidateLookupReq
+(
+  WDI_RoamCandidateLookupReqParamsType* pwdiRoamCandidateLookupReqParams,
+  WDI_RoamOffloadScanCb                 wdiRoamOffloadScancb,
+  void*                                 pUserData
+)
+{
+   WDI_EventInfoType      wdiEventData = {{0}};
+   /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+   /*------------------------------------------------------------------------
+     Sanity Check
+   ------------------------------------------------------------------------*/
+   if ( eWLAN_PAL_FALSE == gWDIInitialized )
+   {
+     WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+               "WDI API call before module is initialized - Fail request");
+
+     return WDI_STATUS_E_NOT_ALLOWED;
+   }
+
+   /*------------------------------------------------------------------------
+     Fill in Event data and post to the Main FSM
+   ------------------------------------------------------------------------*/
+   wdiEventData.wdiRequest      = WDI_START_ROAM_CANDIDATE_LOOKUP_REQ;
+   wdiEventData.pEventData      = pwdiRoamCandidateLookupReqParams;
+   wdiEventData.uEventDataSize  = sizeof(*pwdiRoamCandidateLookupReqParams);
+   wdiEventData.pCBfnc          = wdiRoamOffloadScancb;
+   wdiEventData.pUserData       = pUserData;
+
+   return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+void
+WDI_wdiEdTypeEncToEdTypeEnc(tEdType *EdType, WDI_EdType wdiEdType)
+{
+  switch (wdiEdType)
+  {
+    case WDI_ED_NONE:
+         *EdType = eED_NONE;
+          break;
+    case WDI_ED_WEP40:
+    case WDI_ED_WEP104:
+         *EdType = eED_WEP;
+          break;
+    case WDI_ED_TKIP:
+         *EdType = eED_TKIP;
+          break;
+    case WDI_ED_CCMP:
+#ifdef WLAN_FEATURE_11W
+    case WDI_ED_AES_128_CMAC:
+#endif
+         *EdType = eED_CCMP;
+          break;
+#ifdef FEATURE_WLAN_WAPI
+    case WDI_ED_WPI:
+         *EdType = eED_WPI;
+          break;
+#endif
+    case WDI_ED_ANY:
+         *EdType = eED_ANY;
+          break;
+
+    default:
+         WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+                     "%s: Unknown Encryption Type", __func__);
+         break;
+     }
+}
+
+/**
+ @brief Helper function to pack Start Roam Candidate Lookup
+        Request parameters
+
+ @param  pWDICtx:                               pointer to the WLAN DAL context
+         pwdiRoamCandidateLookupReqParams:      pointer to the info received
+         from upper layers
+         ppSendBuffer, pSize - out pointers of the packed buffer
+         and its size
+
+ @return Result of the function call
+*/
+
+WDI_Status
+WDI_PackStartRoamCandidateLookup
+(
+  WDI_ControlBlockType*                 pWDICtx,
+  WDI_RoamCandidateLookupReqParamsType* pwdiRoamCandidateLookupReqParams,
+  wpt_uint8**                           ppSendBuffer,
+  wpt_uint16*                           pSize
+)
+{
+   wpt_uint8*                 pSendBuffer                = NULL;
+   wpt_uint16                 usDataOffset               = 0;
+   wpt_uint16                 usSendSize                 = 0;
+   tpRoamCandidateListParams  pRoamCandidateListParams   = NULL;
+   wpt_uint8 i;
+   /*-----------------------------------------------------------------------
+     Get message buffer
+   -----------------------------------------------------------------------*/
+   if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, WDI_START_ROAM_CANDIDATE_LOOKUP_REQ,
+                         sizeof(tRoamCandidateListParams),
+                         &pSendBuffer, &usDataOffset, &usSendSize))||
+       ( usSendSize < (usDataOffset + sizeof(tpRoamCandidateListParams) )))
+   {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+                  "Unable to get send buffer in Start Roam Candidate Lookup Req %x ",
+                   pwdiRoamCandidateLookupReqParams);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+   }
+   pRoamCandidateListParams = (tpRoamCandidateListParams)(pSendBuffer + usDataOffset);
+   wpalMemoryZero(pRoamCandidateListParams, sizeof(tpRoamCandidateListParams));
+   pRoamCandidateListParams->RoamScanOffloadEnabled = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.RoamScanOffloadEnabled;
+   wpalMemoryCopy(pRoamCandidateListParams->ConnectedNetwork.currAPbssid,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.currAPbssid,
+                  HAL_MAC_ADDR_LEN);
+   pRoamCandidateListParams->ConnectedNetwork.authentication = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.authentication;
+   WDI_wdiEdTypeEncToEdTypeEnc(&pRoamCandidateListParams->ConnectedNetwork.encryption,
+                               pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.encryption);
+   WDI_wdiEdTypeEncToEdTypeEnc(&pRoamCandidateListParams->ConnectedNetwork.mcencryption,
+                               pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.mcencryption);
+
+   pRoamCandidateListParams->ConnectedNetwork.ssId.length
+                = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ssId.ucLength;
+   wpalMemoryCopy( pRoamCandidateListParams->ConnectedNetwork.ssId.ssId,
+                   pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ssId.sSSID,
+                   pRoamCandidateListParams->ConnectedNetwork.ssId.length);
+   wpalMemoryCopy(pRoamCandidateListParams->ConnectedNetwork.ChannelCache,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCache,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCount );
+   pRoamCandidateListParams->ConnectedNetwork.ChannelCount = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCount;
+   pRoamCandidateListParams->ChannelCacheType = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ChannelCacheType ;
+   pRoamCandidateListParams->LookupThreshold = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.LookupThreshold;
+   pRoamCandidateListParams->RoamRssiDiff = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.RoamRssiDiff ;
+   pRoamCandidateListParams->Command = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.Command ;
+   pRoamCandidateListParams->StartScanReason = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.StartScanReason ;
+   pRoamCandidateListParams->NeighborScanTimerPeriod = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.NeighborScanTimerPeriod ;
+   pRoamCandidateListParams->NeighborRoamScanRefreshPeriod = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.NeighborRoamScanRefreshPeriod ;
+   pRoamCandidateListParams->NeighborScanChannelMinTime = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.NeighborScanChannelMinTime ;
+   pRoamCandidateListParams->NeighborScanChannelMaxTime = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.NeighborScanChannelMaxTime ;
+   pRoamCandidateListParams->EmptyRefreshScanPeriod = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.EmptyRefreshScanPeriod ;
+   pRoamCandidateListParams->IsCCXEnabled = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.IsCCXEnabled ;
+   wpalMemoryCopy(pRoamCandidateListParams->ValidChannelList,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ValidChannelList,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ValidChannelCount);
+   pRoamCandidateListParams->ValidChannelCount = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.ValidChannelCount;
+
+   WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+              "Values are ssid = %s, RoamOffloadScan=%d,Command=%d,StartScanReason=%d, NeighborScanTimerPeriod=%d, NeighborRoamScanRefreshPeriod=%d,NeighborScanChannelMinTime=%d,NeighborScanChannelMaxTime = %d,EmptyRefreshScanPeriod=%d, mdiePresent=%d,MDID=%d, auth=%d, uce=%d, mce=%d\n",
+                   pRoamCandidateListParams->ConnectedNetwork.ssId.ssId, pRoamCandidateListParams->RoamScanOffloadEnabled,
+                   pRoamCandidateListParams->Command,pRoamCandidateListParams->StartScanReason,
+                   pRoamCandidateListParams->NeighborScanTimerPeriod,pRoamCandidateListParams->NeighborRoamScanRefreshPeriod,
+                   pRoamCandidateListParams->NeighborScanChannelMinTime,pRoamCandidateListParams->NeighborScanChannelMaxTime,
+                   pRoamCandidateListParams->EmptyRefreshScanPeriod,pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.MDID.mdiePresent,
+                   pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.MDID.mobilityDomain,
+                   pRoamCandidateListParams->ConnectedNetwork.authentication, pRoamCandidateListParams->ConnectedNetwork.encryption,
+                   pRoamCandidateListParams->ConnectedNetwork.mcencryption);
+   pRoamCandidateListParams->us24GProbeSize =
+           (pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.us24GProbeSize<
+            WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)?
+           pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.us24GProbeSize:
+           WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE;
+   wpalMemoryCopy(pRoamCandidateListParams->a24GProbeTemplate,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.a24GProbeTemplate,
+                  pRoamCandidateListParams->us24GProbeSize);
+   pRoamCandidateListParams->us5GProbeSize =
+           (pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.us5GProbeSize<
+            WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)?
+           pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.us5GProbeSize:
+           WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE;
+   wpalMemoryCopy(pRoamCandidateListParams->a5GProbeTemplate,
+                  pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.a5GProbeTemplate,
+                  pRoamCandidateListParams->us5GProbeSize);
+   pRoamCandidateListParams->MDID.mdiePresent = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.MDID.mdiePresent;
+   pRoamCandidateListParams->MDID.mobilityDomain = pwdiRoamCandidateLookupReqParams->wdiRoamOffloadScanInfo.MDID.mobilityDomain;
+
+   WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,"Valid Channel List");
+   for (i=0; i<pRoamCandidateListParams->ValidChannelCount ; i++)
+   {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,"%d", pRoamCandidateListParams->ValidChannelList[i]);
+   }
+
+
+   /*Set the output values*/
+   *ppSendBuffer = pSendBuffer;
+   *pSize        = usSendSize;
+   return WDI_STATUS_SUCCESS;
+}/*WDI_PackStartRoamCandidateLookup*/
+
+/**
+ @brief Process Start Roam Candidate Lookup Request function
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessStartRoamCandidatelookupReq
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+   WDI_RoamCandidateLookupReqParamsType* pwdiRoamCandidateLookupReqParams = NULL;
+   WDI_RoamOffloadScanCb                 wdiRoamOffloadScancb  = NULL;
+   wpt_uint8*                            pSendBuffer           = NULL;
+   wpt_uint16                            usSendSize            = 0;
+   WDI_Status                            wdiStatus;
+   /*-------------------------------------------------------------------------
+     Sanity check
+   -------------------------------------------------------------------------*/
+   if (( NULL == pEventData ) ||
+       ( NULL == (pwdiRoamCandidateLookupReqParams = (WDI_RoamCandidateLookupReqParamsType*)pEventData->pEventData)) ||
+       ( NULL == (wdiRoamOffloadScancb   = (WDI_RoamOffloadScanCb)pEventData->pCBfnc)))
+   {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                  "%s: Invalid parameters", __func__);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+   }
+
+   /*-------------------------------------------------------------------------
+     Pack the Start Roam Candidate Lookup request structure based on version
+   -------------------------------------------------------------------------*/
+     WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+                  "%s: Packing Roam Candidate Lookup request ", __func__);
+
+     wdiStatus = WDI_PackStartRoamCandidateLookup( pWDICtx, pwdiRoamCandidateLookupReqParams,
+                                      &pSendBuffer, &usSendSize);
+
+   if (( WDI_STATUS_SUCCESS != wdiStatus )||
+       ( NULL == pSendBuffer )||( 0 == usSendSize ))
+   {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                  "%s: failed to pack request parameters", __func__);
+      WDI_ASSERT(0);
+      return wdiStatus;
+   }
+
+   pWDICtx->wdiReqStatusCB     = pwdiRoamCandidateLookupReqParams->wdiReqStatusCB;
+   pWDICtx->pReqStatusUserData = pwdiRoamCandidateLookupReqParams->pUserData;
+
+   /*-------------------------------------------------------------------------
+     Send WDI_START_ROAM_CANDIDATE_LOOKUP_REQ to HAL
+   -------------------------------------------------------------------------*/
+   return  WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize,
+               wdiRoamOffloadScancb, pEventData->pUserData, WDI_START_ROAM_CANDIDATE_LOOKUP_RESP);
+}
+
+/**
+ @brief Process Start Roam Candidate Lookup Rsp function (called when a
+        response is being received over the bus from HAL)
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessStartRoamCandidatelookupRsp
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+   WDI_Status                   wdiStatus;
+   eHalStatus                   halStatus;
+   WDI_RoamOffloadScanCb        wdiRoamOffloadScancb = NULL;
+
+   /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+   /*-------------------------------------------------------------------------
+     Sanity check
+   -------------------------------------------------------------------------*/
+   if (( NULL == pWDICtx ) || ( NULL == pEventData ) ||
+       ( NULL == pEventData->pEventData ))
+   {
+      WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                  "%s: Invalid parameters", __func__);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+   }
+
+   wdiRoamOffloadScancb = (WDI_RoamOffloadScanCb)pWDICtx->pfncRspCB;
+
+   /*-------------------------------------------------------------------------
+     Extract response and send it to UMAC
+   -------------------------------------------------------------------------*/
+   halStatus = *((eHalStatus*)pEventData->pEventData);
+   wdiStatus   =   WDI_HAL_2_WDI_STATUS(halStatus);
+
+   /*Notify UMAC*/
+   wdiRoamOffloadScancb(wdiStatus, pWDICtx->pRspCBUserData);
+
+   return WDI_STATUS_SUCCESS;
+}/*WDI_ProcessStartRoamCandidatelookupRsp*/
+#endif
 
 /**
  @brief Process Update Scan Params function
diff --git a/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
index c23d2cb..53cc6cd 100644
--- a/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
+++ b/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h
@@ -166,6 +166,10 @@
 #ifdef WLAN_FEATURE_11W
    wpt_uint32 rmf:1;
 #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+   wpt_uint32 offloadScanLearn;
+   wpt_uint32 roamCandidateInd;
+#endif
 } WDI_DS_RxMetaInfoType;
 
 typedef struct sPktMetaInfo
diff --git a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
index 6b4dfda..e6ff98f 100644
--- a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
+++ b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
@@ -614,6 +614,10 @@
 #ifdef WLAN_FEATURE_11W
       pRxMetadata->rmf = WDI_RX_BD_GET_RMF(pBDHeader);
 #endif
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+      pRxMetadata->offloadScanLearn = WDI_RX_BD_GET_OFFLOADSCANLEARN(pBDHeader);
+      pRxMetadata->roamCandidateInd = WDI_RX_BD_GET_ROAMCANDIDATEIND(pBDHeader);
+#endif
 
       /* typeSubtype in BD doesn't look like correct. Fill from frame ctrl
          TL does it for Volans but TL does not know BD for Prima. WDI should do it */
diff --git a/Kbuild b/Kbuild
index da225b2..73d1972 100644
--- a/Kbuild
+++ b/Kbuild
@@ -521,7 +521,8 @@
 		-DWLANTL_DEBUG\
 		-DWLAN_ACTIVEMODE_OFFLOAD_FEATURE \
         	-DWLAN_FEATURE_HOLD_RX_WAKELOCK \
-		-DWLAN_SOFTAP_VSTA_FEATURE
+		-DWLAN_SOFTAP_VSTA_FEATURE \
+                -DWLAN_FEATURE_ROAM_SCAN_OFFLOAD
 
 ifneq ($(CONFIG_PRONTO_WLAN),)
 CDEFINES += -DWCN_PRONTO
diff --git a/riva/inc/wlan_hal_msg.h b/riva/inc/wlan_hal_msg.h
index a324b71..95e3b02 100644
--- a/riva/inc/wlan_hal_msg.h
+++ b/riva/inc/wlan_hal_msg.h
@@ -362,6 +362,8 @@
    WLAN_HAL_DEL_BA_IND                      = 188,
    WLAN_HAL_DHCP_START_IND                  = 189,
    WLAN_HAL_DHCP_STOP_IND                   = 190,
+   WLAN_START_ROAM_CANDIDATE_LOOKUP_REQ     = 191,
+   WLAN_START_ROAM_CANDIDATE_LOOKUP_RSP     = 192,
 
   WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE
 }tHalHostMsgType;
@@ -4923,6 +4925,16 @@
 /*Maximum size of the probe template*/
 #define WLAN_HAL_PNO_MAX_PROBE_SIZE     450
 
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define CHANNEL_LIST_STATIC                   1 /* Occupied channel list remains static */
+#define CHANNEL_LIST_DYNAMIC_INIT             2 /* Occupied channel list can be learnt after init */
+#define CHANNEL_LIST_DYNAMIC_FLUSH            3 /* Occupied channel list can be learnt after flush */
+#define CHANNEL_LIST_DYNAMIC_UPDATE           4 /* Occupied channel list can be learnt after update */
+#define WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE     450
+#define WLAN_HAL_ROAM_SCAN_MAX_CHANNELS       NUM_RF_CHANNELS
+#define WLAN_HAL_ROAM_SCAN_RESERVED_BYTES     64
+#endif
+
 /*Type of PNO enabling 
   Immediate - scanning will start immediately and PNO procedure will
   be repeated based on timer
@@ -4952,6 +4964,8 @@
     eAUTH_TYPE_FT_RSN_PSK            = 7,
     eAUTH_TYPE_WAPI_WAI_CERTIFICATE  = 8,
     eAUTH_TYPE_WAPI_WAI_PSK          = 9,
+    eAUTH_TYPE_CCKM_WPA              = 10,
+    eAUTH_TYPE_CCKM_RSN              = 11,
     
     eAUTH_TYPE_MAX = WLAN_HAL_MAX_ENUM_SIZE
 
@@ -5177,7 +5191,65 @@
   tANI_U8          ucRssiThreshold;
 
 } tRssiFilterParams, * tpRssiFilterParams;
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+typedef PACKED_PRE struct PACKED_POST
+{
+   tSirMacSSid ssId;
+   tANI_U8     currAPbssid[HAL_MAC_ADDR_LEN];
+   tANI_U32    authentication;
+   tEdType     encryption;
+   tEdType     mcencryption;
+   tANI_U8     ChannelCount;
+   tANI_U8     ChannelCache[WLAN_HAL_ROAM_SCAN_MAX_CHANNELS];
+}tRoamNetworkType;
 
+typedef PACKED_PRE struct PACKED_POST
+{
+   tANI_U8 mdiePresent;
+   tANI_U16 mobilityDomain;
+}tMobilityDomainInfo;
+
+typedef PACKED_PRE struct PACKED_POST {
+   eAniBoolean       RoamScanOffloadEnabled;
+   tANI_S8           LookupThreshold;
+   tANI_U8           RoamRssiDiff;
+   tANI_U8           ChannelCacheType;
+   tANI_U8           Command;
+   tANI_U8           StartScanReason;
+   tANI_U16          NeighborScanTimerPeriod;
+   tANI_U16          NeighborRoamScanRefreshPeriod;
+   tANI_U16          NeighborScanChannelMinTime;
+   tANI_U16          NeighborScanChannelMaxTime;
+   tANI_U16          EmptyRefreshScanPeriod;
+   tANI_U8           ValidChannelCount;
+   tANI_U8           ValidChannelList[WLAN_HAL_ROAM_SCAN_MAX_CHANNELS];
+   eAniBoolean       IsCCXEnabled;
+
+   tANI_U16          us24GProbeSize;
+   tANI_U8           a24GProbeTemplate[WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE];
+   tANI_U16          us5GProbeSize;
+   tANI_U8           a5GProbeTemplate[WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE];
+   /* Add Reserved bytes */
+   tANI_U8           ReservedBytes[WLAN_HAL_ROAM_SCAN_RESERVED_BYTES];
+   tRoamNetworkType  ConnectedNetwork;
+   tMobilityDomainInfo MDID;
+} tRoamCandidateListParams, * tpRoamCandidateListParams;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+           tHalMsgHeader header;
+              tRoamCandidateListParams RoamScanOffloadNetwListParams;
+}  tSetRoamScanOffloadReq, *tpRoamScanOffloadReq;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+           tHalMsgHeader header;
+
+              /*status of the request - just to indicate that PNO has acknowledged
+               *      the request and will start scanning*/
+              tANI_U32   status;
+}  tSetRoamOffloadScanResp, *tpSetRoamOffloadScanResp;
+#endif
 /*
   RSSI Filter request 
 */
@@ -5564,7 +5636,8 @@
     BCN_FILTER         = 19,
     RTT                = 20,
     RATECTRL           = 21,
-    WOW                = 22
+    WOW                = 22,
+    WLAN_ROAM_SCAN_OFFLOAD = 23,
     //MAX_FEATURE_SUPPORTED = 128
 } placeHolderInCapBitmap;
 
@@ -5584,6 +5657,9 @@
 #define IS_SLM_SESSIONIZATION_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(SLM_SESSIONIZATION)))
 #define IS_FEATURE_SUPPORTED_BY_HOST(featEnumValue) (!!halMsg_GetHostWlanFeatCaps(featEnumValue))
 #define IS_WLANACTIVE_OFFLOAD_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(WLANACTIVE_OFFLOAD)))
+#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
+#define IS_ROAM_SCAN_OFFLOAD_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD)))
+#endif
 
 tANI_U8 halMsg_GetHostWlanFeatCaps(tANI_U8 feat_enum_value);