wlan: LFR MBB preauth changes

As part of LFR make before break, add changes to handle preauth
request and response in lim and csr.

Change-Id: I4a4872f8619efd95643ee8eeb62c9a8574b413dd
CRs-Fixed: 1098427
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 04ebf82..5a52a2c 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -3043,6 +3043,15 @@
 #define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MAX        (100)
 #define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_DEFAULT    (10)
 
+/*
+ * gEnableLFRMBB is used to disable/enable LFR Make before Break
+ * 1: Enable LFR Make before Break
+ * 0: Disable LFR Make before Break
+ */
+#define CFG_ENABLE_LFR_MBB         "gEnableLFRMBB"
+#define CFG_ENABLE_LFR_MBB_MIN     (0)
+#define CFG_ENABLE_LFR_MBB_MAX     (1)
+#define CFG_ENABLE_LFR_MBB_DEFAULT (0)
 
 /*--------------------------------------------------------------------------- 
   Type declarations
@@ -3274,6 +3283,11 @@
    v_U32_t                      PERtimerThreshold;
    v_U32_t                      PERroamRxPktsThreshold;
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+   tANI_BOOLEAN enable_lfr_mbb;
+#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 956f5fb..c485114 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -2877,6 +2877,15 @@
                  CFG_PER_ROAM_BAD_RSSI_MAX),
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+   REG_VARIABLE(CFG_ENABLE_LFR_MBB, WLAN_PARAM_Integer,
+                hdd_config_t, enable_lfr_mbb,
+                VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+                CFG_ENABLE_LFR_MBB_DEFAULT,
+                CFG_ENABLE_LFR_MBB_MIN,
+                CFG_ENABLE_LFR_MBB_MAX ),
+#endif
+
    REG_VARIABLE( CFG_ENABLE_ADAPT_RX_DRAIN_NAME, WLAN_PARAM_Integer,
                  hdd_config_t, fEnableAdaptRxDrain,
                  VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK ,
@@ -4530,6 +4539,13 @@
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
         "Name = [gEnableSapInternalRestart] Value = [%u] ",
          pHddCtx->cfg_ini->sap_internal_restart);
+
+#ifdef WLAN_FEATURE_LFR_MBB
+   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+          "Name = [gEnableLFRMBB] Value = [%u] ",
+           pHddCtx->cfg_ini->enable_lfr_mbb);
+#endif
+
 }
 
 
@@ -6412,6 +6428,11 @@
        smeConfig->csrConfig.bFastRoamInConIniFeatureEnabled = 0;
    }
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+   smeConfig->csrConfig.enable_lfr_mbb = pConfig->enable_lfr_mbb;
+#endif
+
 #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
    smeConfig->csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold;
    smeConfig->csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold;
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index 8197357..fc5ce65 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -230,6 +230,10 @@
     TX_TIMER           gLimFTPreAuthRspTimer;
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+    TX_TIMER           glim_pre_auth_mbb_rsp_timer;
+#endif
+
 #ifdef FEATURE_WLAN_ESE
     TX_TIMER           gLimEseTsmTimer;
 #endif
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 718af27..6ed2bb0 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -389,6 +389,12 @@
     eWNI_SME_REGISTER_MGMT_FRAME_CB,
     eWNI_SME_CAP_TSF_REQ,
     eWNI_SME_GET_TSF_REQ,
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ,
+    eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP,
+#endif
+
     eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 9752eb7..d452aa5 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -175,6 +175,11 @@
     eSIR_LINK_FINISH_CAL_STATE  = 13,
     eSIR_LINK_LISTEN_STATE      = 14,
     eSIR_LINK_SEND_ACTION_STATE = 15,
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    eSIR_LINK_PRE_AUTH_REASSOC_STATE = 17,
+#endif
+
 } tSirLinkState;
 
 
@@ -898,6 +903,10 @@
 #define SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE (SIR_LIM_TIMEOUT_MSG_START + 0x2C)
 #define SIR_LIM_AUTH_RETRY_TIMEOUT            (SIR_LIM_TIMEOUT_MSG_START + 0x2D)
 
+#ifdef WLAN_FEATURE_LFR_MBB
+#define SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT   (SIR_LIM_TIMEOUT_MSG_START + 0x2E)
+#endif
+
 #define SIR_LIM_MSG_TYPES_END            (SIR_LIM_MSG_TYPES_BEGIN+0xFF)
 
 // SCH message types
diff --git a/CORE/MAC/src/pe/include/limFT.h b/CORE/MAC/src/pe/include/limFT.h
index d750849..bf4dd64 100644
--- a/CORE/MAC/src/pe/include/limFT.h
+++ b/CORE/MAC/src/pe/include/limFT.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -52,6 +52,7 @@
 extern int  limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
 extern void limPerformFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, 
                 tpPESession psessionEntry);
+void limFTSetupAuthSession(tpAniSirGlobal pMac, tpPESession psessionEntry);
 void        limPerformPostFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, 
                 tpPESession psessionEntry);
 void        limFTResumeLinkCb(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data);
diff --git a/CORE/MAC/src/pe/include/limFTDefs.h b/CORE/MAC/src/pe/include/limFTDefs.h
index 97625a3..ffda9af 100644
--- a/CORE/MAC/src/pe/include/limFTDefs.h
+++ b/CORE/MAC/src/pe/include/limFTDefs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
diff --git a/CORE/MAC/src/pe/include/lim_mbb.h b/CORE/MAC/src/pe/include/lim_mbb.h
new file mode 100644
index 0000000..b050233
--- /dev/null
+++ b/CORE/MAC/src/pe/include/lim_mbb.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void lim_process_preauth_mbb_rsp_timeout(tpAniSirGlobal mac);
+void lim_process_pre_auth_reassoc_req(tpAniSirGlobal mac, tpSirMsgQ msg);
+void lim_handle_pre_auth_mbb_rsp(tpAniSirGlobal mac,
+     tSirRetStatus status, tpPESession session_entry);
+
diff --git a/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
index 09bb745..83dd917 100644
--- a/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -51,6 +51,9 @@
 #include "limFT.h"
 #endif
 #include "vos_utils.h"
+#ifdef WLAN_FEATURE_LFR_MBB
+#include "lim_mbb.h"
+#endif
 
 
 /**
@@ -1873,15 +1876,33 @@
     limLog(pMac, LOG1, FL("Pre-Auth response received from neighbor"));
     limLog(pMac, LOG1, FL("Pre-Auth done state"));
 #endif
+
+    limLog(pMac, LOG1, FL("is_preauth_lfr_mbb %d"),
+                          pMac->ft.ftSmeContext.is_preauth_lfr_mbb);
+
     // Stopping timer now, that we have our unicast from the AP
     // of our choice.
-    limDeactivateAndChangeTimer(pMac, eLIM_FT_PREAUTH_RSP_TIMER);
+    if (!pMac->ft.ftSmeContext.is_preauth_lfr_mbb)
+        limDeactivateAndChangeTimer(pMac, eLIM_FT_PREAUTH_RSP_TIMER);
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb)
+        limDeactivateAndChangeTimer(pMac, eLIM_PREAUTH_MBB_RSP_TIMER);
+#endif
 
 
     // Save off the auth resp.
     if ((sirConvertAuthFrame2Struct(pMac, pBody, frameLen, &rxAuthFrame) != eSIR_SUCCESS))
     {
         limLog(pMac, LOGE, FL("failed to convert Auth frame to struct"));
+
+#ifdef WLAN_FEATURE_LFR_MBB
+        if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) {
+            lim_handle_pre_auth_mbb_rsp(pMac, eSIR_FAILURE, psessionEntry);
+            return eSIR_FAILURE;
+        }
+#endif
+
         limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry);
         return eSIR_FAILURE;
     }
@@ -1921,6 +1942,13 @@
             break;
     }
 
+#ifdef WLAN_FEATURE_LFR_MBB
+        if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) {
+            lim_handle_pre_auth_mbb_rsp(pMac, ret_status, psessionEntry);
+            return ret_status;
+        }
+#endif
+
     // Send the Auth response to SME
     limHandleFTPreAuthRsp(pMac, ret_status, pBody, frameLen, psessionEntry);
 
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index abc8bad..afca513 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1681,6 +1681,9 @@
         case eWNI_SME_FT_PRE_AUTH_REQ:
         case eWNI_SME_FT_AGGR_QOS_REQ:
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+        case eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ:
+#endif
         case eWNI_SME_ADD_STA_SELF_REQ:
         case eWNI_SME_DEL_STA_SELF_REQ:
         case eWNI_SME_REGISTER_MGMT_FRAME_REQ:
@@ -1986,6 +1989,9 @@
         case SIR_LIM_DEAUTH_ACK_TIMEOUT:
         case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
         case SIR_LIM_AUTH_RETRY_TIMEOUT:
+#ifdef WLAN_FEATURE_LFR_MBB
+        case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT:
+#endif
             // These timeout messages are handled by MLM sub module
 
             limProcessMlmReqMessages(pMac,
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
index d0eab9b..8323ebd 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -59,6 +59,9 @@
 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
 #include "vos_diag_core_log.h"
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+#include "lim_mbb.h"
+#endif
 
 
 // MLM REQ processing function templates
@@ -155,6 +158,11 @@
 #ifdef WLAN_FEATURE_VOWIFI_11R
         case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:limProcessFTPreauthRspTimeout(pMac); break;
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+        case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT:
+             lim_process_preauth_mbb_rsp_timeout(pMac);
+             break;
+#endif
         case SIR_LIM_REMAIN_CHN_TIMEOUT:    limProcessRemainOnChnTimeout(pMac); break;
         case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT:   
                                             limProcessInsertSingleShotNOATimeout(pMac); break;
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index d91635a..4a694f7 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -76,6 +76,10 @@
 #include <limFT.h>
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+#include "lim_mbb.h"
+#endif
+
 
 #define JOIN_FAILURE_TIMEOUT   1000   // in msecs
 /* This overhead is time for sending NOA start to host in case of GO/sending NULL data & receiving ACK 
@@ -5907,6 +5911,13 @@
             break;
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+        case eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ:
+             lim_process_pre_auth_reassoc_req(pMac, pMsg);
+             bufConsumed = FALSE;
+             break;
+#endif
+
 #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
        case eWNI_SME_ESE_ADJACENT_AP_REPORT:
             limProcessAdjacentAPRepMsg ( pMac, pMsgBuf );
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index 0237271..71c7dde 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -64,6 +64,10 @@
    convert  ACTIVE DFS channel to DFS channels */
 #define ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT     1000
 
+#ifdef WLAN_FEATURE_LFR_MBB
+#define PREAUTH_REASSOC_TIMEOUT     500
+#endif
+
 /**
  * limCreateTimers()
  *
@@ -624,6 +628,21 @@
     }
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+    cfgValue = PREAUTH_REASSOC_TIMEOUT;
+    cfgValue = SYS_MS_TO_TICKS(cfgValue);
+
+    if (tx_timer_create(&pMac->lim.limTimers.glim_pre_auth_mbb_rsp_timer,
+                        "PREAUTH MBB RSP TIMEOUT",
+                        limTimerHandler, SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT,
+                        cfgValue, 0,
+                        TX_NO_ACTIVATE) != TX_SUCCESS)
+    {
+        limLog(pMac, LOGP, FL("could not create PREAUTH_MBB_RSP timer"));
+        goto err_timer;
+    }
+#endif
+
 #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
     cfgValue = 5000;
     cfgValue = SYS_MS_TO_TICKS(cfgValue);
@@ -712,6 +731,9 @@
         tx_timer_delete(&pMac->lim.limTimers.gLimEseTsmTimer);
 #endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */
         tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer);
+#ifdef WLAN_FEATURE_LFR_MBB
+        tx_timer_delete(&pMac->lim.limTimers.glim_pre_auth_mbb_rsp_timer);
+#endif
         tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer);
         while(((tANI_S32)--i) >= 0)
         {
@@ -1730,6 +1752,18 @@
             }
             break;
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+        case eLIM_PREAUTH_MBB_RSP_TIMER:
+            if (tx_timer_deactivate(&pMac->lim.limTimers.
+                          glim_pre_auth_mbb_rsp_timer) != TX_SUCCESS) {
+                limLog(pMac, LOGP,
+                       FL("Unable to deactivate preauth response mbb timer"));
+                return;
+            }
+            break;
+#endif
+
 #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
          case eLIM_TSM_TIMER:
              if (tx_timer_deactivate(&pMac->lim.limTimers.gLimEseTsmTimer)
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index 1906182..67e06fc 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -77,7 +77,10 @@
     eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER,
     eLIM_INSERT_SINGLESHOT_NOA_TIMER,
     eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE,
-    eLIM_AUTH_RETRY_TIMER
+    eLIM_AUTH_RETRY_TIMER,
+#ifdef WLAN_FEATURE_LFR_MBB
+    eLIM_PREAUTH_MBB_RSP_TIMER
+#endif
 };
 
 #define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT         500
diff --git a/CORE/MAC/src/pe/lim/limTrace.c b/CORE/MAC/src/pe/lim/limTrace.c
index 662670b..02f3087 100644
--- a/CORE/MAC/src/pe/lim/limTrace.c
+++ b/CORE/MAC/src/pe/lim/limTrace.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -92,6 +92,9 @@
         CASE_RETURN_STRING(eLIM_INSERT_SINGLESHOT_NOA_TIMER);
         CASE_RETURN_STRING(eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE);
         CASE_RETURN_STRING(eLIM_AUTH_RETRY_TIMER);
+#ifdef WLAN_FEATURE_LFR_MBB
+        CASE_RETURN_STRING(eLIM_PREAUTH_MBB_RSP_TIMER);
+#endif
         default:
             return( "UNKNOWN" );
             break;
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 42fe6cd..4936ed9 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -648,6 +648,11 @@
             return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT";
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+        case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT:
+            return "SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT";
+#endif
+
         case SIR_HAL_APP_SETUP_NTF:
             return "SIR_HAL_APP_SETUP_NTF";
         case SIR_HAL_INITIAL_CAL_FAILED_NTF:
diff --git a/CORE/MAC/src/pe/lim/lim_mbb.c b/CORE/MAC/src/pe/lim/lim_mbb.c
new file mode 100644
index 0000000..42e27ef
--- /dev/null
+++ b/CORE/MAC/src/pe/lim/lim_mbb.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "aniGlobal.h"
+#include "limTypes.h"
+#include "limUtils.h"
+#include "limFT.h"
+#include "limSendMessages.h"
+
+/**
+ * lim_post_pre_auth_reassoc_rsp() -Posts preauth_reassoc response to SME
+ * @mac: MAC context
+ * @status: status
+ * @session_entry: session entry
+ *
+ * This function process preauth request received from CSR
+ */
+void lim_post_pre_auth_reassoc_rsp(tpAniSirGlobal mac,
+     tSirRetStatus status, tpPESession session_entry)
+{
+    tpSirFTPreAuthRsp pre_auth_rsp;
+    tSirMsgQ mmh_msg;
+    tANI_U16 rsp_len = sizeof(tSirFTPreAuthRsp);
+
+    pre_auth_rsp = (tpSirFTPreAuthRsp)vos_mem_malloc(rsp_len);
+    if (NULL == pre_auth_rsp) {
+        limLog(mac, LOGE, FL("Failed to allocate memory"));
+        return;
+    }
+
+    vos_mem_zero(pre_auth_rsp, rsp_len);
+    pre_auth_rsp->messageType = eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP;
+    pre_auth_rsp->length = (tANI_U16)rsp_len;
+    pre_auth_rsp->status = status;
+
+    if (session_entry)
+        pre_auth_rsp->smeSessionId = session_entry->smeSessionId;
+
+    /* The bssid of the AP we are sending Auth1 to. */
+    if (mac->ft.ftPEContext.pFTPreAuthReq)
+        sirCopyMacAddr(pre_auth_rsp->preAuthbssId,
+                       mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId);
+
+    if (status != eSIR_SUCCESS) {
+        limLog(mac, LOG1, "Pre-Auth Failed, Cleanup!");
+        limFTCleanup(mac);
+    }
+
+    mmh_msg.type = pre_auth_rsp->messageType;
+    mmh_msg.bodyptr = pre_auth_rsp;
+    mmh_msg.bodyval = 0;
+
+    limLog(mac, LOG1,
+           FL("Posted Auth Rsp to SME with status of 0x%x"), status);
+
+    limSysProcessMmhMsgApi(mac, &mmh_msg, ePROT);
+}
+
+/*
+ * lim_process_preauth_mbb_result() -process pre auth result
+ * @mac: MAC context
+ * @status: status
+ * @data: pointer to data
+ *
+ * This function invokes resume callback
+ */
+static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac,
+     eHalStatus status, tANI_U32 *data)
+{
+    tpPESession session_entry;
+
+    if (!mac->ft.ftPEContext.pFTPreAuthReq) {
+        limLog(mac, LOG1, "Pre-Auth request is NULL!");
+        return;
+    }
+
+    session_entry = (tpPESession)data;
+
+    /* Post the FT Pre Auth Response to SME in case of failure*/
+    if (mac->ft.ftPEContext.ftPreAuthStatus == eSIR_FAILURE) {
+        lim_post_pre_auth_reassoc_rsp(mac,
+                  mac->ft.ftPEContext.ftPreAuthStatus, session_entry);
+        return;
+    }
+
+    /* Flow for preauth success */
+    limFTSetupAuthSession(mac, session_entry);
+}
+
+/*
+ * lim_perform_post_preauth_mbb_channel_change() -invokes resume callback
+ * @mac: MAC context
+ * @status: status
+ * @data: pointer to data
+ * @session_entry: session entry
+ *
+ * This function invokes resume callback after successful reception of
+ * pre auth
+ */
+static inline
+void lim_perform_post_preauth_mbb_channel_change(tpAniSirGlobal mac,
+     eHalStatus status, tANI_U32 *data, tpPESession session_entry)
+{
+    peSetResumeChannel(mac, 0, 0);
+    limResumeLink(mac, lim_process_preauth_mbb_result,
+                                (tANI_U32 *)session_entry);
+}
+
+/*
+ * lim_handle_pre_auth_mbb_rsp() -handles preauth response
+ * @mac: MAC context
+ * @status: status of message
+ * @session_entry: session entry
+ *
+ * This function process preauth response
+ */
+void lim_handle_pre_auth_mbb_rsp(tpAniSirGlobal mac,
+     tSirRetStatus status, tpPESession session_entry)
+{
+    tpPESession ft_session_entry;
+    tANI_U8 session_id;
+    tpSirBssDescription  bss_description;
+
+    mac->ft.ftPEContext.ftPreAuthStatus = status;
+
+    mac->ft.ftPEContext.saved_auth_rsp_length = 0;
+
+    limLog(mac, LOG1, FL("preauth status %d"),
+                         mac->ft.ftPEContext.ftPreAuthStatus);
+
+    /* Create FT session for the re-association at this point */
+    if (mac->ft.ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) {
+        bss_description = mac->ft.ftPEContext.pFTPreAuthReq->pbssDescription;
+        if((ft_session_entry = peCreateSession(mac, bss_description->bssId,
+                                  &session_id, mac->lim.maxStation)) == NULL) {
+            limLog(mac, LOGE,
+                   FL("session can not be created for pre-auth AP"));
+            mac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE;
+            goto out;
+        }
+        ft_session_entry->peSessionId = session_id;
+        sirCopyMacAddr(ft_session_entry->selfMacAddr,
+                                 session_entry->selfMacAddr);
+        sirCopyMacAddr(ft_session_entry->limReAssocbssId,
+                                     bss_description->bssId);
+        ft_session_entry->bssType = session_entry->bssType;
+
+        if (ft_session_entry->bssType == eSIR_INFRASTRUCTURE_MODE)
+            ft_session_entry->limSystemRole = eLIM_STA_ROLE;
+
+        ft_session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+        mac->ft.ftPEContext.pftSessionEntry = ft_session_entry;
+        limLog(mac, LOG1,"%s:created session (%p) with id = %d",
+               __func__, ft_session_entry, ft_session_entry->peSessionId);
+
+        /* Update the ReAssoc BSSID of the current session */
+        sirCopyMacAddr(session_entry->limReAssocbssId, bss_description->bssId);
+        limPrintMacAddr(mac, session_entry->limReAssocbssId, LOG1);
+    }
+out:
+    if (session_entry->currentOperChannel !=
+        mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum) {
+        limChangeChannelWithCallback(mac, session_entry->currentOperChannel,
+              lim_perform_post_preauth_mbb_channel_change, NULL, session_entry);
+     } else {
+        /* Link needs to be resumed as link was suspended for same channel */
+        peSetResumeChannel(mac, 0, 0);
+        limResumeLink(mac, lim_process_preauth_mbb_result,
+                                           (tANI_U32 *)session_entry);
+     }
+}
+
+/**
+ * lim_process_preauth_mbb_rsp_timeout() -Process preauth response timeout
+ * @mac: MAC context
+ *
+ * This function is called if preauth response is not received from the AP
+ * within timeout
+ */
+void lim_process_preauth_mbb_rsp_timeout(tpAniSirGlobal mac)
+{
+    tpPESession session_entry;
+
+    /*
+     * Pre auth is failed. Need to resume link and get back on
+     * to home channel.
+     */
+    limLog(mac, LOG1, FL("Pre-Auth MBB Time Out!!!!"));
+
+    if((session_entry = peFindSessionBySessionId(mac,
+        mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer.sessionId))== NULL) {
+        limLog(mac, LOGE, FL("session does not exist for given session id"));
+        return;
+    }
+
+    /*
+     * To handle the race condition where we recieve preauth rsp after
+     * timer has expired.
+     */
+    if (mac->ft.ftPEContext.pFTPreAuthReq == NULL) {
+        limLog(mac, LOGE, FL("Auth Rsp might already be posted to SME"
+               "and cleanup done! sessionId:%d"),
+                mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer.sessionId);
+        return;
+    }
+
+    if (eANI_BOOLEAN_TRUE ==
+         mac->ft.ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) {
+         limLog(mac, LOGE,
+                FL("Auth rsp already posted to SME session %p"), session_entry);
+         return;
+    } else {
+    /*
+     * Here we are sending preauth rsp with failure state
+     * and which is forwarded to SME. Now, if we receive an preauth
+     * resp from AP with success it would create a FT pesession, but
+     * will be dropped in SME leaving behind the pesession.
+     * Mark Preauth rsp processed so that any rsp from AP is dropped in
+     * limProcessAuthFrameNoSession.
+     */
+     limLog(mac,LOG1,
+            FL("Auth rsp not yet posted to SME session %p)"), session_entry);
+            mac->ft.ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed =
+           eANI_BOOLEAN_TRUE;
+     }
+     /*
+      * Ok, so attempted a Pre-Auth and failed. If we are off channel. We need
+      * to get back.
+      */
+     lim_handle_pre_auth_mbb_rsp(mac, eSIR_FAILURE, session_entry);
+ }
+
+/**
+ * lim_perform_pre_auth_reassoc() -Sends preauth request
+ * @mac: MAC context
+ * @status: status of message
+ * @data: gives information of session
+ * @session_entry: session entry
+ *
+ * This function process preauth request received from CSR
+ */
+static inline
+void lim_perform_pre_auth_reassoc(tpAniSirGlobal mac, eHalStatus status,
+     tANI_U32 *data, tpPESession session_entry)
+{
+    tSirMacAuthFrameBody authFrame;
+
+    if (status != eHAL_STATUS_SUCCESS) {
+        limLog(mac, LOGE,
+               FL("Change channel not successful for pre-auth"));
+        goto preauth_fail;
+    }
+
+    limLog(mac, LOGE,
+           FL("session id %d"), session_entry->peSessionId);
+
+    mac->ft.ftPEContext.psavedsessionEntry = session_entry;
+
+    authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM;
+    authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
+    authFrame.authStatusCode = 0;
+
+    /* Start timer here to come back to operating channel. */
+    mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer.sessionId =
+                                                session_entry->peSessionId;
+
+    limSendAuthMgmtFrame(mac, &authFrame,
+         mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId,
+         LIM_NO_WEP_IN_FC, session_entry, eSIR_FALSE);
+
+    if(TX_SUCCESS !=
+          tx_timer_activate(&mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer)) {
+       limLog(mac, LOGE, FL("Pre Auth MBB Rsp Timer Start Failed"));
+
+       mac->ft.ftPEContext.psavedsessionEntry = NULL;
+       goto preauth_fail;
+    }
+
+    return;
+
+preauth_fail:
+     lim_handle_pre_auth_mbb_rsp(mac, eSIR_FAILURE, session_entry);
+     return;
+}
+
+/**
+ * pre_auth_mbb_suspend_link_handler() -Handler for suspend link
+ * @mac: MAC context
+ * @status: status of message
+ * @data: gives information of session
+ *
+ * This function process preauth request received from CSR
+ */
+static inline
+void pre_auth_mbb_suspend_link_handler(tpAniSirGlobal mac,
+     eHalStatus status, tANI_U32 *data)
+{
+    tpPESession session_entry;
+
+    if (status != eHAL_STATUS_SUCCESS) {
+        limLog(mac, LOGE, FL("Link suspend failed"));
+        lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, (tpPESession)data);
+        return;
+    }
+
+    session_entry = (tpPESession)data;
+
+    if (session_entry->currentOperChannel !=
+                mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum) {
+        limChangeChannelWithCallback(mac,
+                mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum,
+                lim_perform_pre_auth_reassoc, NULL, session_entry);
+        return;
+    } else {
+        lim_perform_pre_auth_reassoc(mac, eHAL_STATUS_SUCCESS,
+                                  NULL, session_entry);
+        return;
+    }
+}
+
+/**
+ * lim_process_pre_auth_reassoc_req() -Process preauth request
+ * @hal: HAL context
+ * @msg: message
+ *
+ * This function process preauth request received from CSR
+ */
+void lim_process_pre_auth_reassoc_req(tpAniSirGlobal mac, tpSirMsgQ msg)
+{
+    tpPESession session_entry;
+    tANI_U8 session_id;
+
+    limFTInit(mac);
+
+    /* Can set it only after sending auth */
+    mac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE;
+
+    /* We need information from the Pre-Auth Req. Lets save that */
+    mac->ft.ftPEContext.pFTPreAuthReq = (tpSirFTPreAuthReq)msg->bodyptr;
+    if (!mac->ft.ftPEContext.pFTPreAuthReq) {
+        limLog(mac, LOGE,
+               FL("pFTPreAuthReq is NULL"));
+        lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL);
+        return;
+    }
+
+    /* Get the current session entry */
+    session_entry = peFindSessionByBssid(mac,
+                    mac->ft.ftPEContext.pFTPreAuthReq->currbssId, &session_id);
+    if (session_entry == NULL) {
+        limLog(mac, LOGE,
+               FL("Unable to find session for the following bssid"));
+        limPrintMacAddr(mac,
+                        mac->ft.ftPEContext.pFTPreAuthReq->currbssId, LOGE);
+
+        /* Post the pre auth response to SME */
+        lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL);
+    }
+
+    limLog(mac, LOG1,
+           FL("set link with eSIR_LINK_PRE_AUTH_REASSOC_STATE"));
+
+    if (limSetLinkState(mac, eSIR_LINK_PRE_AUTH_REASSOC_STATE,
+                        session_entry->bssId, session_entry->selfMacAddr,
+                        NULL, NULL) != eSIR_SUCCESS) {
+        limLog(mac, LOGE,
+               FL("set link failed for eSIR_LINK_PRE_AUTH_REASSOC_STATE"));
+        lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL);
+        return;
+    }
+
+    /*
+     * Suspend link for same channel or different channel so that STA
+     * can be in power save for connected AP.
+     */
+    limLog(mac, LOG1,
+           FL("pre-auth on channel %d (session %p) currentOperChannel %d"),
+           mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum,
+           session_entry, session_entry->currentOperChannel);
+    limSuspendLink(mac, eSIR_CHECK_ROAMING_SCAN,
+                   pre_auth_mbb_suspend_link_handler,
+                  (tANI_U32 *)session_entry);
+}
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index e92ff99..08fac82 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -1199,6 +1199,11 @@
     v_U32_t PERtimerThreshold;
     v_U32_t PERroamTriggerPercent;
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    tANI_BOOLEAN enable_lfr_mbb;
+#endif
+
 #endif
 
     tANI_BOOLEAN ignorePeerErpInfo;
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index a780af6..c31a36b 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -206,7 +206,7 @@
     eCsrLostLink1Abort,
     eCsrLostLink2Abort,
     eCsrLostLink3Abort,
-
+    ecsr_mbb_perform_preauth_reassoc,
 }eCsrRoamReason;
 
 typedef enum
@@ -636,6 +636,10 @@
 #endif
 #endif
 
+#ifdef WLAN_FEATURE_LFR_MBB
+    tANI_BOOLEAN enable_lfr_mbb;
+#endif
+
 #ifdef FEATURE_WLAN_ESE
     tANI_U8   isEseIniFeatureEnabled;
 #endif
diff --git a/CORE/SME/inc/csrNeighborRoam.h b/CORE/SME/inc/csrNeighborRoam.h
index 5df4eee..aa427ce 100644
--- a/CORE/SME/inc/csrNeighborRoam.h
+++ b/CORE/SME/inc/csrNeighborRoam.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -55,6 +55,10 @@
     eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING,
     eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE,
 #endif /* WLAN_FEATURE_VOWIFI_11R */    
+#ifdef WLAN_FEATURE_LFR_MBB
+    eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC,
+#endif
+
     eNEIGHBOR_STATE_MAX
 } eCsrNeighborRoamState;
 
@@ -206,6 +210,11 @@
     vos_timer_t                 forcedInitialRoamTo5GHTimer;
     tANI_U8                     isForcedInitialRoamTo5GH;
     tANI_U8                     lastSentCmd;
+
+#ifdef WLAN_FEATURE_LFR_MBB
+     bool is_pre_auth_reassoc_mbb_timer_started;
+#endif
+
 } tCsrNeighborRoamControlInfo, *tpCsrNeighborRoamControlInfo;
 
 
@@ -251,6 +260,15 @@
                                             tANI_U8  *pOutputChannelList,
                                             tANI_U8  outputNumOfChannels,
                                             tANI_U8  *pMergedOutputNumOfChannels);
+tANI_BOOLEAN
+csrNeighborRoamRemoveRoamableAPListEntry(tpAniSirGlobal pMac,
+                 tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry);
+eHalStatus
+csrNeighborRoamAddBssIdToPreauthFailList(tpAniSirGlobal pMac,
+                                                          tSirMacAddr bssId);
+void csrNeighborRoamFreeNeighborRoamBSSNode(tpAniSirGlobal pMac,
+                              tpCsrNeighborRoamBSSInfo neighborRoamBSSNode);
+
 
 #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
 #define ROAM_SCAN_OFFLOAD_START                     1
diff --git a/CORE/SME/inc/csr_roam_mbb.h b/CORE/SME/inc/csr_roam_mbb.h
new file mode 100644
index 0000000..aa0bcbc
--- /dev/null
+++ b/CORE/SME/inc/csr_roam_mbb.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+eHalStatus csr_neighbor_roam_issue_preauth_reassoc(tpAniSirGlobal mac);
+
+eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal,
+                     tANI_U32 session_id, tpSirBssDescription bss_description);
+
+void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal,
+                          tpSirFTPreAuthRsp pre_auth_rsp);
+
+void csr_preauth_reassoc_mbb_timer_callback(void *context);
+
+void csr_stop_preauth_reassoc_mbb_timer(tpAniSirGlobal mac);
+
diff --git a/CORE/SME/inc/sme_FTApi.h b/CORE/SME/inc/sme_FTApi.h
index 4eed9f5..0a57aa5 100644
--- a/CORE/SME/inc/sme_FTApi.h
+++ b/CORE/SME/inc/sme_FTApi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -72,6 +72,12 @@
     tCsrRoamSetKey    *pCsrFTKeyInfo;
 
     v_BOOL_t          addMDIE;
+
+    tANI_BOOLEAN is_preauth_lfr_mbb;
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    vos_timer_t       pre_auth_reassoc_mbb_timer;
+#endif
 } tftSMEContext, *tpftSMEContext;
 
 /*--------------------------------------------------------------------------
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index 4c6aa21..edfd45e 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -76,6 +76,11 @@
 #include "csrEse.h"
 #endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */
 #include "vos_utils.h"
+#ifdef WLAN_FEATURE_LFR_MBB
+#include "csr_roam_mbb.h"
+#endif
+
+
 #define CSR_NUM_IBSS_START_CHANNELS_50      4
 #define CSR_NUM_IBSS_START_CHANNELS_24      3
 #define CSR_DEF_IBSS_START_CHANNEL_50       36
@@ -1976,6 +1981,11 @@
                 pParam->PERMinRssiThresholdForRoam;
         pMac->PERroamTimeout = pParam->waitPeriodForNextPERScan;
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+        pMac->roam.configParam.enable_lfr_mbb = pParam->enable_lfr_mbb;
+#endif
+
 #ifdef FEATURE_WLAN_LFR
         pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled;
         pMac->roam.configParam.MAWCEnabled = pParam->MAWCEnabled;
@@ -2206,6 +2216,11 @@
         pParam->PERMinRssiThresholdForRoam =
                 pMac->roam.configParam.PERMinRssiThresholdForRoam;
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+        pParam->enable_lfr_mbb = pMac->roam.configParam.enable_lfr_mbb;
+#endif
+
 #ifdef FEATURE_WLAN_LFR
         pParam->isFastRoamIniFeatureEnabled = pMac->roam.configParam.isFastRoamIniFeatureEnabled;
 #endif
@@ -5064,6 +5079,14 @@
                 pCommand->u.roamCmd.pLastRoamBss);
         break;
 
+#ifdef WLAN_FEATURE_LFR_MBB
+    case ecsr_mbb_perform_preauth_reassoc:
+        smsLog(pMac, LOG1, FL("Attempting MBB PreAuth/Reassoc Req"));
+        status = csr_roam_issue_preauth_reassoc_req(pMac, sessionId,
+                pCommand->u.roamCmd.pLastRoamBss);
+        break;
+#endif
+
     default:
         csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId );
 
@@ -7391,6 +7414,9 @@
                 csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
             }
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+            csr_stop_preauth_reassoc_mbb_timer(pMac);
+#endif
         }
 
         if( fDisassoc )
@@ -10050,6 +10076,10 @@
                         csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
                     }
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+                    csr_stop_preauth_reassoc_mbb_timer(pMac);
+#endif
+
                     pSession = CSR_GET_SESSION( pMac, sessionId );
 
                     if (!pSession)
@@ -10126,6 +10156,9 @@
                     csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
                 }
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+                csr_stop_preauth_reassoc_mbb_timer(pMac);
+#endif
                 pSession = CSR_GET_SESSION( pMac, sessionId );
 
                 if(!pSession)
@@ -10918,6 +10951,13 @@
             csrRoamFTPreAuthRspProcessor( pMac, (tpSirFTPreAuthRsp)pSirMsg );
             break;
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+        case eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP:
+             csr_roam_preauth_rsp_mbb_processor(pMac,
+                                           (tpSirFTPreAuthRsp)pSirMsg);
+             break;
+#endif
+
         case eWNI_SME_MAX_ASSOC_EXCEEDED:
             pSmeMaxAssocInd = (tSmeMaxAssocInd*)pSirMsg;
             smsLog( pMac, LOG1, FL("send indication that max assoc have been reached and the new peer cannot be accepted"));
diff --git a/CORE/SME/src/csr/csrInsideApi.h b/CORE/SME/src/csr/csrInsideApi.h
index a57a09c..1d5cbc0 100644
--- a/CORE/SME/src/csr/csrInsideApi.h
+++ b/CORE/SME/src/csr/csrInsideApi.h
@@ -273,6 +273,10 @@
 void csrRoamJoinedStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf );
 tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp );
 void csrReleaseCommandRoam(tpAniSirGlobal pMac, tSmeCmd *pCommand);
+tpCsrNeighborRoamBSSInfo csrNeighborRoamGetRoamableAPListNextEntry(tpAniSirGlobal pMac,
+                                        tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry);
+v_U8_t *csrNeighborRoamStateToString(v_U8_t state);
+void csrReleaseCommandPreauth(tpAniSirGlobal pMac, tSmeCmd *pCommand);
 void csrReleaseCommandScan(tpAniSirGlobal pMac, tSmeCmd *pCommand);
 void csrReleaseCommandWmStatusChange(tpAniSirGlobal pMac, tSmeCmd *pCommand);
 //pIes2 can be NULL
diff --git a/CORE/SME/src/csr/csrNeighborRoam.c b/CORE/SME/src/csr/csrNeighborRoam.c
index da1f2cf..8b7e2cb 100644
--- a/CORE/SME/src/csr/csrNeighborRoam.c
+++ b/CORE/SME/src/csr/csrNeighborRoam.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -72,6 +72,9 @@
 #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
 #include "csrEse.h"
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+#include "csr_roam_mbb.h"
+#endif
 
 #define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1
 #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG
@@ -253,6 +256,24 @@
                                           tpCsrNeighborRoamControlInfo pNeighborRoamInfo)
 {
     eHalStatus status = eHAL_STATUS_SUCCESS;
+
+    if (pMac->roam.configParam.enable_lfr_mbb
+#ifdef WLAN_FEATURE_LFR_MBB
+        && (!pNeighborRoamInfo->is11rAssoc)
+#ifdef FEATURE_WLAN_ESE
+        && (!pNeighborRoamInfo->isESEAssoc)
+#endif
+       )
+    {
+       smsLog(pMac, LOG1,
+              FL("Issuing preauth reassoc"));
+       status = csr_neighbor_roam_issue_preauth_reassoc(pMac);
+       return status;
+    }
+
+
+#endif
+
 #ifdef WLAN_FEATURE_VOWIFI_11R
     if ((pNeighborRoamInfo->is11rAssoc)
 #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
@@ -4442,6 +4463,10 @@
 #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
             }
 #endif
+
+#ifdef WLAN_FEATURE_LFR_MBB
+            csr_stop_preauth_reassoc_mbb_timer(pMac);
+#endif
             break;
 
         case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN:
diff --git a/CORE/SME/src/csr/csr_roam_mbb.c b/CORE/SME/src/csr/csr_roam_mbb.c
new file mode 100644
index 0000000..d04247e
--- /dev/null
+++ b/CORE/SME/src/csr/csr_roam_mbb.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "aniGlobal.h"
+#include "smeInside.h"
+#include "csrInsideApi.h"
+#include "smsDebug.h"
+#include "macTrace.h"
+#include "csrNeighborRoam.h"
+
+#define PREAUTH_REASSOC_MBB_TIMER_VALUE    60
+
+#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(newState)\
+{\
+    mac->roam.neighborRoamInfo.prevNeighborRoamState = mac->roam.neighborRoamInfo.neighborRoamState;\
+    mac->roam.neighborRoamInfo.neighborRoamState = newState;\
+    VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, \
+               FL("Neighbor Roam Transition from state %s ==> %s"), \
+               csrNeighborRoamStateToString (mac->roam.neighborRoamInfo.prevNeighborRoamState), \
+               csrNeighborRoamStateToString (newState));\
+}
+
+/**
+ * csr_roam_issue_preauth_reassoc_req() -Prepares preauth request
+ * @hal: HAL context
+ * @session_id: session id
+ * @bss_description: BSS description
+ *
+ * This function prepares preauth request and sends request to PE
+ *
+ * Return: eHAL_STATUS_SUCCESS on success,
+ *           : eHAL_STATUS_RESOURCES when resource allocation is failure
+ *           : eHAL_STATUS_FAILURE otherwise
+ */
+eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal,
+                     tANI_U32 session_id, tpSirBssDescription bss_description)
+{
+    tpAniSirGlobal mac = PMAC_STRUCT(hal);
+    tpSirFTPreAuthReq pre_auth_req;
+    tANI_U16 auth_req_len = 0;
+    tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id);
+
+    auth_req_len = sizeof(tSirFTPreAuthReq);
+    pre_auth_req = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len);
+    if (NULL == pre_auth_req) {
+        smsLog(mac, LOGE,
+               FL("Memory allocation for Preauth request failed"));
+        return eHAL_STATUS_RESOURCES;
+    }
+
+    /*
+     * Save the SME Session ID here. We need it while processing
+     * the preauth response.
+     */
+    mac->ft.ftSmeContext.smeSessionId = session_id;
+    vos_mem_zero(pre_auth_req, auth_req_len);
+
+    pre_auth_req->pbssDescription = (tpSirBssDescription)vos_mem_malloc(
+            sizeof(bss_description->length) + bss_description->length);
+
+    pre_auth_req->messageType =
+                     pal_cpu_to_be16(eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ);
+
+    pre_auth_req->preAuthchannelNum = bss_description->channelId;
+
+    /*
+     * Set is_preauth_lfr_mbb which will be checked in
+     * limProcessAuthFrameNoSession
+     */
+    mac->ft.ftSmeContext.is_preauth_lfr_mbb = true;
+    smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"),
+           mac->ft.ftSmeContext.is_preauth_lfr_mbb);
+
+    vos_mem_copy((void *)&pre_auth_req->currbssId,
+                 (void *)session->connectedProfile.bssid, sizeof(tSirMacAddr));
+    vos_mem_copy((void *)&pre_auth_req->preAuthbssId,
+                 (void *)bss_description->bssId, sizeof(tSirMacAddr));
+
+    vos_mem_copy(pre_auth_req->pbssDescription, bss_description,
+                 sizeof(bss_description->length) + bss_description->length);
+    pre_auth_req->length = pal_cpu_to_be16(auth_req_len);
+    return palSendMBMessage(mac->hHdd, pre_auth_req);
+}
+
+/**
+ * csr_neighbor_roam_issue_preauth_reassoc() -issues  preauth_reassoc request
+ * @mac: MAC context
+ *
+ * This function issues preauth_reassoc request to PE with the 1st AP
+ * entry in the roamable AP list
+ *
+ * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise
+ */
+eHalStatus csr_neighbor_roam_issue_preauth_reassoc(tpAniSirGlobal mac)
+{
+    tpCsrNeighborRoamControlInfo neighbor_roam_info =
+                                           &mac->roam.neighborRoamInfo;
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+    tpCsrNeighborRoamBSSInfo neighbor_bss_node;
+
+    VOS_ASSERT(neighbor_roam_info->FTRoamInfo.preauthRspPending ==
+                                                         eANI_BOOLEAN_FALSE);
+
+    neighbor_bss_node = csrNeighborRoamGetRoamableAPListNextEntry(mac,
+                               &neighbor_roam_info->roamableAPList, NULL);
+
+    if (neighbor_bss_node == NULL)
+    {
+        smsLog(mac, LOGE, FL("Roamable AP list is empty"));
+        return eHAL_STATUS_FAILURE;
+    }
+    else
+    {
+        status = csrRoamEnqueuePreauth(mac,
+                 neighbor_roam_info->csrSessionId,
+                 neighbor_bss_node->pBssDescription,
+                 ecsr_mbb_perform_preauth_reassoc,
+                 eANI_BOOLEAN_TRUE);
+
+        smsLog(mac, LOG1, FL("Before Pre-Auth: BSSID "MAC_ADDRESS_STR", Ch:%d"),
+               MAC_ADDR_ARRAY(neighbor_bss_node->pBssDescription->bssId),
+               neighbor_bss_node->pBssDescription->channelId);
+
+        if (eHAL_STATUS_SUCCESS != status)
+        {
+            smsLog(mac, LOGE,
+                   FL("Send Preauth request to PE failed with status %d"),
+                   status);
+            return status;
+        }
+    }
+
+    neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_TRUE;
+
+    CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)
+    return status;
+}
+
+/**
+ * csr_stop_preauth_reassoc_mbb_timer() -stops preauth_reassoc timer
+ * @mac: MAC context
+ *
+ * This function stops preauth_reassoc timer
+ *
+ */
+void csr_stop_preauth_reassoc_mbb_timer(tpAniSirGlobal mac)
+{
+    if (mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started)
+        vos_timer_stop(&mac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer);
+}
+
+
+/**
+ * csr_preauth_reassoc_mbb_timer_callback() -preauth_reassoc timer callback
+ * @mac: MAC context
+ *
+ * This function issues preauth_reassoc with another roamable entry
+ *
+ */
+void csr_preauth_reassoc_mbb_timer_callback(void *context)
+{
+    tpAniSirGlobal mac = (tpAniSirGlobal)context;
+
+    mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = 0;
+    csr_neighbor_roam_issue_preauth_reassoc(mac);
+}
+
+
+/**
+ * csr_roam_dequeue_preauth_reassoc() -Dequeues
+ * ecsr_mbb_perform_preauth_reassoc
+ * @mac: MAC context
+ *
+ * This function dequeues ecsr_mbb_perform_preauth_reassoc
+ *
+ */
+eHalStatus csr_roam_dequeue_preauth_reassoc(tpAniSirGlobal mac)
+{
+    tListElem *entry;
+    tSmeCmd *command;
+    entry = csrLLPeekHead(&mac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
+    if (entry) {
+        command = GET_BASE_ADDR(entry, tSmeCmd, Link);
+        if ((eSmeCommandRoam == command->command) &&
+            (ecsr_mbb_perform_preauth_reassoc ==
+                                    command->u.roamCmd.roamReason)) {
+            smsLog(mac, LOG1, FL("DQ-Command = %d, Reason = %d"),
+                    command->command, command->u.roamCmd.roamReason);
+            if (csrLLRemoveEntry( &mac->sme.smeCmdActiveList,
+                                       entry, LL_ACCESS_LOCK)) {
+                csrReleaseCommandPreauth( mac, command );
+            }
+        } else {
+            smsLog(mac, LOGE, FL("Command = %d, Reason = %d "),
+                    command->command, command->u.roamCmd.roamReason);
+        }
+    }
+    else {
+        smsLog(mac, LOGE,
+               FL("pEntry NULL for eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP"));
+    }
+    smeProcessPendingQueue( mac );
+    return eHAL_STATUS_SUCCESS;
+}
+
+/**
+ * csr_neighbor_roam_preauth_reassoc_rsp_handler() -handles preauth
+ * reassoc response
+ * @mac: MAC context
+ * @lim_status: status of preauth reassoc response from lim
+ *
+ * This function handles preauth_reassoc response from PE. When
+ * preauth_reassoc response failure is received, preauth reassoc
+ * with new candidate will be attempted. In success case, candidate will be
+ * removed from roamable entry.
+ *
+ */
+eHalStatus
+csr_neighbor_roam_preauth_reassoc_rsp_handler(tpAniSirGlobal mac,
+          tSirRetStatus lim_status)
+{
+    tpCsrNeighborRoamControlInfo neighbor_roam_info =
+                                      &mac->roam.neighborRoamInfo;
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+    eHalStatus preauth_processed = eHAL_STATUS_SUCCESS;
+    tpCsrNeighborRoamBSSInfo preauth_rsp_node = NULL;
+
+    if (eANI_BOOLEAN_FALSE ==
+                neighbor_roam_info->FTRoamInfo.preauthRspPending) {
+       /*
+        * This can happen when we disconnect immediately after sending
+        * a pre-auth request. During processing of the disconnect command,
+        * we would have reset preauthRspPending and transitioned to INIT state.
+        */
+       smsLog(mac, LOGE,
+              FL("Unexpected pre-auth response in state %d"),
+              neighbor_roam_info->neighborRoamState);
+       preauth_processed = eHAL_STATUS_FAILURE;
+       goto DEQ_PREAUTH;
+    }
+
+    if ((neighbor_roam_info->neighborRoamState !=
+                            eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)) {
+        smsLog(mac, LOGE,
+               FL("Preauth response received in state %s"),
+               macTraceGetNeighbourRoamState(
+                      neighbor_roam_info->neighborRoamState));
+        preauth_processed = eHAL_STATUS_FAILURE;
+        goto DEQ_PREAUTH;
+    }
+
+    neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE;
+
+    if (eSIR_SUCCESS == lim_status)
+        preauth_rsp_node = csrNeighborRoamGetRoamableAPListNextEntry(mac,
+                                  &neighbor_roam_info->roamableAPList, NULL);
+
+    if ((eSIR_SUCCESS == lim_status) && (NULL != preauth_rsp_node)) {
+        smsLog(mac, LOG1, FL("MBB Reassoc completed successfully"));
+
+        smsLog(mac, LOG1, FL("After MBB reassoc BSSID "MAC_ADDRESS_STR" Ch %d"),
+               MAC_ADDR_ARRAY(preauth_rsp_node->pBssDescription->bssId),
+               preauth_rsp_node->pBssDescription->channelId);
+
+        /*
+        * MBB Reassoc competer successfully. Insert the preauthenticated
+        * node to tail of preAuthDoneList
+        */
+        csrNeighborRoamRemoveRoamableAPListEntry(mac,
+                         &neighbor_roam_info->roamableAPList, preauth_rsp_node);
+        csrLLInsertTail(&neighbor_roam_info->FTRoamInfo.preAuthDoneList,
+                                  &preauth_rsp_node->List, LL_ACCESS_LOCK);
+    } else {
+        tpCsrNeighborRoamBSSInfo    neighbor_bss_node = NULL;
+        tListElem                   *entry;
+
+        smsLog(mac, LOG1,
+               FL("Pre-Auth failed BSSID "MAC_ADDRESS_STR" Ch:%d status = %d"),
+               MAC_ADDR_ARRAY(preauth_rsp_node->pBssDescription->bssId),
+               preauth_rsp_node->pBssDescription->channelId, lim_status);
+
+        /*
+        * Pre-auth failed. Add the bssId to the preAuth failed list MAC Address.
+        * Also remove the AP from roamable AP list. The one in the head of the
+        * list should be one with which we issued pre-auth and failed.
+        */
+        entry = csrLLRemoveHead(&neighbor_roam_info->roamableAPList,
+                                  LL_ACCESS_LOCK);
+        if(entry) {
+           neighbor_bss_node = GET_BASE_ADDR(entry,
+                                            tCsrNeighborRoamBSSInfo, List);
+           /*
+            * Add the BSSID to pre-auth fail list if it is
+            * not requested by HDD
+            */
+           status = csrNeighborRoamAddBssIdToPreauthFailList(mac,
+                                 neighbor_bss_node->pBssDescription->bssId);
+
+           /* Now we can free this node */
+           csrNeighborRoamFreeNeighborRoamBSSNode(mac, neighbor_bss_node);
+        }
+
+        /* Dequeue ecsr_mbb_perform_preauth_reassoc */
+        csr_roam_dequeue_preauth_reassoc(mac);
+
+        /*
+        * Move state to Connected. Connected state here signifies connection
+        * with current AP as preauth failed with roamable AP. Still driver has
+        * connection with current AP.
+        */
+        CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
+
+        /* Start a timer to issue preauth_reassoc request for the next entry*/
+        status = vos_timer_start(&mac->ft.ftSmeContext.
+                   pre_auth_reassoc_mbb_timer, PREAUTH_REASSOC_MBB_TIMER_VALUE);
+        if (eHAL_STATUS_SUCCESS != status) {
+            smsLog(mac, LOGE,
+                   FL("pre_auth_reassoc_mbb_timer start failed status %d"),
+                   status);
+            return eHAL_STATUS_FAILURE;
+        }
+        mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = true;
+        return eHAL_STATUS_SUCCESS;
+    }
+
+DEQ_PREAUTH:
+    csr_roam_dequeue_preauth_reassoc(mac);
+    return preauth_processed;
+}
+
+/**
+ * csr_roam_preauth_rsp_mbb_processor() -handles
+ * eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP
+ * @hal: HAL context
+ *
+ * This function invokes preauth reassoc response handler and
+ * updates CSR with new connection information.
+ *
+ */
+void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal,
+     tpSirFTPreAuthRsp pre_auth_rsp)
+{
+    tpAniSirGlobal mac = PMAC_STRUCT(hal);
+    eHalStatus  status;
+
+    mac->ft.ftSmeContext.is_preauth_lfr_mbb = false;
+    smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"),
+                         mac->ft.ftSmeContext.is_preauth_lfr_mbb);
+
+    status = csr_neighbor_roam_preauth_reassoc_rsp_handler(mac,
+                                                pre_auth_rsp->status);
+    if (status != eHAL_STATUS_SUCCESS) {
+        smsLog(mac, LOGE,FL("Preauth was not processed: %d SessionID: %d"),
+                            status, pre_auth_rsp->smeSessionId);
+        return;
+    }
+
+    /*
+     * The below function calls/timers should be invoked only
+     * if the pre-auth is successful.
+     */
+    if (VOS_STATUS_SUCCESS != (VOS_STATUS)pre_auth_rsp->status)
+        return;
+
+    mac->ft.ftSmeContext.FTState = eFT_AUTH_COMPLETE;
+
+    /* Save the received response */
+    vos_mem_copy((void *)&mac->ft.ftSmeContext.preAuthbssId,
+                 (void *)pre_auth_rsp->preAuthbssId, sizeof(tCsrBssid));
+
+
+    /* To Do: add code to update CSR for new connection */
+
+    CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
+}
+
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 0fcac9f..0dd99ae 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -1537,6 +1537,10 @@
 #if defined WLAN_FEATURE_VOWIFI_11R
       sme_FTOpen(pMac);
 #endif
+#ifdef WLAN_FEATURE_LFR_MBB
+
+#endif
+
       sme_p2pOpen(pMac);
       smeTraceInit(pMac);
       sme_register_debug_callback();
diff --git a/CORE/SME/src/sme_common/sme_FTApi.c b/CORE/SME/src/sme_common/sme_FTApi.c
index 4d988af..c791338 100644
--- a/CORE/SME/src/sme_common/sme_FTApi.c
+++ b/CORE/SME/src/sme_common/sme_FTApi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -41,6 +41,11 @@
 #include <csrNeighborRoam.h>
 #include "vos_utils.h"
 
+#ifdef WLAN_FEATURE_LFR_MBB
+#include "csr_roam_mbb.h"
+#endif
+
+
 /*--------------------------------------------------------------------------
   Initialize the FT context. 
   ------------------------------------------------------------------------*/
@@ -60,6 +65,18 @@
         return;
     }                 
     vos_reset_roam_timer_log();
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    status = vos_timer_init(&pMac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer,
+                            VOS_TIMER_TYPE_SW,
+                            csr_preauth_reassoc_mbb_timer_callback,
+                            (void *)pMac);
+
+    if (eHAL_STATUS_SUCCESS != status) {
+        smsLog(pMac, LOGE, FL("pre_auth_reassoc_mbb_timer allocation failed"));
+        return;
+    }
+#endif
 }
 
 /*--------------------------------------------------------------------------
@@ -71,6 +88,10 @@
     //Clear the FT Context.
     sme_FTReset(hHal);
     vos_timer_destroy(&pMac->ft.ftSmeContext.preAuthReassocIntvlTimer);
+
+#ifdef WLAN_FEATURE_LFR_MBB
+    vos_timer_destroy(&pMac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer);
+#endif
 }
 
 void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state)
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index ff50926..c275cb0 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -137,6 +137,9 @@
         CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING);
         CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE);
         #endif /* WLAN_FEATURE_VOWIFI_11R */
+        #ifdef WLAN_FEATURE_LFR_MBB
+        CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC);
+        #endif
         CASE_RETURN_STRING(eNEIGHBOR_STATE_MAX);
 
         default:
@@ -572,6 +575,10 @@
         CASE_RETURN_STRING(eWNI_SME_UPDATE_MAX_RATE_IND);
         CASE_RETURN_STRING(eWNI_SME_SET_TDLS_2040_BSSCOEX_REQ);
         CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB);
+#ifdef WLAN_FEATURE_LFR_MBB
+        CASE_RETURN_STRING(eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ);
+        CASE_RETURN_STRING(eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP);
+#endif
         CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END);
         CASE_RETURN_STRING(eWNI_SME_CAP_TSF_REQ);
         CASE_RETURN_STRING(eWNI_SME_GET_TSF_REQ);
@@ -983,6 +990,11 @@
         CASE_RETURN_STRING(SIR_LIM_DEAUTH_ACK_TIMEOUT);
         CASE_RETURN_STRING(SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT);
         CASE_RETURN_STRING(SIR_LIM_AUTH_RETRY_TIMEOUT);
+
+#ifdef WLAN_FEATURE_LFR_MBB
+       CASE_RETURN_STRING(SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT);
+#endif
+
         CASE_RETURN_STRING(SIR_LIM_MSG_TYPES_END);
         CASE_RETURN_STRING(LIM_MLM_SCAN_REQ);
         CASE_RETURN_STRING(LIM_MLM_SCAN_CNF);
diff --git a/Kbuild b/Kbuild
index a7d0f57..dfa683e 100644
--- a/Kbuild
+++ b/Kbuild
@@ -23,6 +23,9 @@
 #Flag to enable Legacy Fast Roaming(LFR)
     CONFIG_PRIMA_WLAN_LFR := y
 
+#Flag to enable Legacy Fast Roaming(LFR) Make Before Break
+    CONFIG_PRIMA_WLAN_LFR_MBB := y
+
 #JB kernel has PMKSA patches, hence enabling this flag
     CONFIG_PRIMA_WLAN_OKC := y
 
@@ -233,6 +236,10 @@
 MAC_LIM_OBJS += $(MAC_SRC_DIR)/pe/lim/limProcessTdls.o
 endif
 
+ifeq ($(CONFIG_PRIMA_WLAN_LFR_MBB),y)
+MAC_LIM_OBJS += $(MAC_SRC_DIR)/pe/lim/lim_mbb.o
+endif
+
 MAC_PMM_OBJS := $(MAC_SRC_DIR)/pe/pmm/pmmAP.o \
 		$(MAC_SRC_DIR)/pe/pmm/pmmApi.o \
 		$(MAC_SRC_DIR)/pe/pmm/pmmDebug.o
@@ -294,6 +301,10 @@
 SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csrTdlsProcess.o
 endif
 
+ifeq ($(CONFIG_PRIMA_WLAN_LFR_MBB),y)
+SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csr_roam_mbb.o
+endif
+
 SME_PMC_OBJS := $(SME_SRC_DIR)/pmc/pmcApi.o \
 		$(SME_SRC_DIR)/pmc/pmc.o \
 		$(SME_SRC_DIR)/pmc/pmcLogDump.o
@@ -627,6 +638,10 @@
 CDEFINES += -DFEATURE_WLAN_LFR
 endif
 
+ifeq ($(CONFIG_PRIMA_WLAN_LFR_MBB),y)
+CDEFINES += -DWLAN_FEATURE_LFR_MBB
+endif
+
 ifeq ($(CONFIG_PRIMA_WLAN_OKC),y)
 CDEFINES += -DFEATURE_WLAN_OKC
 endif