qcacld-2.0: SAP to follow STA channel in concurrency

In SAP+STA mode, SAP to switch channel to STA operating
channel by transmitting CSA, instead of direct restarting
on new channel.

Change-Id: I512100d83b2597d9d729ec1ea42c08888ad37f41
CRs-Fixed: 2178029
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index a4dc09d..8265db1 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -5061,6 +5061,15 @@
 #define CFG_ENABLE_MONITOR_ON_STA_MAX     (1)
 #define CFG_ENABLE_MONITOR_ON_STA_DEFAULT (0)
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+/*SAP Channel Switch Support*/
+#define CFG_SAP_CHANNEL_SWITCH_WITH_CSA_NAME "gSAPChannelSwitchWithCSA"
+#define CFG_SAP_CHANNEL_SWITCH_WITH_CSA_MIN      (0)
+#define CFG_SAP_CHANNEL_SWITCH_WITH_CSA_MAX      (1)
+#define CFG_SAP_CHANNEL_SWITCH_WITH_CSA_DEFAULT  (0)
+
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 /*---------------------------------------------------------------------------
   Type declarations
   -------------------------------------------------------------------------*/
@@ -5957,6 +5966,10 @@
    uint32_t  cca_threshold_2g;
    uint32_t  cca_threshold_5g;
    uint8_t                     mon_on_sta_enable;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+   uint32_t                    sap_ch_switch_with_csa;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 };
 
 typedef struct hdd_config hdd_config_t;
diff --git a/CORE/HDD/inc/wlan_hdd_hostapd.h b/CORE/HDD/inc/wlan_hdd_hostapd.h
index 2a08dc9..a45564d 100644
--- a/CORE/HDD/inc/wlan_hdd_hostapd.h
+++ b/CORE/HDD/inc/wlan_hdd_hostapd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -123,7 +123,20 @@
 {
 }
 #endif /* SAP_AUTH_OFFLOAD */
+
 int hdd_softap_set_channel_change(struct net_device *dev, int target_channel);
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+VOS_STATUS hdd_sta_state_sap_notify(hdd_context_t *hdd_context,
+                                sta_sap_notifications event,
+                                struct wlan_sap_csa_info csa_info);
+VOS_STATUS hdd_send_sap_event(struct net_device *dev,
+                sta_sap_notifications event,
+                struct wlan_sap_csa_info csa_info,
+                struct wireless_dev *wdev);
+void hdd_hostapd_chan_switch_cb(v_PVOID_t usrDataForCallback);
+
+int hdd_softap_set_channel_change(struct net_device *dev, int target_channel);
+#endif //WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 
 /**
  * hdd_is_sta_connection_pending() - This function will check if sta connection
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 82e8d7d..b761d52 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1735,6 +1735,21 @@
 	uint32_t clock_freq;
 };
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+typedef struct sap_ch_switch_with_csa_ctx
+{
+    v_BOOL_t is_ch_sw_through_sta_csa;
+    u_int8_t tbtt_count;
+    v_U8_t csa_to_channel; //channel on which SAP will move after sending CSA
+    v_U8_t sap_chan_sw_pending; //SAP channel switch pending after STA disconnect
+    vos_timer_t hdd_ap_chan_switch_timer; //timer to init SAP chan switch
+    v_BOOL_t chan_sw_timer_initialized;
+    v_U8_t def_csa_channel_on_disc;
+    v_BOOL_t scan_only_dfs_channels;
+    struct mutex sap_ch_sw_lock; //Synchronize access to sap_chan_sw_pending
+}sap_ch_switch_ctx;
+#endif
+
 /** Adapter stucture definition */
 
 struct hdd_context_s
@@ -2134,6 +2149,9 @@
     /* flag to show whether moniotr mode is enabled */
     bool is_mon_enable;
     v_MACADDR_t hw_macaddr;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    sap_ch_switch_ctx  ch_switch_ctx;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_CHAN
 };
 
 /*---------------------------------------------------------------------------
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index d2166d0..1c16702 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -75,6 +75,10 @@
 
 #include "adf_trace.h"
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+#include "wlan_hdd_hostapd.h"
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 struct ether_addr
 {
     u_char  ether_addr_octet[6];
@@ -1635,6 +1639,21 @@
             }
 #endif
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+            if((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) &&
+                    vos_is_ch_switch_with_csa_enabled())
+            {
+                struct wlan_sap_csa_info csa_info;
+                hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+                    "%s: Indicate disconnected event to HostApd",
+                    __func__);
+
+                csa_info.sta_channel = 0;
+                /*Indicate to HostApd about Station interface state change*/
+                hdd_sta_state_sap_notify(pHddCtx, STA_NOTIFY_DISCONNECTED, csa_info);
+            }
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
             //If the Device Mode is Station
             // and the P2P Client is Connected
             //Enable BMPS
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index a1e8202..e27bb04 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -4279,6 +4279,16 @@
               CFG_CONNECT_BLOCK_DURATION_MAX ),
 #endif /* SAP_AUTH_OFFLOAD */
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+   REG_VARIABLE( CFG_SAP_CHANNEL_SWITCH_WITH_CSA_NAME, WLAN_PARAM_Integer,
+              hdd_config_t, sap_ch_switch_with_csa,
+              VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+              CFG_SAP_CHANNEL_SWITCH_WITH_CSA_DEFAULT,
+              CFG_SAP_CHANNEL_SWITCH_WITH_CSA_MIN,
+              CFG_SAP_CHANNEL_SWITCH_WITH_CSA_MAX ),
+
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
    REG_VARIABLE(CFG_DOT11P_MODE_NAME, WLAN_PARAM_Integer,
                 hdd_config_t, dot11p_mode,
                 VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -8276,6 +8286,9 @@
    smeConfig->sta_change_cc_via_beacon =
 	 pHddCtx->cfg_ini->sta_change_cc_via_beacon;
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+   smeConfig->csrConfig.sap_ch_switch_with_csa = pHddCtx->cfg_ini->sap_ch_switch_with_csa;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
    halStatus = sme_UpdateConfig( pHddCtx->hHal, smeConfig);
    if ( !HAL_STATUS_SUCCESS( halStatus ) )
    {
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 3138bd1..3b8373f 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -97,6 +97,10 @@
 #include "wlan_hdd_tsf.h"
 #include "wlan_hdd_oemdata.h"
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+#include <vos_utils.h>
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 #define    IS_UP(_dev) \
     (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
 #define    IS_UP_AUTO(_ic) \
@@ -1129,6 +1133,46 @@
     EXIT();
 }
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+//This function runs in the timer context of hdd_ap_chan_switch_timer.
+void hdd_hostapd_chan_switch_cb(v_PVOID_t usrDataForCallback)
+{
+    hdd_adapter_t   *pHostapdAdapter = NULL;
+    hdd_context_t   *pHddCtx = NULL;
+    int             ret = 0;
+
+    ENTER();
+
+    if(usrDataForCallback)
+    {
+        pHostapdAdapter = (struct hdd_adapter_s *)usrDataForCallback;
+    }
+    else
+    {
+        hddLog(LOGE, FL("hdd_hostapd_chan_switch_cb NULL cb pointer!!\n"));
+                EXIT();
+        return;
+    }
+    pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
+
+    mutex_lock(&pHddCtx->ch_switch_ctx.sap_ch_sw_lock);
+    if(pHddCtx->ch_switch_ctx.sap_chan_sw_pending)
+    {
+        vos_ssr_protect(__func__);
+        ret = hdd_softap_set_channel_change(pHostapdAdapter->dev, pHddCtx->ch_switch_ctx.def_csa_channel_on_disc);
+        vos_ssr_unprotect(__func__);
+        if (ret)
+        {
+            hddLog(LOGE, FL("hdd_softap_set_channel_change failed!!"));
+        }
+        pHddCtx->ch_switch_ctx.sap_chan_sw_pending = 0;
+    }
+    mutex_unlock(&pHddCtx->ch_switch_ctx.sap_ch_sw_lock);
+
+    EXIT();
+}
+#endif //#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 static VOS_STATUS
 hdd_change_mcc_go_beacon_interval(hdd_adapter_t *pHostapdAdapter)
 {
@@ -1507,6 +1551,218 @@
 	return VOS_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+VOS_STATUS hdd_send_sap_event(struct net_device *dev,
+                sta_sap_notifications event,
+                struct wlan_sap_csa_info csa_info,
+                struct wireless_dev *wdev)
+{
+    uint32_t freq = 0, ret;
+
+    hdd_wlan_get_freq(csa_info.sta_channel, &freq);
+
+    hddLog(LOG1, FL(" Set Freq %d Chan= %d"), freq, csa_info.sta_channel );
+
+    vos_ssr_protect(__func__);
+    ret = hdd_softap_set_channel_change(dev, csa_info.sta_channel);
+    vos_ssr_unprotect(__func__);
+
+    return ret;
+}
+
+VOS_STATUS hdd_sta_state_sap_notify(hdd_context_t *hdd_context,
+                                sta_sap_notifications event,
+                                struct wlan_sap_csa_info csa_info)
+{
+    /* Get the HostApd Adapter. If present proceed further.
+     * Check the current state of SAP. If its in active state, get the channel in which it is running.
+     * Verify the channel and band. Based on the event type, take a decision.
+     * If it is a disconnection event and SAP is running in 2.4 band channel, no action should be taken.
+     * If its a connection event and SAP needs to do a CSA to the HomeAP channel.
+     */
+
+    hdd_adapter_t *pHostapdAdapter = NULL;
+    hdd_ap_ctx_t *pHddApCtx = NULL;
+    hdd_hostapd_state_t *pHostapdState = NULL;
+    VOS_STATUS status = VOS_STATUS_SUCCESS;
+    tsap_Config_t *sap_config;
+    uint32_t ret = 0;
+
+    hddLog(LOGE, FL("%s Entry event = %d channel = %d"),
+                        __func__, event, csa_info.sta_channel);
+
+    if (!hdd_context) {
+        hddLog(LOGE, FL("HDD context is NULL"));
+                return VOS_STATUS_E_FAILURE;
+    }
+
+    ret = wlan_hdd_validate_context(hdd_context);
+
+    if (ret != 0) {
+
+        hddLog(LOGE, FL("%s Failed in hdd_validate_context ret=%d"), __func__, ret);
+        return ret;
+    }
+
+    /*Get the Adapter of SAP*/
+    pHostapdAdapter = hdd_get_adapter(hdd_context, WLAN_HDD_SOFTAP);
+
+    if(!pHostapdAdapter)
+    {
+        hddLog(LOGE, FL("Hostapd adapter context is NULL"));
+        return VOS_STATUS_E_FAILURE;
+    }
+
+    pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter);
+
+    pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
+
+    /*Verify the state*/
+    if(pHostapdState->vosStatus != VOS_STATUS_SUCCESS ||
+            pHostapdState->bssState != BSS_START)
+    {
+        hddLog(LOGE, FL("Invalid HostApd State vosStatus=%d bssState=%d"),
+                    pHostapdState->vosStatus, pHostapdState->bssState);
+        return VOS_STATUS_E_FAILURE;
+    }
+
+    switch(event)
+    {
+        case STA_NOTIFY_DISCONNECTED:
+            {
+                /* check for the operating channel
+                 * If operating in 2.4, just ignore and return
+                 * else start ACS & find the strongest signal channel and do initiate CSA to that channel.
+                 */
+                if((pHddApCtx->operatingChannel >= 1 && pHddApCtx->operatingChannel <= 14))
+                {
+                    hddLog(LOGE, FL("Hostapd is operating in 2.4Band Channel=%d, Avoid channel switch"),
+                                        pHddApCtx->operatingChannel);
+                }
+                else
+                {
+		    sap_config = &((WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->sapConfig);
+		    if (VOS_IS_DFS_CH(pHddApCtx->operatingChannel) &&
+				( VOS_IS_DFS_CH(sap_config->channel) ||
+					(sap_config->channel == AUTO_CHANNEL_SELECT) )){
+			hddLog(LOGE, FL("SAP CUR CH %d(DFS) Hostapd Conf CH=%d(%s) Switch to CH %d"),
+					pHddApCtx->operatingChannel, pHddApCtx->operatingChannel,
+				        (sap_config->channel == AUTO_CHANNEL_SELECT)?"AUTO":"DFS", 36);
+                        hdd_context->ch_switch_ctx.def_csa_channel_on_disc = 36;
+		    }else if (VOS_IS_DFS_CH(pHddApCtx->operatingChannel) &&
+				!VOS_IS_DFS_CH(sap_config->channel)){
+			hddLog(LOGE, FL("SAP CUR CH %d(DFS) Hostapd Conf CH=%d(Non-DFS) Switch to %d"),
+					pHddApCtx->operatingChannel, sap_config->channel, sap_config->channel);
+			hdd_context->ch_switch_ctx.def_csa_channel_on_disc = sap_config->channel; //channel from the hostapd
+		    }else{
+			    hddLog(LOGE, FL("SAP is operating in 5Ghz Band Non DFS Channel=%d, Avoid channel switch"),
+					    pHddApCtx->operatingChannel);
+			    return status;
+		    }
+		    mutex_lock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+		    hdd_context->ch_switch_ctx.sap_chan_sw_pending = 1;
+		    mutex_unlock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+
+		    //Set the timer to initiate channel switch
+		    if(hdd_context->ch_switch_ctx.chan_sw_timer_initialized == VOS_TRUE)
+		    {
+			    status = vos_timer_start(&hdd_context->ch_switch_ctx.hdd_ap_chan_switch_timer, 10000);
+			    if(!VOS_IS_STATUS_SUCCESS(status))
+			    {
+				    hddLog(LOGE, FL("Failed to start AP channel switch timer!!"));
+				    break;
+			    }
+		    }
+		}
+	    }
+	    break;
+	case STA_NOTIFY_CONNECTED:
+	    {
+		    //stop the channel switch timer first
+		    if (hdd_context->ch_switch_ctx.hdd_ap_chan_switch_timer.state == VOS_TIMER_STATE_RUNNING)
+		    {
+			    status = vos_timer_stop(&hdd_context->ch_switch_ctx.hdd_ap_chan_switch_timer);
+			    if(!VOS_IS_STATUS_SUCCESS(status))
+			    {
+				    hddLog(LOGE, FL("Failed to stop AP channel switch timer!!"));
+				    break;
+			    }
+		    }
+		    if(pHddApCtx->operatingChannel != csa_info.sta_channel)
+		    {
+			    mutex_lock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+			    hddLog(LOGE, FL("Switching Hostapd to Station channel %d"), csa_info.sta_channel);
+			    status = hdd_send_sap_event(pHostapdAdapter->dev,
+					    event,
+					    csa_info,
+					    &pHostapdAdapter->wdev);
+			    if(!VOS_IS_STATUS_SUCCESS(status))
+			    {
+				    hddLog(LOGE, FL("Failed to send channel switch event!!"));
+				    mutex_unlock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+				    break;
+			    }
+			    hdd_context->ch_switch_ctx.sap_chan_sw_pending = 0;
+			    mutex_unlock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+		    }
+		    else
+		    {
+			    hddLog(LOGE, FL("Hostapd and Sta are operating in same channel : %d\n"),
+					    pHddApCtx->operatingChannel);
+		    }
+	    }
+	    break;
+	case STA_NOTIFY_CSA:
+	    {
+		    mutex_lock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+		    if(pHddApCtx->operatingChannel != csa_info.sta_channel)
+		    {
+			    if(!(hdd_context->ch_switch_ctx.is_ch_sw_through_sta_csa &&
+						    hdd_context->ch_switch_ctx.csa_to_channel == csa_info.sta_channel))
+			    {
+				    hdd_context->ch_switch_ctx.is_ch_sw_through_sta_csa = VOS_TRUE;
+
+				    hddLog(LOGE, FL("Switching Hostapd to Station channel %d"), csa_info.sta_channel);
+				    status = hdd_send_sap_event(pHostapdAdapter->dev,
+						    event,
+						    csa_info,
+						    &pHostapdAdapter->wdev);
+				    if(!VOS_IS_STATUS_SUCCESS(status))
+				    {
+					    hddLog(LOGE, FL("Failed to send channel switch event!!"));
+					    mutex_unlock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+					    break;
+				    }
+
+				    hdd_context->ch_switch_ctx.csa_to_channel = csa_info.sta_channel;
+			    }
+			    else
+			    {
+				    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+						    "%s : CSA Sta interface for Channel %d is already notified",
+						    __func__, csa_info.sta_channel);
+			    }
+		    }
+		    else
+		    {
+			    hddLog(LOGE, FL("Hostapd and Sta are operating in same channel : %d\n"),
+					    pHddApCtx->operatingChannel);
+		    }
+		    mutex_unlock(&hdd_context->ch_switch_ctx.sap_ch_sw_lock);
+	    }
+	    break;
+	default:
+	    {
+		    hddLog(LOGE, FL("%s Invalid event %d"), __func__, event);
+	    }
+	    break;
+    }
+
+    hddLog(LOGE, FL("%s Exit ret = %d"), __func__, status);
+
+    return status;
+}
+#endif //#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 /**
  * hdd_send_radar_event() - Function to send radar events to user space
  * @hdd_context:	HDD context
@@ -2184,6 +2440,19 @@
             we_event = IWEVCUSTOM;
             we_custom_event_generic = we_custom_start_event;
             hdd_dump_concurrency_info(pHddCtx);
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+            if(pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
+	    {
+		    mutex_lock(&pHddCtx->ch_switch_ctx.sap_ch_sw_lock);
+		    if(pHddCtx->ch_switch_ctx.is_ch_sw_through_sta_csa &&
+				    (pHddApCtx->operatingChannel == pHddCtx->ch_switch_ctx.csa_to_channel)){
+			    hddLog(LOG1, FL("Successfully Channel Switch is done to CH = %d"),
+					    pHddApCtx->operatingChannel);
+			    pHddCtx->ch_switch_ctx.is_ch_sw_through_sta_csa = VOS_FALSE;
+		    }
+		    mutex_unlock(&pHddCtx->ch_switch_ctx.sap_ch_sw_lock);
+	    }
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
             break; //Event will be sent after Switch-Case stmt
 
         case eSAP_STOP_BSS_EVENT:
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 02ed253..6eec976 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -408,6 +408,14 @@
 	return opclass;
 }
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+void hdd_csa_notify_cb
+(
+   void *hdd_context,
+   void *indi_param
+);
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 #ifdef FEATURE_GREEN_AP
 
 static void hdd_wlan_green_ap_timer_fn(void *phddctx)
@@ -1038,7 +1046,10 @@
         clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
         wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
         hddLog(LOGE, FL("SAP Stop Success"));
-
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+                /*this delay is needed to ensure proper resource cleanup of SAP*/
+                vos_sleep(1000);
+#endif  //#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
         if (pHddCtx->cfg_ini->apOBSSProtEnabled)
             vos_runtime_pm_allow_suspend(pHddCtx->runtime_context.obss);
         if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
@@ -12703,6 +12714,27 @@
             wlan_hdd_reset_prob_rspies(pAdapter);
             kfree(pAdapter->sessionCtx.ap.beacon);
             pAdapter->sessionCtx.ap.beacon = NULL;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+            if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
+            {
+                if(pHddCtx->ch_switch_ctx.chan_sw_timer_initialized == VOS_TRUE)
+                {
+                //Stop the channel switch timer
+                    if (VOS_TIMER_STATE_RUNNING ==
+			    vos_timer_getCurrentState(&pHddCtx->ch_switch_ctx.hdd_ap_chan_switch_timer))
+		    {
+			    vos_timer_stop(&pHddCtx->ch_switch_ctx.hdd_ap_chan_switch_timer);
+		    }
+			    //Destroy the channel switch timer
+		    if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
+					&pHddCtx->ch_switch_ctx.hdd_ap_chan_switch_timer)))
+		    {
+			    hddLog(LOGE, FL("Failed to destroy AP channel switch timer!!"));
+		    }
+		    pHddCtx->ch_switch_ctx.chan_sw_timer_initialized = VOS_FALSE;
+                }
+             }
+#endif //WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
          }
          mutex_unlock(&pHddCtx->sap_lock);
 
@@ -16898,6 +16930,13 @@
 #endif
 #endif /* FEATURE_WLAN_CH_AVOID */
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    /* Initialize the lock*/
+   mutex_init(&pHddCtx->ch_switch_ctx.sap_ch_sw_lock);
+    /*Register the CSA Notification callback*/
+   sme_AddCSAIndCallback(pHddCtx->hHal, hdd_csa_notify_cb);
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
    status = hdd_post_voss_start_config( pHddCtx );
    if ( !VOS_IS_STATUS_SUCCESS( status ) )
    {
@@ -19564,18 +19603,85 @@
         pHddApCtx->sapConfig.channel, intf_ch);
 
     pHddApCtx->sapConfig.channel = intf_ch;
-    pHddApCtx->bss_stop_reason = BSS_STOP_DUE_TO_MCC_SCC_SWITCH;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    if(vos_is_ch_switch_with_csa_enabled())
+    {
+        struct wlan_sap_csa_info csa_info;
 
-    sme_SelectCBMode(hHal,
+        csa_info.sta_channel = intf_ch;
+
+        hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+	    "%s: Indicate connected event to HostApd Chan=%d",
+	    __func__, csa_info.sta_channel);
+
+	/*Indicate to HostApd about Station interface state change*/
+        hdd_sta_state_sap_notify(pHddCtx, STA_NOTIFY_CONNECTED, csa_info);
+    }else{
+#endif
+        pHddApCtx->bss_stop_reason = BSS_STOP_DUE_TO_MCC_SCC_SWITCH;
+        sme_SelectCBMode(hHal,
                      pHddApCtx->sapConfig.SapHw_mode,
                      pHddApCtx->sapConfig.channel,
                      pHddApCtx->sapConfig.sec_ch,
                      &vht_channel_width, pHddApCtx->sapConfig.ch_width_orig);
-    wlan_sap_set_vht_ch_width(pHddApCtx->sapContext, vht_channel_width);
-    wlan_hdd_restart_sap(ap_adapter);
+        wlan_sap_set_vht_ch_width(pHddApCtx->sapContext, vht_channel_width);
+        wlan_hdd_restart_sap(ap_adapter);
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    }
+#endif
 }
 #endif
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
+void hdd_csa_notify_cb
+(
+   void *hdd_context,
+   void *indi_param
+)
+{
+   tpSmeCsaOffloadInd csa_params = NULL;
+   hdd_context_t      *hdd_ctxt = NULL;
+   struct wlan_sap_csa_info csa_info;
+   v_U32_t ret = 0;
+   /* Basic sanity */
+
+   if(!vos_is_ch_switch_with_csa_enabled())
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s : SAP channel switch with CSA not enabled", __func__);
+      return;
+   }
+
+   if (!hdd_context || !indi_param)
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s : Invalid arguments", __func__);
+      return;
+   }
+
+   hdd_ctxt    = (hdd_context_t *)hdd_context;
+
+   csa_params = (tpSmeCsaOffloadInd)indi_param;
+
+   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+             "%s : tbtt count %d Channel = %d",
+             __func__,csa_params->tbtt_count, csa_params->channel);
+   hdd_ctxt->ch_switch_ctx.tbtt_count = csa_params->tbtt_count - 1;  /* Will reduce the count by 1,
+									as the switch might take time.
+									Currently of No Use, as this will be
+									override by ini g_sap_chanswitch_beacon_cnt */
+   csa_info.sta_channel = csa_params->channel;
+   ret = hdd_sta_state_sap_notify(hdd_ctxt, STA_NOTIFY_CSA, csa_info);
+   if(ret != 0)
+   {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+          "%s : Failed to trigger Channel Switch Ch:%d ret=%d",
+          __func__,csa_params->channel, ret);
+   }
+}
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
 /**
  * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
  *                                             and sta's operating channel.
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index 363d1a1..5cfad0d 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -2965,6 +2965,25 @@
         hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
         return ERR_PTR(-ENOSPC);
     }
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    if(pAdapter->device_mode == WLAN_HDD_SOFTAP)
+    {
+	    if(pHddCtx->ch_switch_ctx.chan_sw_timer_initialized == VOS_FALSE)
+	    {
+		    //Initialize the channel switch timer
+		    ret = vos_timer_init(&pHddCtx->ch_switch_ctx.hdd_ap_chan_switch_timer, VOS_TIMER_TYPE_SW,
+				    hdd_hostapd_chan_switch_cb, (v_PVOID_t)pAdapter);
+		    if(!VOS_IS_STATUS_SUCCESS(ret))
+		    {
+			    hddLog(LOGE, FL("Failed to initialize AP channel switch timer!!\n"));
+			    EXIT();
+			    return ERR_PTR(ret);
+		    }
+		    pHddCtx->ch_switch_ctx.chan_sw_timer_initialized = VOS_TRUE;
+	    }
+    }
+#endif //WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+
     EXIT();
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS)
     return pAdapter->dev->ieee80211_ptr;
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 0b50aee..a0a7d53 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -3186,6 +3186,10 @@
     tANI_U16    mesgType;    // eWNI_SME_CSA_OFFLOAD_EVENT
     tANI_U16    mesgLen;
     tSirMacAddr bssId;       // BSSID
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    tANI_U16    channel;
+    tANI_U16    tbtt_count;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 } tSmeCsaOffloadInd, *tpSmeCsaOffloadInd;
 
 /// WOW related structures
@@ -5259,6 +5263,9 @@
     uint8_t  ch_switch_mode;
     uint8_t  dfs_ch_switch_disable;
     uint8_t  sub20_switch_mode;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    tANI_U8  csaSwitchCount;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 }tSirDfsCsaIeRequest, *tpSirDfsCsaIeRequest;
 
 /* Indication from lower layer indicating the completion of first beacon send
diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
index e00b4e6..2603df2 100644
--- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -3119,6 +3119,10 @@
       mmhMsg.type = eWNI_SME_CSA_OFFLOAD_EVENT;
       mmhMsg.bodyptr = pCsaOffloadInd;
       mmhMsg.bodyval = 0;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+      pCsaOffloadInd->tbtt_count = csa_params->csa_tbtt_count;
+      pCsaOffloadInd->channel = csa_params->channel;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
       PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_SME_CSA_OFFLOAD_EVENT to SME. "));)
       MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, mmhMsg.type));
       limDiagEventReport(pMac, WLAN_PE_DIAG_SWITCH_CHL_REQ_EVENT, psessionEntry,
diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h
index 1c34ba5..9cc3f09 100644
--- a/CORE/SAP/inc/sapApi.h
+++ b/CORE/SAP/inc/sapApi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -194,6 +194,9 @@
     eSAP_ACS_SCAN_SUCCESS_EVENT,
     eSAP_ACS_CHANNEL_SELECTED,
     eSAP_ECSA_CHANGE_CHAN_IND,
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    eSAP_CHANNEL_SWITCH_NOTIFICATION,
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 } eSapHddEvent;
 
 typedef enum {
@@ -739,6 +742,9 @@
     bool               dfs_beacon_tx_enhanced;
     uint16_t           reduced_beacon_interval;
     enum sub20_chan_switch_mode  sub20_switch_mode;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    v_U8_t              csaSwitchCount;
+#endif
 } tSapDfsInfo;
 
 typedef struct tagSapCtxList
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 58aaccb..f9fbe57 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -7131,11 +7131,17 @@
 		csa_ie = (struct ieee80211_channelswitch_ie *)(&csa_event->csa_ie[0]);
 		csa_offload_event->channel = csa_ie->newchannel;
 		csa_offload_event->switchmode = csa_ie->switchmode;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+		csa_offload_event->csa_tbtt_count = csa_ie->tbttcount;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 	} else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
 		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie*)(&csa_event->xcsa_ie[0]);
 		csa_offload_event->channel = xcsa_ie->newchannel;
 		csa_offload_event->switchmode = xcsa_ie->switchmode;
 		csa_offload_event->new_op_class = xcsa_ie->newClass;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+		csa_offload_event->csa_tbtt_count = xcsa_ie->tbttcount;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 	} else {
 		WMA_LOGE("CSA Event error: No CSA IE present");
 		vos_mem_free(csa_offload_event);
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index 6b0b7a7..6327dae 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1406,6 +1406,9 @@
 #ifdef WLAN_FEATURE_FILS_SK
     uint8_t fils_max_chan_guard_time;
 #endif
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    tANI_U32    sap_ch_switch_with_csa;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 }tCsrConfigParam;
 
 //Tush
diff --git a/CORE/SME/inc/smeInternal.h b/CORE/SME/inc/smeInternal.h
index d63c9a9..0b5adb6 100644
--- a/CORE/SME/inc/smeInternal.h
+++ b/CORE/SME/inc/smeInternal.h
@@ -266,6 +266,10 @@
     void (*stats_ext2_cb)(void *, struct stats_ext2_event *);
     void (*chip_power_save_fail_cb)(void *,
 			struct chip_pwr_save_fail_detected_params *);
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+    /*call back to indicate CSA notification received on STA interfce to SAP*/
+    void (*pCSASAPIndCb) (void * hdd_context, void *indi_param);
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 } tSmeStruct, *tpSmeStruct;
 
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 777f7eb..3383f34 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4524,6 +4524,14 @@
 VOS_STATUS sme_apfind_set_cmd(struct sme_ap_find_request_req *input);
 #endif /* WLAN_FEATURE_APFIND */
 
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+eHalStatus sme_AddCSAIndCallback
+(
+   tHalHandle hHal,
+   void (*pCallbackfn)(void *pAdapter, void *CSAindParam)
+);
+#endif//#ifdef
+
 /**
  * sme_enable_disable_mas() - Function to set MAS value to UMAC
  * @val:        1-Enable, 0-Disable
diff --git a/CORE/SME/src/csr/csrUtil.c b/CORE/SME/src/csr/csrUtil.c
index b29c367..2d4b90d 100644
--- a/CORE/SME/src/csr/csrUtil.c
+++ b/CORE/SME/src/csr/csrUtil.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -44,7 +44,9 @@
 #include "smeQosInternal.h"
 #include "wlan_qct_wda.h"
 #include "vos_utils.h"
-
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+#include "limApi.h"
+#endif
 #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
 #include "csrEse.h"
 #endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD*/
@@ -1108,6 +1110,7 @@
 	tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
 	tCsrRoamSession *pSession = NULL;
 	v_U8_t i = 0;
+	tpPESession psessionEntry;
 
 	for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) {
 		if( !CSR_IS_SESSION_VALID( pMac, i ) )
@@ -1121,8 +1124,21 @@
 				VOS_P2P_CLIENT_MODE)) &&
 			(pSession->connectState ==
 				eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED)) {
-			info->och =
-				pSession->connectedProfile.operationChannel;
+			if(vos_is_ch_switch_with_csa_enabled()){
+				psessionEntry = peFindSessionBySessionId(pMac,
+						pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId);
+				if (psessionEntry && LIM_IS_STA_ROLE(psessionEntry)) {
+					info->och = psessionEntry->gLimChannelSwitch.primaryChannel;
+					smsLog(pMac, LOGP,
+						FL("SAP channel switch with CSA enabled (SAP new ch: %d)"), info->och);
+				}else{
+					info->och =
+						pSession->connectedProfile.operationChannel;
+				}
+			}else{
+				info->och =
+					pSession->connectedProfile.operationChannel;
+			}
 			csrGetChFromHTProfile(pMac,
 				&pSession->connectedProfile.HTProfile,
 				info->och, &info->cfreq, &info->hbw);
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index e6c6ae4..3912b33 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -3257,6 +3257,15 @@
           case eWNI_SME_CSA_OFFLOAD_EVENT:
                if (pMsg->bodyptr)
                {
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+                   /*Indicate to HostApd*/
+                   if(pMac->sme.pCSASAPIndCb)
+                   {
+                        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                             "%s: CSA Notification to SAP", __func__);
+                        pMac->sme.pCSASAPIndCb(pMac->hHdd, pMsg->bodyptr);
+                   }
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
                    csrScanFlushBssEntry(pMac, pMsg->bodyptr);
                    vos_mem_free(pMsg->bodyptr);
                }
@@ -17639,6 +17648,34 @@
      return VOS_STATUS_SUCCESS;
 }
 #endif /* WLAN_FEATURE_APFIND */
+
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+eHalStatus sme_AddCSAIndCallback
+(
+   tHalHandle hHal,
+   void (*pCallbackfn)(void *pAdapter, void *CSAindParam)
+)
+{
+   eHalStatus          status    = eHAL_STATUS_SUCCESS;
+    tpAniSirGlobal      pMac      = PMAC_STRUCT(hHal);
+
+    VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+              "%s: Plug in CSA Notify CB", __func__);
+
+    status = sme_AcquireGlobalLock(&pMac->sme);
+    if (eHAL_STATUS_SUCCESS == status)
+    {
+        if (NULL != pCallbackfn)
+        {
+           pMac->sme.pCSASAPIndCb = pCallbackfn;
+        }
+        sme_ReleaseGlobalLock(&pMac->sme);
+    }
+
+    return(status);
+
+}
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 /*
  * sme_validate_sap_channel_switch() - validate target channel switch w.r.t
diff --git a/CORE/SVC/external/wlan_nlink_common.h b/CORE/SVC/external/wlan_nlink_common.h
index 0b3604c..220e845 100644
--- a/CORE/SVC/external/wlan_nlink_common.h
+++ b/CORE/SVC/external/wlan_nlink_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -222,5 +222,16 @@
         WLAN_SVC_TP_MEDIUM,
         WLAN_SVC_TP_HIGH,
 };
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+typedef enum sta_sap_notifications
+{
+    STA_NOTIFY_DISCONNECTED,
+    STA_NOTIFY_CONNECTED,
+    STA_NOTIFY_CSA,
+}sta_sap_notifications;
 
+struct wlan_sap_csa_info {
+   uint32_t sta_channel;
+};
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 #endif //WLAN_NLINK_COMMON_H__
diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h
index dc7d90f..66aa196 100644
--- a/CORE/VOSS/inc/vos_api.h
+++ b/CORE/VOSS/inc/vos_api.h
@@ -437,5 +437,5 @@
  *          true: monitor mode is on
  */
 bool vos_is_mon_enable(void);
-
+v_BOOL_t vos_is_ch_switch_with_csa_enabled(void);
 #endif // if !defined __VOS_API_H
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 360237d..3d49c79 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -3320,3 +3320,24 @@
 
 	return phdd_ctx->is_mon_enable;
 }
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+v_BOOL_t vos_is_ch_switch_with_csa_enabled(void)
+{
+   hdd_context_t *pHddCtx;
+
+   pHddCtx = (hdd_context_t*)(gpVosContext->pHDDContext);
+   if((NULL == pHddCtx) ||
+      (NULL == pHddCtx->cfg_ini))
+   {
+     VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+               "%s: Hdd Context is Null", __func__);
+     return FALSE;
+   }
+   return pHddCtx->cfg_ini->sap_ch_switch_with_csa;
+}
+#else
+v_BOOL_t vos_is_ch_switch_with_csa_enabled(void)
+{
+	return FALSE;
+}
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
diff --git a/CORE/WDA/inc/legacy/halMsgApi.h b/CORE/WDA/inc/legacy/halMsgApi.h
index 0c3a8c7..cfe4984 100644
--- a/CORE/WDA/inc/legacy/halMsgApi.h
+++ b/CORE/WDA/inc/legacy/halMsgApi.h
@@ -1056,6 +1056,9 @@
    tANI_U8 new_sub20_channelwidth;  /* 5MHz or 10Mhz channel width */
    tANI_U32 ies_present_flag;   /* WMI_CSA_EVENT_IES_PRESENT_FLAG */
    tSirMacAddr bssId;
+#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
+   tANI_U32 csa_tbtt_count;
+#endif//#ifdef WLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 }*tpCSAOffloadParams, tCSAOffloadParams;
 
 typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam,
diff --git a/Kbuild b/Kbuild
index 1a906a1..57684d6 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1080,7 +1080,8 @@
 CDEFINES +=     -DWLAN_FEATURE_MBSSID \
 		-DFEATURE_WLAN_MCC_TO_SCC_SWITCH \
 		-DFEATURE_WLAN_CH_AVOID \
-		-DFEATURE_WLAN_STA_AP_MODE_DFS_DISABLE
+		-DFEATURE_WLAN_STA_AP_MODE_DFS_DISABLE \
+		-DWLAN_FEATURE_SAP_TO_FOLLOW_STA_CHAN
 endif
 
 ifeq ($(CONFIG_QCA_WIFI_SDIO), 1)