wlan: Avoid unsafe channel with softap mode and P2PGO mode

If FW sends unsafe channel detect indication,
Softap mode and P2PGO mode, should avoid to stay unsafe channels.
Make indication path from FW.
Store into module context.
Store into static module storage incase of re-load driver.
Channel selection should avoid unsafe channel

CRs-fixed: 576020
diff --git a/CORE/HDD/inc/wlan_hdd_hostapd.h b/CORE/HDD/inc/wlan_hdd_hostapd.h
index 534d808..fc0e0de 100644
--- a/CORE/HDD/inc/wlan_hdd_hostapd.h
+++ b/CORE/HDD/inc/wlan_hdd_hostapd.h
@@ -49,13 +49,6 @@
   \brief Linux HDD HOSTAPD include file
          Copyright 2008-2013 (c) Qualcomm, Incorporated.
          All Rights Reserved.
-<<<<<<< HEAD:CORE/HDD/inc/wlan_hdd_hostapd.h
-         Qualcomm Confidential and Proprietary.
-  
-=======
-         Qualcomm Technologies Confidential and Proprietary.
-
->>>>>>> 009551c... wlan: hdd: remove obsolete "WLAN_SOFTAP_FEATURE" featurization:prima/CORE/HDD/inc/wlan_hdd_hostapd.h
   ==========================================================================*/
 
 /*---------------------------------------------------------------------------
@@ -108,4 +101,7 @@
 VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback);
 VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter );
 void hdd_set_ap_ops( struct net_device *pWlanHostapdDev );
+#ifdef FEATURE_WLAN_CH_AVOID
+void hdd_hostapd_ch_avoid_cb(void *pAdapter, void *indParam);
+#endif /* FEATURE_WLAN_CH_AVOID */
 #endif    // end #if !defined( WLAN_HDD_HOSTAPD_H )
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 1367813..6b73788 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1240,6 +1240,11 @@
     /* VHT80 allowed*/
     v_BOOL_t isVHT80Allowed;
 
+#ifdef FEATURE_WLAN_CH_AVOID
+   v_U16_t unsafeChannelCount;
+   v_U16_t unsafeChannelList[NUM_20MHZ_RF_CHANNELS];
+   v_U16_t safeChannelList[NUM_20MHZ_RF_CHANNELS];
+#endif /* FEATURE_WLAN_CH_AVOID */
 };
 
 
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index af86402..70322cc 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -94,6 +94,10 @@
 #include "cfgApi.h"
 #include "wniCfgAp.h"
 
+#ifdef FEATURE_WLAN_CH_AVOID
+#include "wcnss_wlan.h"
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 #define    IS_UP(_dev) \
     (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
 #define    IS_UP_AUTO(_ic) \
@@ -107,6 +111,60 @@
 
 #define SAP_24GHZ_CH_COUNT (14) 
 
+#ifdef FEATURE_WLAN_CH_AVOID
+/* Channle/Freqency table */
+extern const tRfChannelProps rfChannels[NUM_RF_CHANNELS];
+safeChannelType safeChannels[NUM_20MHZ_RF_CHANNELS] =
+{
+  /*CH  , SAFE, default safe */
+    {1  , VOS_TRUE},      //RF_CHAN_1,
+    {2  , VOS_TRUE},      //RF_CHAN_2,
+    {3  , VOS_TRUE},      //RF_CHAN_3,
+    {4  , VOS_TRUE},      //RF_CHAN_4,
+    {5  , VOS_TRUE},      //RF_CHAN_5,
+    {6  , VOS_TRUE},      //RF_CHAN_6,
+    {7  , VOS_TRUE},      //RF_CHAN_7,
+    {8  , VOS_TRUE},      //RF_CHAN_8,
+    {9  , VOS_TRUE},      //RF_CHAN_9,
+    {10 , VOS_TRUE},      //RF_CHAN_10,
+    {11 , VOS_TRUE},      //RF_CHAN_11,
+    {12 , VOS_TRUE},      //RF_CHAN_12,
+    {13 , VOS_TRUE},      //RF_CHAN_13,
+    {14 , VOS_TRUE},      //RF_CHAN_14,
+    {240, VOS_TRUE},      //RF_CHAN_240,
+    {244, VOS_TRUE},      //RF_CHAN_244,
+    {248, VOS_TRUE},      //RF_CHAN_248,
+    {252, VOS_TRUE},      //RF_CHAN_252,
+    {208, VOS_TRUE},      //RF_CHAN_208,
+    {212, VOS_TRUE},      //RF_CHAN_212,
+    {216, VOS_TRUE},      //RF_CHAN_216,
+    {36 , VOS_TRUE},      //RF_CHAN_36,
+    {40 , VOS_TRUE},      //RF_CHAN_40,
+    {44 , VOS_TRUE},      //RF_CHAN_44,
+    {48 , VOS_TRUE},      //RF_CHAN_48,
+    {52 , VOS_TRUE},      //RF_CHAN_52,
+    {56 , VOS_TRUE},      //RF_CHAN_56,
+    {60 , VOS_TRUE},      //RF_CHAN_60,
+    {64 , VOS_TRUE},      //RF_CHAN_64,
+    {100, VOS_TRUE},      //RF_CHAN_100,
+    {104, VOS_TRUE},      //RF_CHAN_104,
+    {108, VOS_TRUE},      //RF_CHAN_108,
+    {112, VOS_TRUE},      //RF_CHAN_112,
+    {116, VOS_TRUE},      //RF_CHAN_116,
+    {120, VOS_TRUE},      //RF_CHAN_120,
+    {124, VOS_TRUE},      //RF_CHAN_124,
+    {128, VOS_TRUE},      //RF_CHAN_128,
+    {132, VOS_TRUE},      //RF_CHAN_132,
+    {136, VOS_TRUE},      //RF_CHAN_136,
+    {140, VOS_TRUE},      //RF_CHAN_140,
+    {149, VOS_TRUE},      //RF_CHAN_149,
+    {153, VOS_TRUE},      //RF_CHAN_153,
+    {157, VOS_TRUE},      //RF_CHAN_157,
+    {161, VOS_TRUE},      //RF_CHAN_161,
+    {165, VOS_TRUE},      //RF_CHAN_165,
+};
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 /*--------------------------------------------------------------------------- 
  *   Function definitions
  *-------------------------------------------------------------------------*/
@@ -1001,6 +1059,237 @@
     return VOS_STATUS_SUCCESS;
 }
 
+#ifdef FEATURE_WLAN_CH_AVOID
+/**---------------------------------------------------------------------------
+
+  \brief hdd_hostapd_freq_to_chn() -
+
+  Input frequency translated into channel number
+
+  \param  - freq input frequency with order of kHz
+
+  \return - corresponding channel number.
+            incannot find correct channel number, return 0
+
+  --------------------------------------------------------------------------*/
+v_U16_t hdd_hostapd_freq_to_chn
+(
+   v_U16_t   freq
+)
+{
+   int   loop;
+
+   for (loop = 0; loop < NUM_20MHZ_RF_CHANNELS; loop++)
+   {
+      if (rfChannels[loop].targetFreq == freq)
+      {
+         return rfChannels[loop].channelNum;
+      }
+   }
+
+   return (0);
+}
+
+/*==========================================================================
+  FUNCTION    sapUpdateUnsafeChannelList
+
+  DESCRIPTION
+    Function  Undate unsafe channel list table
+
+  DEPENDENCIES
+    NA.
+
+  PARAMETERS
+
+    IN
+    pSapCtx : SAP context pointer, include unsafe channel list
+
+  RETURN VALUE
+    NONE
+============================================================================*/
+void hdd_hostapd_update_unsafe_channel_list(hdd_context_t *pHddCtx,
+                        v_U16_t *unsafeChannelList, v_U16_t unsafeChannelCount)
+{
+   v_U16_t   i, j;
+
+   vos_mem_zero((void *)pHddCtx->unsafeChannelList,
+                sizeof(pHddCtx->unsafeChannelList));
+   if (0 == unsafeChannelCount)
+   {
+      pHddCtx->unsafeChannelCount = 0;
+   }
+   else
+   {
+      vos_mem_copy((void *)pHddCtx->unsafeChannelList,
+                   unsafeChannelList,
+                   unsafeChannelCount * sizeof(tANI_U16));
+      pHddCtx->unsafeChannelCount = unsafeChannelCount;
+   }
+
+   /* Flush, default set all channel safe */
+   for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++)
+   {
+      safeChannels[i].isSafe = VOS_TRUE;
+   }
+
+   /* Try to find unsafe channel */
+   for (i = 0; i < pHddCtx->unsafeChannelCount; i++)
+   {
+      for (j = 0; j < NUM_20MHZ_RF_CHANNELS; j++)
+      {
+         if(safeChannels[j].channelNumber == pHddCtx->unsafeChannelList[i])
+         {
+            /* Found unsafe channel, update it */
+            safeChannels[j].isSafe = VOS_FALSE;
+            VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+                      "%s : CH %d is not safe",
+                      __func__, pHddCtx->unsafeChannelList[i]);
+            break;
+         }
+      }
+   }
+
+   return;
+}
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_hostapd_ch_avoid_cb() -
+
+  Avoid channel notification from FW handler.
+  FW will send un-safe channle list to avoid overwrapping.
+  hostapd should not use notified channel
+
+  \param  - pAdapter HDD adapter pointer
+            indParam channel avoid notification parameter
+
+  \return - None
+
+  --------------------------------------------------------------------------*/
+void hdd_hostapd_ch_avoid_cb
+(
+   void *pAdapter,
+   void *indParam
+)
+{
+   hdd_adapter_t      *pHostapdAdapter = NULL;
+   hdd_context_t      *hddCtxt;
+   tSirChAvoidIndType *chAvoidInd;
+   v_U8_t              rangeLoop;
+   v_U16_t             channelLoop;
+   v_U16_t             dupCheck;
+   v_U16_t             startChannel;
+   v_U16_t             endChannel;
+   v_U16_t             unsafeChannelCount = 0;
+   v_U16_t             unsafeChannelList[NUM_20MHZ_RF_CHANNELS];
+   v_CONTEXT_t         pVosContext;
+
+   /* Basic sanity */
+   if ((NULL == pAdapter) || (NULL == indParam))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s : Invalid arguments", __func__);
+      return;
+   }
+
+   hddCtxt     = (hdd_context_t *)pAdapter;
+   chAvoidInd  = (tSirChAvoidIndType *)indParam;
+   pVosContext = hddCtxt->pvosContext;
+
+   /* Make unsafe channel list */
+   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+             "%s : band count %d",
+             __func__, chAvoidInd->avoidRangeCount);
+   vos_mem_zero((void *)unsafeChannelList,
+                NUM_20MHZ_RF_CHANNELS * sizeof(v_U16_t));
+   for (rangeLoop = 0; rangeLoop < chAvoidInd->avoidRangeCount; rangeLoop++)
+   {
+      startChannel = hdd_hostapd_freq_to_chn(
+                      chAvoidInd->avoidFreqRange[rangeLoop].startFreq);
+      endChannel   = hdd_hostapd_freq_to_chn(
+                      chAvoidInd->avoidFreqRange[rangeLoop].endFreq);
+      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                "%s : start %d : %d, end %d : %d",
+                __func__,
+                chAvoidInd->avoidFreqRange[rangeLoop].startFreq,
+                startChannel,
+                chAvoidInd->avoidFreqRange[rangeLoop].endFreq,
+                endChannel);
+      for (channelLoop = startChannel;
+           channelLoop < (endChannel + 1);
+           channelLoop++)
+      {
+         /* Channel duplicate check routine */
+         for (dupCheck = 0; dupCheck < unsafeChannelCount; dupCheck++)
+         {
+            if (unsafeChannelList[dupCheck] == channelLoop)
+            {
+               /* This channel is duplicated */
+               VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                      "%s : found duplicated channel %d",
+                      __func__, channelLoop);
+               break;
+            }
+         }
+         if (dupCheck == unsafeChannelCount)
+         {
+            unsafeChannelList[unsafeChannelCount] = channelLoop;
+            unsafeChannelCount++;
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                      "%s : unsafe channel %d, count %d",
+                      __func__,
+                      channelLoop, unsafeChannelCount);
+         }
+         else
+         {
+            /* DUP, do nothing */
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                      "%s : duplicated channel %d",
+                      __func__, channelLoop);
+         }
+      }
+   }
+   /* Update unsafe channel cache
+    * WCN Platform Driver cache */
+   wcnss_set_wlan_unsafe_channel(unsafeChannelList,
+                                 unsafeChannelCount);
+
+   /* Store into local cache
+    * Start with STA and later start SAP
+    * in this scenario, local cache will be used */
+   hdd_hostapd_update_unsafe_channel_list(hddCtxt,
+                                          unsafeChannelList,
+                                          unsafeChannelCount);
+
+   /* Get SAP context first
+    * SAP and P2PGO would not concurrent */
+   pHostapdAdapter = hdd_get_adapter(hddCtxt, WLAN_HDD_SOFTAP);
+   if ((pHostapdAdapter) && (unsafeChannelCount))
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                "%s : Current operation channel %d",
+                __func__,
+                pHostapdAdapter->sessionCtx.ap.operatingChannel);
+      for (channelLoop = 0; channelLoop < unsafeChannelCount; channelLoop++)
+      {
+         if (((unsafeChannelList[channelLoop] ==
+               pHostapdAdapter->sessionCtx.ap.operatingChannel)) &&
+             (AUTO_CHANNEL_SELECT ==
+               pHostapdAdapter->sessionCtx.ap.sapConfig.channel))
+         {
+            /* current operating channel is un-safe channel
+             * restart driver */
+            hdd_hostapd_stop(pHostapdAdapter->dev);
+            break;
+         }
+      }
+   }
+
+   return;
+}
+
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 int
 static iw_softap_setparam(struct net_device *dev, 
                           struct iw_request_info *info,
@@ -3218,12 +3507,31 @@
     struct net_device *dev = pAdapter->dev;
     hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
     VOS_STATUS status;
+#ifdef FEATURE_WLAN_CH_AVOID
+    v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+    v_U16_t unsafeChannelList[NUM_20MHZ_RF_CHANNELS];
+    v_U16_t unsafeChannelCount;
+#endif /* FEATURE_WLAN_CH_AVOID */
+
     ENTER();
        // Allocate the Wireless Extensions state structure   
     phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter );
  
     sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
 
+#ifdef FEATURE_WLAN_CH_AVOID
+    /* Get unsafe cahnnel list from cached location */
+    wcnss_get_wlan_unsafe_channel(unsafeChannelList,
+                                  sizeof(unsafeChannelList),
+                                  &unsafeChannelCount);
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+              "%s : Unsafe Channel count %d",
+              __func__, unsafeChannelCount);
+    hdd_hostapd_update_unsafe_channel_list(pVosContext,
+                                  unsafeChannelList,
+                                  unsafeChannelCount);
+#endif /* FEATURE_WLAN_CH_AVOID */
+
     // Zero the memory.  This zeros the profile structure.
     memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t));
     
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index cdf0b36..3a6b667 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8299,6 +8299,12 @@
    // Initialize the restart logic
    wlan_hdd_restart_init(pHddCtx);
 
+#ifdef FEATURE_WLAN_CH_AVOID
+    /* Plug in avoid channel notification callback */
+    sme_AddChAvoidCallback(pHddCtx->hHal,
+                           hdd_hostapd_ch_avoid_cb);
+#endif /* FEATURE_WLAN_CH_AVOID */
+
    //Register the traffic monitor timer now
    if ( pHddCtx->cfg_ini->dynSplitscan)
    {
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index c4d34b9..f75c100 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -4625,5 +4625,20 @@
 
 #endif // FEATURE_WLAN_BATCH_SCAN
 
+#ifdef FEATURE_WLAN_CH_AVOID
+#define SIR_CH_AVOID_MAX_RANGE   4
+
+typedef struct sSirChAvoidFreqType
+{
+   tANI_U32 startFreq;
+   tANI_U32 endFreq;
+} tSirChAvoidFreqType;
+
+typedef struct sSirChAvoidIndType
+{
+   tANI_U32            avoidRangeCount;
+   tSirChAvoidFreqType avoidFreqRange[SIR_CH_AVOID_MAX_RANGE];
+} tSirChAvoidIndType;
+#endif /* FEATURE_WLAN_CH_AVOID */
 
 #endif /* __SIR_API_H */
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 45879b8..41fb991 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -387,6 +387,9 @@
     eWNI_SME_GET_TSM_STATS_RSP,
     eWNI_SME_TSM_IE_IND,
 
+#ifdef FEATURE_WLAN_CH_AVOID
+   eWNI_SME_CH_AVOID_IND,
+#endif /* FEATURE_WLAN_CH_AVOID */
     eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h
index c9f26e8..48ba1ad 100644
--- a/CORE/SAP/inc/sapApi.h
+++ b/CORE/SAP/inc/sapApi.h
@@ -580,6 +580,14 @@
 #endif
 } tSap_SoftapStats, *tpSap_SoftapStats;
 
+#ifdef FEATURE_WLAN_CH_AVOID
+/* Store channel safty information */
+typedef struct
+{
+   v_U16_t   channelNumber;
+   v_BOOL_t  isSafe;
+} safeChannelType;
+#endif /* FEATURE_WLAN_CH_AVOID */
 
 int sapSetPreferredChannel(tANI_U8* ptr);
 void sapCleanupChannelList(void);
diff --git a/CORE/SAP/src/sapChSelect.c b/CORE/SAP/src/sapChSelect.c
index 9c51f80..b64a863 100644
--- a/CORE/SAP/src/sapChSelect.c
+++ b/CORE/SAP/src/sapChSelect.c
@@ -95,6 +95,10 @@
    ((extRssi < rssi)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \
 )
 
+#ifdef FEATURE_WLAN_CH_AVOID
+extern safeChannelType safeChannels[];
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 /*==========================================================================
   FUNCTION    sapCleanupChannelList
 
@@ -399,6 +403,10 @@
     v_U8_t *pChans = NULL;
     v_U16_t channelnum = 0;
     tpAniSirGlobal pMac = PMAC_STRUCT(halHandle);
+#ifdef FEATURE_WLAN_CH_AVOID
+    v_U16_t i;
+    v_BOOL_t chSafe = VOS_TRUE;
+#endif /* FEATURE_WLAN_CH_AVOID */
 
     VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s", __func__);
 
@@ -423,14 +431,40 @@
 
     // Fill the channel number in the spectrum in the operating freq band
     for (channelnum = 0; channelnum < pSpectInfoParams->numSpectChans; channelnum++) {
+#ifdef FEATURE_WLAN_CH_AVOID
+        chSafe = VOS_TRUE;
+        for(i = 0; i < NUM_20MHZ_RF_CHANNELS; i++)
+        {
+            if((safeChannels[i].channelNumber == *pChans) &&
+               (VOS_FALSE == safeChannels[i].isSafe))
+            {
+               VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+                         "%s : CH %d is not safe", __func__, *pChans);
+               chSafe = VOS_FALSE;
+               break;
+            }
+        }
+#endif /* FEATURE_WLAN_CH_AVOID */
 
         if(*pChans == 14 ) //OFDM rates are not supported on channel 14
             continue;
-        pSpectCh->chNum = *pChans;
-        pSpectCh->valid = eSAP_TRUE;
-        pSpectCh->rssiAgr = SOFTAP_MIN_RSSI;// Initialise for all channels
-        pSpectCh->channelWidth = SOFTAP_HT20_CHANNELWIDTH; // Initialise 20MHz for all the Channels 
-        pSpectCh++;
+#ifdef FEATURE_WLAN_CH_AVOID
+        if (VOS_TRUE == chSafe)
+        {
+#endif /* FEATURE_WLAN_CH_AVOID */
+           VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_DEBUG,
+                     "%s : Available Ch %d",
+                     __func__, *pChans);
+           pSpectCh->chNum = *pChans;
+           pSpectCh->valid = eSAP_TRUE;
+           // Initialise for all channels
+           pSpectCh->rssiAgr = SOFTAP_MIN_RSSI;
+           // Initialise 20MHz for all the Channels
+           pSpectCh->channelWidth = SOFTAP_HT20_CHANNELWIDTH;
+           pSpectCh++;
+#ifdef FEATURE_WLAN_CH_AVOID
+        }
+#endif /* FEATURE_WLAN_CH_AVOID */
         pChans++;
     }
     return eSAP_TRUE;
diff --git a/CORE/SME/inc/smeInternal.h b/CORE/SME/inc/smeInternal.h
index a14e705..8031546 100644
--- a/CORE/SME/inc/smeInternal.h
+++ b/CORE/SME/inc/smeInternal.h
@@ -153,6 +153,9 @@
     tDblLinkList smeScanCmdPendingList;
     //active scan command list
     tDblLinkList smeScanCmdActiveList;
+#ifdef FEATURE_WLAN_CH_AVOID
+    void (*pChAvoidNotificationCb) (void *pAdapter, void *indParam);
+#endif /* FEATURE_WLAN_CH_AVOID */
 } tSmeStruct, *tpSmeStruct;
 
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index f12d900..1680abe 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -3161,4 +3161,21 @@
 );
 
 #endif
+
+#ifdef FEATURE_WLAN_CH_AVOID
+/* ---------------------------------------------------------------------------
+    \fn sme_AddChAvoidCallback
+    \brief  Used to plug in callback function
+            Which notify channel may not be used with SAP or P2PGO mode.
+            Notification come from FW.
+    \param  hHal
+    \param  pCallbackfn : callback function pointer should be plugged in
+    \- return eHalStatus
+    -------------------------------------------------------------------------*/
+eHalStatus sme_AddChAvoidCallback
+(
+   tHalHandle hHal,
+   void (*pCallbackfn)(void *pAdapter, void *indParam)
+);
+#endif /* FEATURE_WLAN_CH_AVOID */
 #endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 5c68639..d369a75 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -2147,6 +2147,20 @@
                 break;
 #endif /* FEATURE_WLAN_LPHB */
 
+#ifdef FEATURE_WLAN_CH_AVOID
+          /* LPHB timeout indication arrived, send IND to client */
+          case eWNI_SME_CH_AVOID_IND:
+                if (pMac->sme.pChAvoidNotificationCb)
+                {
+                   VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+                             "%s: CH avoid notification", __func__);
+                   pMac->sme.pChAvoidNotificationCb(pMac->pAdapter, pMsg->bodyptr);
+                }
+                vos_mem_free(pMsg->bodyptr);
+
+                break;
+#endif /* FEATURE_WLAN_CH_AVOID */
+
           default:
 
              if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN )
@@ -10101,3 +10115,40 @@
 }
 
 #endif
+
+#ifdef FEATURE_WLAN_CH_AVOID
+/* ---------------------------------------------------------------------------
+    \fn sme_AddChAvoidCallback
+    \brief  Used to plug in callback function
+            Which notify channel may not be used with SAP or P2PGO mode.
+            Notification come from FW.
+    \param  hHal
+    \param  pCallbackfn : callback function pointer should be plugged in
+    \- return eHalStatus
+    -------------------------------------------------------------------------*/
+eHalStatus sme_AddChAvoidCallback
+(
+   tHalHandle hHal,
+   void (*pCallbackfn)(void *pAdapter, void *indParam)
+)
+{
+    eHalStatus          status    = eHAL_STATUS_SUCCESS;
+    tpAniSirGlobal      pMac      = PMAC_STRUCT(hHal);
+
+    VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
+              "%s: Plug in CH AVOID CB", __func__);
+
+    status = sme_AcquireGlobalLock(&pMac->sme);
+    if (eHAL_STATUS_SUCCESS == status)
+    {
+        if (NULL != pCallbackfn)
+        {
+           pMac->sme.pChAvoidNotificationCb = pCallbackfn;
+        }
+        sme_ReleaseGlobalLock(&pMac->sme);
+    }
+
+    return(status);
+}
+#endif /* FEATURE_WLAN_CH_AVOID */
+
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 0279d2a..30420e8 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -12690,6 +12690,45 @@
      }
 #endif
 
+#ifdef FEATURE_WLAN_CH_AVOID
+      case WDI_CH_AVOID_IND:
+      {
+         vos_msg_t            vosMsg;
+         tSirChAvoidIndType  *chAvoidInd;
+
+         chAvoidInd =
+           (tSirChAvoidIndType *)vos_mem_malloc(sizeof(tSirChAvoidIndType));
+         if (NULL == chAvoidInd)
+         {
+            VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: CH_AVOID IND buffer alloc Fail", __func__);
+            return ;
+         }
+
+         chAvoidInd->avoidRangeCount =
+              wdiLowLevelInd->wdiIndicationData.wdiChAvoidInd.avoidRangeCount;
+         wpalMemoryCopy((void *)chAvoidInd->avoidFreqRange,
+             (void *)wdiLowLevelInd->wdiIndicationData.wdiChAvoidInd.avoidFreqRange,
+             chAvoidInd->avoidRangeCount * sizeof(tSirChAvoidFreqType));
+
+         VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                   "%s : WDA CH avoid notification", __func__);
+
+         vosMsg.type    = eWNI_SME_CH_AVOID_IND;
+         vosMsg.bodyptr = chAvoidInd;
+         vosMsg.bodyval = 0;
+         /* Send message to SME */
+         if (VOS_STATUS_SUCCESS !=
+             vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vosMsg))
+         {
+            VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                      "post eWNI_SME_CH_AVOID_IND to SME Failed");
+            vos_mem_free(chAvoidInd);
+         }
+         break;
+      }
+#endif /* FEATURE_WLAN_CH_AVOID */
+
       default:
       {
          /* TODO error */
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index ccf2c5e..fcce9ba 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -411,6 +411,10 @@
   WDI_BATCH_SCAN_RESULT_IND,
 #endif
 
+#ifdef FEATURE_WLAN_CH_AVOID
+  WDI_CH_AVOID_IND,
+#endif /* FEATURE_WLAN_CH_AVOID */
+
   WDI_MAX_IND
 }WDI_LowLevelIndEnumType;
 
@@ -805,6 +809,22 @@
 
 } WDI_RateUpdateIndParams;
 
+#ifdef FEATURE_WLAN_CH_AVOID
+#define WDI_CH_AVOID_MAX_RANGE   4
+
+typedef struct
+{
+   wpt_uint32 startFreq;
+   wpt_uint32 endFreq;
+} WDI_ChAvoidFreqType;
+
+typedef struct
+{
+   wpt_uint32          avoidRangeCount;
+   WDI_ChAvoidFreqType avoidFreqRange[WDI_CH_AVOID_MAX_RANGE];
+} WDI_ChAvoidIndType;
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 /*---------------------------------------------------------------------------
   WDI_LowLevelIndType
     Inidcation type and information about the indication being carried
@@ -870,6 +890,9 @@
     void *pBatchScanResult;
 #endif
 
+#ifdef FEATURE_WLAN_CH_AVOID
+    WDI_ChAvoidIndType          wdiChAvoidInd;
+#endif /* FEATURE_WLAN_CH_AVOID */
   }  wdiIndicationData;
 }WDI_LowLevelIndType;
 
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index aa6492c..aca2df6 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -823,6 +823,7 @@
 #endif
 
 
+  WDI_HAL_CH_AVOID_IND                 = WDI_HAL_IND_MIN + 18,
   WDI_MAX_RESP
 }WDI_ResponseEnumType; 
 
@@ -5596,5 +5597,23 @@
 
 #endif /* FEATURE_WLAN_BATCH_SCAN */
 
+#ifdef FEATURE_WLAN_CH_AVOID
+/**
+ @brief v -
+
+
+ @param  pWDICtx : wdi context
+         pEventData : indication data
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessChAvoidInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 #endif /*WLAN_QCT_WDI_I_H*/
 
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index 5bebc56..0c83dac 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -678,6 +678,12 @@
   NULL,
 #endif
 
+#ifdef FEATURE_WLAN_CH_AVOID
+    WDI_ProcessChAvoidInd,               /* WDI_LBP_UPDATE_IND_TO_HOST */
+#else
+   NULL,
+#endif /* FEATURE_WLAN_CH_AVOID */
+
 };
 
 
@@ -23114,6 +23120,11 @@
     return WDI_BATCHSCAN_RESULT_IND;
 #endif // FEATURE_WLAN_BATCH_SCAN
 
+#ifdef FEATURE_WLAN_CH_AVOID
+  case WLAN_HAL_AVOID_FREQ_RANGE_IND:
+    return WDI_HAL_CH_AVOID_IND;
+#endif /* FEATURE_WLAN_CH_AVOID */
+
   default:
     return eDRIVER_TYPE_MAX;
   }
@@ -29164,5 +29175,74 @@
 
     return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
 }
-
 #endif /*FEATURE_WLAN_BATCH_SCAN*/
+
+#ifdef FEATURE_WLAN_CH_AVOID
+/**
+ @brief v -WDI_ProcessChAvoidInd
+
+
+ @param  pWDICtx : wdi context
+         pEventData : indication data
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessChAvoidInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  WDI_LowLevelIndType  wdiInd;
+  tHalAvoidFreqRangeIndParams chAvoidIndicationParam;
+  wpt_uint16           rangeLoop;
+  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+  /*-------------------------------------------------------------------------
+  Sanity check
+ -------------------------------------------------------------------------*/
+  if ((NULL == pWDICtx) || (NULL == pEventData) ||
+      (NULL == pEventData->pEventData))
+  {
+     WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                 "%s: Invalid parameters", __func__);
+     WDI_ASSERT(0);
+     return WDI_STATUS_E_FAILURE;
+  }
+
+  /*-------------------------------------------------------------------------
+  Extract indication and send it to UMAC
+ -------------------------------------------------------------------------*/
+  wpalMemoryCopy(&chAvoidIndicationParam,
+                 pEventData->pEventData,
+                 sizeof(tHalAvoidFreqRangeIndParams));
+
+  wdiInd.wdiIndicationType = WDI_CH_AVOID_IND;
+  wdiInd.wdiIndicationData.wdiChAvoidInd.avoidRangeCount =
+               chAvoidIndicationParam.avoidCnt;
+  wpalMemoryCopy((void *)wdiInd.wdiIndicationData.wdiChAvoidInd.avoidFreqRange,
+                 (void *)chAvoidIndicationParam.avoidRange,
+                 wdiInd.wdiIndicationData.wdiChAvoidInd.avoidRangeCount *
+                 sizeof(WDI_ChAvoidFreqType));
+  WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+          "%s: band count %d", __func__,
+          wdiInd.wdiIndicationData.wdiChAvoidInd.avoidRangeCount);
+  for (rangeLoop = 0; rangeLoop < chAvoidIndicationParam.avoidCnt; rangeLoop++)
+  {
+     WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+          "%s: srart freq %d, end freq %d", __func__,
+          wdiInd.wdiIndicationData.wdiChAvoidInd.avoidFreqRange[rangeLoop].startFreq,
+          wdiInd.wdiIndicationData.wdiChAvoidInd.avoidFreqRange[rangeLoop].endFreq);
+  }
+
+  /*Notify UMAC*/
+  if (pWDICtx->wdiLowLevelIndCB)
+  {
+    pWDICtx->wdiLowLevelIndCB(&wdiInd, pWDICtx->pIndUserData);
+  }
+
+  return WDI_STATUS_SUCCESS;
+}
+#endif /* FEATURE_WLAN_CH_AVOID */
+
diff --git a/Kbuild b/Kbuild
index f2e6740..ca2f403 100644
--- a/Kbuild
+++ b/Kbuild
@@ -643,6 +643,8 @@
 CDEFINES += -DCONFIG_ENABLE_LINUX_REG
 endif
 
+CDEFINES += -DFEATURE_WLAN_CH_AVOID
+
 # Fix build for GCC 4.7
 EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function