sap: Add scan band preference threshold

Current ACS implementation does not have the capability of switching
scan band when the environment is noisy. Added configurable weight
threshold to trigger AP scan next band for choosing best channel.

Change-Id: I7d9831db48d73282eccb8583760ae71b3a866ca6
CRs-fixed: 722429
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 6ed83f2..f61f5ee 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1609,6 +1609,11 @@
 #define CFG_SAP_SCAN_BAND_PREFERENCE_MIN          (0)
 #define CFG_SAP_SCAN_BAND_PREFERENCE_MAX          (2)
 #define CFG_SAP_SCAN_BAND_PREFERENCE_DEFAULT      (0)
+#define CFG_ACS_BAND_SWITCH_THRESHOLD             "gACSBandSwitchThreshold"
+#define CFG_ACS_BAND_SWITCH_THRESHOLD_MIN         (0)
+#define CFG_ACS_BAND_SWITCH_THRESHOLD_MAX         (4444)
+/* 2 BSS, maximus RSSI -90 */
+#define CFG_ACS_BAND_SWITCH_THRESHOLD_DEFAULT     (296)
 
 /*BMPS Logic
  * Notes:
@@ -2828,6 +2833,7 @@
    v_U8_t                      enableDhcpDebug; /* Enable/Disable dhcp debug */
    v_U32_t                     burstModeTXOPValue;
    v_U8_t                      acsScanBandPreference;
+   v_U16_t                     acsBandSwitchThreshold;
 } hdd_config_t;
 /*--------------------------------------------------------------------------- 
   Function declarations and documenation
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index b25144e..828a930 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -3583,6 +3583,7 @@
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gRoamtoDFSChannel] Value = [%u] ",pHddCtx->cfg_ini->allowDFSChannelRoam);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gMaxConcurrentActiveSessions] Value = [%u] ", pHddCtx->cfg_ini->gMaxConcurrentActiveSessions);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gAcsScanBandPreference] Value = [%u] ",pHddCtx->cfg_ini->acsScanBandPreference);
+  VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,"Name = [gACSBandSwitchThreshold] value = [%u]\n",pHddCtx->cfg_ini->acsBandSwitchThreshold);
 }
 
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index ac89e87..dd67f73 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -6171,6 +6171,7 @@
         pConfig->scanBandPreference = psmeConfig->csrConfig.scanBandPreference;
         vos_mem_free(psmeConfig);
     }
+    pConfig->acsBandSwitchThreshold = iniConfig->acsBandSwitchThreshold;
 
     pSapEventCallback = hdd_hostapd_SAPEventCB;
     if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
diff --git a/CORE/SAP/inc/sapApi.h b/CORE/SAP/inc/sapApi.h
index 0bc2ee6..cfd9570 100644
--- a/CORE/SAP/inc/sapApi.h
+++ b/CORE/SAP/inc/sapApi.h
@@ -456,6 +456,7 @@
     v_BOOL_t        mfpCapable;
 #endif
     eCsrBand        scanBandPreference;
+    v_U16_t         acsBandSwitchThreshold;
 
 } tsap_Config_t;
 
diff --git a/CORE/SAP/src/sapChSelect.c b/CORE/SAP/src/sapChSelect.c
index 3663652..46d2766 100644
--- a/CORE/SAP/src/sapChSelect.c
+++ b/CORE/SAP/src/sapChSelect.c
@@ -66,6 +66,7 @@
 #ifdef ANI_OS_TYPE_QNX
 #include "stdio.h"
 #endif
+#include "wlan_hdd_main.h"
 
 /*--------------------------------------------------------------------------
   Function definitions
@@ -1741,13 +1742,14 @@
     // DFS param object holding all the data req by the algo
     tSapChSelSpectInfo oSpectInfoParams = {NULL,0}; 
     tSapChSelSpectInfo *pSpectInfoParams = &oSpectInfoParams; // Memory? NB    
-    v_U8_t bestChNum = 0;
+    v_U8_t bestChNum = SAP_CHANNEL_NOT_SELECTED;
 #ifdef SOFTAP_CHANNEL_RANGE
     v_U32_t startChannelNum;
     v_U32_t endChannelNum;
     v_U32_t operatingBand = 0;
-    v_U8_t  count = 0;
-#endif    
+    v_U32_t tmpChNum;
+    v_U8_t  count;
+#endif
     VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch Select", __func__);
 
     // Set to zero tSapChSelParams
@@ -1768,9 +1770,12 @@
 #ifdef SOFTAP_CHANNEL_RANGE
     if (eCSR_BAND_ALL == pSapCtx->scanBandPreference)
     {
-        ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL, &startChannelNum);
-        ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL, &endChannelNum);
-        ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, &operatingBand);
+        ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL,
+                                                        &startChannelNum);
+        ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL,
+                                                          &endChannelNum);
+        ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND,
+                                                          &operatingBand);
     }
     else
     {
@@ -1788,6 +1793,9 @@
         }
      }
 
+    pSapCtx->acsBestChannelInfo.channelNum = 0;
+    pSapCtx->acsBestChannelInfo.weight = CFG_ACS_BAND_SWITCH_THRESHOLD_MAX;
+
     /*Loop till get the best channel in the given range */
     for(count=0; count < pSpectInfoParams->numSpectChans ; count++)
     {
@@ -1799,9 +1807,51 @@
             {
                 continue; //skip this channel, continue to next channel
             }
-            if(bestChNum == 0)
+            if(bestChNum == SAP_CHANNEL_NOT_SELECTED)
             {
-                bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum;
+                bestChNum = pSpectInfoParams->pSpectCh[count].chNum;
+                /* check if bestChNum is in preferred channel list */
+                bestChNum = sapSelectPreferredChannelFromChannelList(
+                        bestChNum, pSapCtx, pSpectInfoParams);
+                if (bestChNum == SAP_CHANNEL_NOT_SELECTED)
+                {
+                    /* not in preferred channel list, go to next best channel*/
+                    continue;
+                }
+
+                if (pSpectInfoParams->pSpectCh[count].weight >
+                        pSapCtx->acsBandSwitchThreshold)
+                {
+                    /* the best channel exceeds the threshold
+                       check if need to scan next band */
+                    if ((eCSR_BAND_ALL !=  pSapCtx->scanBandPreference) &&
+                            !pSapCtx->allBandScanned)
+                    {
+                        /* store best channel for later comparison */
+                        pSapCtx->acsBestChannelInfo.channelNum = bestChNum;
+                        pSapCtx->acsBestChannelInfo.weight =
+                            pSpectInfoParams->pSpectCh[count].weight;
+                        bestChNum = SAP_CHANNEL_NOT_SELECTED;
+                        break;
+                    }
+                    else
+                    {
+                        /* all bands are scanned, compare current best channel
+                           with channel scanned previously */
+                        if ( pSpectInfoParams->pSpectCh[count].weight >
+                                pSapCtx->acsBestChannelInfo.weight)
+                        {
+                            /* previous stored channel is better */
+                            bestChNum = pSapCtx->acsBestChannelInfo.channelNum;
+                        }
+                        else
+                        {
+                            pSapCtx->acsBestChannelInfo.channelNum = bestChNum;
+                            pSapCtx->acsBestChannelInfo.weight =
+                                pSpectInfoParams->pSpectCh[count].weight;
+                        }
+                    }
+                }
             }
             else
             {
@@ -1809,13 +1859,22 @@
                 {
                     /* Give preference to Non-overlap channels */
                     if(((pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_1) ||
-                      (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_6) ||
-                      (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_11))&&
-                      (pSpectInfoParams->pSpectCh[count].weight == 0))
-                      {
-                           bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum;
-                           break;
-                      }
+                                (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_6) ||
+                                (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_11))&&
+                            (pSpectInfoParams->pSpectCh[count].weight ==
+                             pSapCtx->acsBestChannelInfo.weight))
+                    {
+                        tmpChNum = pSpectInfoParams->pSpectCh[count].chNum;
+                        tmpChNum =
+                            sapSelectPreferredChannelFromChannelList(tmpChNum,
+                                    pSapCtx, pSpectInfoParams);
+                        if ( tmpChNum != SAP_CHANNEL_NOT_SELECTED)
+                        {
+                            bestChNum = tmpChNum;
+                            break;
+                        }
+
+                    }
                 }
             }
          }
@@ -1823,10 +1882,10 @@
 #else
     // Get the first channel in sorted array as best 20M Channel
     bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[0].chNum;
-#endif
-
     //Select Best Channel from Channel List if Configured
-    bestChNum = sapSelectPreferredChannelFromChannelList(bestChNum, pSapCtx, pSpectInfoParams);
+    bestChNum = sapSelectPreferredChannelFromChannelList(bestChNum,
+                                                  pSapCtx, pSpectInfoParams);
+#endif
 
     // Free all the allocated memory
     sapChanSelExit(pSpectInfoParams);
diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h
index 71f082e..98a7811 100644
--- a/CORE/SAP/src/sapInternal.h
+++ b/CORE/SAP/src/sapInternal.h
@@ -141,6 +141,11 @@
     v_U8_t              WmmIsEnabled;
 } tSapQosCfg;
 
+typedef struct sSapAcsChannelInfo {
+    v_U32_t             channelNum;
+    v_U32_t             weight;
+}tSapAcsChannelInfo;
+
 typedef struct sSapContext {
 
     vos_lock_t          SapGlobalLock;
@@ -213,6 +218,8 @@
     tANI_BOOLEAN       allBandScanned;
     eCsrBand           currentPreferredBand;
     eCsrBand           scanBandPreference;
+    v_U16_t            acsBandSwitchThreshold;
+    tSapAcsChannelInfo acsBestChannelInfo;
 } *ptSapContext;
 
 
diff --git a/CORE/SAP/src/sapModule.c b/CORE/SAP/src/sapModule.c
index a05fa39..1f9c35e 100644
--- a/CORE/SAP/src/sapModule.c
+++ b/CORE/SAP/src/sapModule.c
@@ -593,6 +593,7 @@
         /* Channel selection is auto or configured */
         pSapCtx->channel = pConfig->channel;
         pSapCtx->scanBandPreference = pConfig->scanBandPreference;
+        pSapCtx->acsBandSwitchThreshold = pConfig->acsBandSwitchThreshold;
         pSapCtx->pUsrContext = pUsrContext;
 
         //Set the BSSID to your "self MAC Addr" read the mac address from Configuation ITEM received from HDD