wlan: SAPHT40 2.4GHz:Add HT40 timer support

To move SAP from HT20 to HT40 Added HT40 timer support

Change-Id: I9cac15332c33cf9ca9d90cccb7256358d6f6b44e
CRs-Fixed: 760811
diff --git a/CORE/SAP/src/sapApiLinkCntl.c b/CORE/SAP/src/sapApiLinkCntl.c
index 8b5ced2..af96442 100644
--- a/CORE/SAP/src/sapApiLinkCntl.c
+++ b/CORE/SAP/src/sapApiLinkCntl.c
@@ -192,6 +192,84 @@
 
 #ifdef WLAN_FEATURE_AP_HT40_24G
 /*==========================================================================
+  FUNCTION    sap_ht2040_timer_cb()
+
+  DESCRIPTION
+    SAP HT40 timer CallBack, Once this function execute it will move SAP
+    from HT20 to HT40
+
+  DEPENDENCIES
+    NA.
+
+  PARAMETERS
+
+    IN
+    usrDataForCallback   : The second context pass in for the caller (sapContext)
+
+  RETURN VALUE
+  SIDE EFFECTS
+============================================================================*/
+void sap_ht2040_timer_cb(v_PVOID_t usrDataForCallback)
+{
+    v_U8_t cbMode;
+    tHalHandle hHal;
+    eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+    ptSapContext sapContext = (ptSapContext)usrDataForCallback;
+    eSapPhyMode sapPhyMode;
+
+    hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME,
+                                             sapContext->pvosGCtx);
+    if (NULL == hHal)
+    {
+        /* we have a serious problem */
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL,
+                   FL("Invalid hHal"));
+       return;
+    }
+
+    cbMode = sme_GetChannelBondingMode24G(hHal);
+
+    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+               FL("Current Channel bonding : %d"), cbMode);
+
+    if(cbMode)
+    {
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_FATAL,
+                  FL("Already in HT40 Channel bonding : %d"), cbMode);
+       return;
+    }
+
+    sapPhyMode =
+        sapConvertSapPhyModeToCsrPhyMode(sapContext->csrRoamProfile.phyMode);
+
+    sme_SelectCBMode(hHal, sapPhyMode, sapContext->channel);
+
+    cbMode = sme_GetChannelBondingMode24G(hHal);
+
+    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+               FL("Selected Channel bonding : %d"), cbMode);
+
+    if(cbMode)
+    {
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+                   FL("Move SAP from HT20 to HT40"));
+
+        if (cbMode == eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY)
+            cbMode = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+        else if (cbMode == eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY)
+            cbMode = PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+
+        halStatus = sme_SetHT2040Mode(hHal, sapContext->sessionId, cbMode);
+
+        if (halStatus == eHAL_STATUS_FAILURE )
+        {
+            VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                              FL("Failed to change HT20/40 mode"));
+        }
+    }
+}
+
+/*==========================================================================
   FUNCTION    sapCheckHT2040CoexAction()
 
   DESCRIPTION
@@ -221,6 +299,8 @@
     tHalHandle hHal;
     v_U8_t cbMode;
     eHalStatus halStatus;
+    VOS_STATUS  vosStatus = VOS_STATUS_SUCCESS;
+    unsigned int delay;
 
     /* tHalHandle */
     hHal = VOS_GET_HAL_CB(psapCtx->pvosGCtx);
@@ -322,9 +402,38 @@
             sme_UpdateChannelBondingMode24G(hHal,
                                 PHY_SINGLE_CHANNEL_CENTERED);
         }
-        else
-            VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
-                   FL("SAP is Already in HT20"));
+
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+                FL("SAP is Already in HT20"));
+
+        if (!psapCtx->numHT40IntoSta)
+        {
+            /* Stop Previous Running HT20/40 Timer & Start timer
+               with (OBSS TransitionDelayFactor * obss interval)
+               delay after time out move AP from HT20 -> HT40
+               mode
+             */
+            if (VOS_TIMER_STATE_RUNNING == psapCtx->sap_HT2040_timer.state)
+            {
+                vosStatus = vos_timer_stop(&psapCtx->sap_HT2040_timer);
+                if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+                    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                               FL("Failed to Stop HT20/40 timer"));
+            }
+
+            delay = psapCtx->ObssScanInterval * psapCtx->ObssTransitionDelayFactor;
+
+            VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                       FL("Start HT20/40 itransition"
+                       " timer (%d sec)"), delay);
+
+            vosStatus = vos_timer_start( &psapCtx->sap_HT2040_timer,
+                                                (delay * 1000));
+
+            if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+                VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                            FL("Failed to Start HT20/40 timer"));
+        }
     }
     return;
 }
diff --git a/CORE/SAP/src/sapFsm.c b/CORE/SAP/src/sapFsm.c
index ab678a1..572304a 100644
--- a/CORE/SAP/src/sapFsm.c
+++ b/CORE/SAP/src/sapFsm.c
@@ -67,6 +67,7 @@
 #include "sapInternal.h"
 #ifdef WLAN_FEATURE_AP_HT40_24G
 #include "csrInsideApi.h"
+#include "cfgApi.h"
 #endif
 // Pick up the SME API definitions
 #include "sme_Api.h"
@@ -146,6 +147,80 @@
    sapEvent->u2 = 0;
 }
 
+#ifdef WLAN_FEATURE_AP_HT40_24G
+/*==========================================================================
+  FUNCTION    sapSetObssParm
+
+  DESCRIPTION
+    Function for Setting OBSS Scan interval & OBSS TRANS_DELAY_FACTOR
+
+  DEPENDENCIES
+    NA.
+
+  PARAMETERS
+
+    IN
+    sapContext  : Sap Context value
+
+  RETURN VALUE
+    The VOS_STATUS code associated with performing the operation
+
+    VOS_STATUS_SUCCESS: Success
+
+  SIDE EFFECTS
+============================================================================*/
+void sapSetObssParm(ptSapContext sapContext)
+{
+    tHalHandle hHal;
+    tpAniSirGlobal pMac;
+    tANI_U32 cfgValue;
+
+    /* tHalHandle */
+    hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx);
+
+    if (NULL == hHal)
+    {
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                   FL("Invalid hHal"));
+        return;
+    }
+
+    pMac = PMAC_STRUCT( hHal );
+
+    if (wlan_cfgGetInt(pMac, WNI_CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL,
+                       &cfgValue) != eSIR_SUCCESS)
+    {
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                FL("Fail to retrieve"
+                "WNI_CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL value"));
+       return;
+    }
+
+    sapContext->ObssScanInterval = cfgValue;
+
+    if (wlan_cfgGetInt(pMac,
+          WNI_CFG_OBSS_HT40_WIDTH_CHANNEL_TRANSITION_DELAY_FACTOR,
+                       &cfgValue) != eSIR_SUCCESS)
+    {
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+              FL("Fail to retrieve"
+              "WNI_CFG_OBSS_HT40_WIDTH_CHANNEL_TRANSITION_DELAY_FACTOR value"));
+       return;
+    }
+
+    sapContext->ObssTransitionDelayFactor = cfgValue;
+
+    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+               FL("ObssScanInterval: %d"
+                 " ObssTransitionDelayFactor: %d"),
+               sapContext->ObssScanInterval,
+               sapContext->ObssTransitionDelayFactor);
+
+    return;
+}
+#endif
+
+
 /*==========================================================================
   FUNCTION    sapGotoChannelSel
 
@@ -928,6 +1003,9 @@
                 /* Set SAP device role */
                 sapContext->sapsMachine = eSAP_CH_SELECT;
 
+#ifdef WLAN_FEATURE_AP_HT40_24G
+                sapSetObssParm(sapContext);
+#endif
                 /* Perform sme_ScanRequest */
                 vosStatus = sapGotoChannelSel(sapContext, sapEvent);
 
@@ -980,6 +1058,20 @@
                  /* Transition from eSAP_STARTING to eSAP_STARTED (both without substates) */
                  VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, from state %s => %s",
                             __func__, "eSAP_STARTING", "eSAP_STARTED");
+
+#ifdef WLAN_FEATURE_AP_HT40_24G
+                /* Initialize the HT2040 timer */
+                VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                           "In %s, Init HT20/40 timer", __func__);
+
+                vosStatus = vos_timer_init( &sapContext->sap_HT2040_timer,
+                                 VOS_TIMER_TYPE_SW, sap_ht2040_timer_cb,
+                                 (v_PVOID_t)sapContext );
+
+                if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+                    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                               "In %s, Failed to Init HT20/40 timer", __func__);
+#endif
              }
              else if (msg == eSAP_MAC_START_FAILS)
              {
@@ -1056,26 +1148,39 @@
                            __func__, "eSAP_STARTED", "eSAP_DISCONNECTING");
                 sapContext->sapsMachine = eSAP_DISCONNECTING;
                 vosStatus = sapGotoDisconnecting(sapContext);
-#ifdef WLAN_FEATURE_AP_HT40_24G
-                /* Reset the OBSS Affected Channel Range */
-                if ( (0 != sapContext->affected_start)
-                  && (0 != sapContext->affected_end)
-                  && (0 != sapContext->sap_sec_chan) )
-                {
-                    sapContext->affected_start = 0;
-                    sapContext->affected_end = 0;
-                    sapContext->sap_sec_chan = 0;
-                    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
-                         FL("Reset the OBSS Affected Channel Range [%d %d]"),
-                         sapContext->affected_start, sapContext->affected_end);
-                }
-#endif
             }
             else
             {
                 VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, in state %s, invalid event msg %d",
                            __func__, "eSAP_STARTED", msg);
             }
+#ifdef WLAN_FEATURE_AP_HT40_24G
+            /* Reset the OBSS Affected Channel Range */
+            if ( (0 != sapContext->affected_start)
+               && (0 != sapContext->affected_end)
+               && (0 != sapContext->sap_sec_chan) )
+            {
+                sapContext->affected_start = 0;
+                sapContext->affected_end = 0;
+                sapContext->sap_sec_chan = 0;
+                VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
+                     FL("Reset the OBSS Affected Channel Range [%d %d]"),
+                     sapContext->affected_start, sapContext->affected_end);
+            }
+
+            if (VOS_TIMER_STATE_RUNNING == sapContext->sap_HT2040_timer.state)
+            {
+                vosStatus = vos_timer_stop(&sapContext->sap_HT2040_timer);
+                if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+                    VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                              FL("Failed to Stop HT20/40 timer"));
+            }
+
+            vosStatus = vos_timer_destroy(&sapContext->sap_HT2040_timer);
+            if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+                VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                          FL("Failed to Destroy HT20/40 timer"));
+#endif
             break;
 
         case eSAP_DISCONNECTING:
@@ -1479,6 +1584,7 @@
     v_U8_t cbMode;
     tANI_U8  staId;
     eHalStatus halStatus;
+    VOS_STATUS  vosStatus = VOS_STATUS_SUCCESS;
 
     /* tHalHandle */
     hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx);
@@ -1522,6 +1628,16 @@
                " STA ID: %d HT40IntolerantSet: %d"),
                 sapContext->numHT40IntoSta,
                 staId, sapContext->aStaInfo[staId].isHT40IntolerantSet);
+
+    /* Stop HT20/40 Timer */
+    if (VOS_TIMER_STATE_RUNNING == sapContext->sap_HT2040_timer.state)
+    {
+        vosStatus = vos_timer_stop(&sapContext->sap_HT2040_timer);
+        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+            VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                      FL("Failed to Stop HT20/40 timer"));
+    }
+
     if(cbMode)
     {
         VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO,
@@ -1571,6 +1687,8 @@
                                           tCsrRoamInfo *pCsrRoamInfo)
 {
     tANI_U8  staId;
+    VOS_STATUS  vosStatus = VOS_STATUS_SUCCESS;
+    unsigned int delay;
 
     staId = pCsrRoamInfo->staId;
 
@@ -1590,6 +1708,7 @@
     }
 
     sapContext->aStaInfo[pCsrRoamInfo->staId].isHT40IntolerantSet = 0;
+
     if (sapContext->numHT40IntoSta > 0)
         sapContext->numHT40IntoSta--;
 
@@ -1599,6 +1718,35 @@
                 sapContext->numHT40IntoSta,
                 staId, sapContext->aStaInfo[staId].isHT40IntolerantSet);
 
+    if (!sapContext->numHT40IntoSta)
+    {
+        /* Stop Previous Running HT20/40 Timer & Start timer
+           with (OBSS TransitionDelayFactor * obss interval)
+           delay after time out move AP from HT20 -> HT40
+           mode
+         */
+        if (VOS_TIMER_STATE_RUNNING == sapContext->sap_HT2040_timer.state)
+        {
+            vosStatus = vos_timer_stop(&sapContext->sap_HT2040_timer);
+            if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+                 VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                          FL("Failed to Stop HT20/40 timer"));
+        }
+
+        delay =
+         (sapContext->ObssScanInterval * sapContext->ObssTransitionDelayFactor);
+
+        VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                   FL("Start HT20/40 itransition"
+                   " timer (%d sec)"), delay);
+
+        vosStatus = vos_timer_start( &sapContext->sap_HT2040_timer,
+                                              (delay * 1000));
+
+        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+             VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+                       FL("Failed to Start HT20/40 timer"));
+    }
     return;
 }
 #endif
diff --git a/CORE/SAP/src/sapInternal.h b/CORE/SAP/src/sapInternal.h
index 8c6375f..8f3aed5 100644
--- a/CORE/SAP/src/sapInternal.h
+++ b/CORE/SAP/src/sapInternal.h
@@ -270,6 +270,9 @@
     v_U8_t            affected_end;
     v_U8_t            sap_sec_chan;
     v_U8_t            numHT40IntoSta;
+    vos_timer_t       sap_HT2040_timer;
+    v_U8_t            ObssScanInterval;
+    v_U8_t            ObssTransitionDelayFactor;
 #endif
 } *ptSapContext;
 
@@ -887,6 +890,17 @@
 ============================================================================*/
 eCsrPhyMode sapConvertSapPhyModeToCsrPhyMode( eSapPhyMode sapPhyMode );
 
+#ifdef WLAN_FEATURE_AP_HT40_24G
+/*==========================================================================
+FUNCTION  sap_ht2040_timer_cb
+
+DESCRIPTION Function to implement ht2040 timer callback implementation
+
+SIDE EFFECTS
+============================================================================*/
+void sap_ht2040_timer_cb(v_PVOID_t usrDataForCallback);
+#endif
+
 #ifdef __cplusplus
 }
 #endif 
diff --git a/Kbuild b/Kbuild
index 9a665a9..0f0c5d7 100644
--- a/Kbuild
+++ b/Kbuild
@@ -661,6 +661,7 @@
 endif
 
 CDEFINES += -DFEATURE_WLAN_CH_AVOID
+CDEFINES += -DWLAN_FEATURE_AP_HT40_24G
 
 # Some kernel include files are being moved.  Check to see if
 # the old version of the files are present