wlan: Enable wow before going to suspend state.

When WoWL is enabled, remember whether device is exiting from
WoWL because of wake-up indication or user explicitly disabling
WoWL. If device is coming out of WoWL because of wake-up indication
then re-enable it while going to suspend state.

Change-Id: I629993364413d0d4132b806452b42fdeb68c22ca
CRs-Fixed: 685406
diff --git a/CORE/SME/inc/pmc.h b/CORE/SME/inc/pmc.h
index e6164ef..0afe567 100644
--- a/CORE/SME/inc/pmc.h
+++ b/CORE/SME/inc/pmc.h
@@ -177,6 +177,7 @@
     tANI_BOOLEAN pmcReady; /*whether eWNI_SME_SYS_READY_IND has been sent to PE or not */
     tANI_BOOLEAN wowlEnabled;  /* TRUE if WoWL is enabled */
     tANI_BOOLEAN wowlModeRequired; /* TRUE if device should go to WOWL on entering BMPS */
+    tWowlExitSource wowlExitSrc; /*WoWl exiting because of wakeup pkt or user explicitly disabling WoWL*/
     void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call for wowl request */ 
     void *enterWowlCallbackContext;/* value to be passed as parameter to routine specified above */
     tSirSmeWowlEnterParams wowlEnterParams; /* WOWL mode configuration */
diff --git a/CORE/SME/inc/pmcApi.h b/CORE/SME/inc/pmcApi.h
index d0d965b..e085be2 100644
--- a/CORE/SME/inc/pmcApi.h
+++ b/CORE/SME/inc/pmcApi.h
@@ -214,8 +214,11 @@
 
 } tPmcSmpsMode;
 
-
-
+typedef enum
+{
+    eWOWL_EXIT_USER,
+    eWOWL_EXIT_WAKEIND
+}tWowlExitSource;
 
 /* Configuration parameters for Idle Mode Power Save (IMPS). */
 
@@ -418,7 +421,7 @@
 #endif // WLAN_WAKEUP_EVENTS
     tpSirSmeWowlEnterParams wowlEnterParams, tANI_U8 sessionId);
 
-extern eHalStatus pmcExitWowl (tHalHandle hHal);
+extern eHalStatus pmcExitWowl (tHalHandle hHal, tWowlExitSource wowlExitSrc);
 
 
 extern eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest,
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 32433c2..e93d6cc 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -1499,7 +1499,7 @@
                                   not even completed.
             eHAL_STATUS_SUCCESS  Request accepted to exit WoWLAN mode. 
   ---------------------------------------------------------------------------*/
-extern eHalStatus sme_ExitWowl (tHalHandle hHal);
+extern eHalStatus sme_ExitWowl (tHalHandle hHal, tWowlExitSource wowlExitSrc);
 
 /* ---------------------------------------------------------------------------
 
diff --git a/CORE/SME/src/pmc/pmc.c b/CORE/SME/src/pmc/pmc.c
index 5409cb7..b8cf095 100644
--- a/CORE/SME/src/pmc/pmc.c
+++ b/CORE/SME/src/pmc/pmc.c
@@ -1814,9 +1814,6 @@
    /* Call Wowl callback routine. */
    if (pMac->pmc.enterWowlCallbackRoutine != NULL)
       pMac->pmc.enterWowlCallbackRoutine(pMac->pmc.enterWowlCallbackContext, callbackStatus);
-
-   pMac->pmc.enterWowlCallbackRoutine = NULL;
-   pMac->pmc.enterWowlCallbackContext = NULL;
 }
 
 
diff --git a/CORE/SME/src/pmc/pmcApi.c b/CORE/SME/src/pmc/pmcApi.c
index 367945e..d49ccef 100644
--- a/CORE/SME/src/pmc/pmcApi.c
+++ b/CORE/SME/src/pmc/pmcApi.c
@@ -210,6 +210,7 @@
     pMac->pmc.requestFullPowerPending = FALSE;
     pMac->pmc.uapsdSessionRequired = FALSE;
     pMac->pmc.wowlModeRequired = FALSE;
+    pMac->pmc.wowlExitSrc = eWOWL_EXIT_USER;
     pMac->pmc.bmpsRequestedByHdd = FALSE;
     pMac->pmc.remainInPowerActiveTillDHCP = FALSE;
     pMac->pmc.remainInPowerActiveThreshold = 0;
@@ -1760,7 +1761,16 @@
    status = pmcEnterBmpsCheck( pMac );
    if(HAL_STATUS_SUCCESS( status ))
    {
+      /* If DUT exits from WoWL because of wake-up indication then it enters
+       * into WoWL again. Disable WoWL only when user explicitly disables.
+       */
+      if(pMac->pmc.wowlModeRequired == FALSE && pMac->pmc.wowlExitSrc == eWOWL_EXIT_WAKEIND)
+      {
+          pMac->pmc.wowlModeRequired = TRUE;
+      }
+
       status = pmcEnterRequestBmpsState(hHal);
+
       /* Enter Request BMPS State. */
       if ( HAL_STATUS_SUCCESS( status ) )
       {
@@ -2472,6 +2482,11 @@
 
    pMac->pmc.wowlModeRequired = TRUE;
 
+   /* By default set wowlExitSrc to eWOWL_EXIT_WAKEIND, so that device will
+    * come out of WoWL only when user explicity disables WoWL.
+    */
+   pMac->pmc.wowlExitSrc = eWOWL_EXIT_WAKEIND;
+
    return eHAL_STATUS_PMC_PENDING;
 }
 
@@ -2481,11 +2496,13 @@
             SME will initiate exit from WoWLAN mode and device will be put in BMPS 
             mode.
     \param  hHal - The handle returned by macOpen.
+            wowlExitSrc - is wowl exiting because of wakeup pkt or user
+                          explicitly disabling WoWL
     \return eHalStatus
             eHAL_STATUS_FAILURE  Device cannot exit WoWLAN mode.
             eHAL_STATUS_SUCCESS  Request accepted to exit WoWLAN mode. 
   ---------------------------------------------------------------------------*/
-eHalStatus pmcExitWowl (tHalHandle hHal)
+eHalStatus pmcExitWowl (tHalHandle hHal, tWowlExitSource wowlExitSrc)
 {
    tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
 
@@ -2503,13 +2520,24 @@
    /* Clear any buffered command for entering WOWL */
    pMac->pmc.wowlModeRequired = FALSE;
 
+   /* are we exiting from WoW because of wake indication
+      or user disabling this feature */
+   pMac->pmc.wowlExitSrc = wowlExitSrc;
+
    /* Enter REQUEST_EXIT_WOWL State*/
    if (pmcRequestExitWowlState(hHal) != eHAL_STATUS_SUCCESS)
       return eHAL_STATUS_FAILURE;
 
-   /* Clear the callback routines */
-   pMac->pmc.enterWowlCallbackRoutine = NULL;
-   pMac->pmc.enterWowlCallbackContext = NULL;
+   if (eWOWL_EXIT_USER == wowlExitSrc)
+   {
+       /* Clear the callback routines */
+       pMac->pmc.enterWowlCallbackRoutine = NULL;
+       pMac->pmc.enterWowlCallbackContext = NULL;
+#ifdef WLAN_WAKEUP_EVENTS
+       pMac->pmc.wakeReasonIndCB = NULL;
+       pMac->pmc.wakeReasonIndCBContext = NULL;
+#endif
+   }
 
    return eHAL_STATUS_SUCCESS;
 }
diff --git a/CORE/SME/src/pmc/pmcLogDump.c b/CORE/SME/src/pmc/pmcLogDump.c
index 6bd7ad8..ea3043e 100644
--- a/CORE/SME/src/pmc/pmcLogDump.c
+++ b/CORE/SME/src/pmc/pmcLogDump.c
@@ -275,7 +275,7 @@
 dump_pmc_exit_wowl( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
 {
     (void) arg1; (void) arg2; (void) arg3; (void) arg4;
-    (void)sme_ExitWowl(pMac);
+    (void)sme_ExitWowl(pMac, eWOWL_EXIT_USER);
     return p;
 }
 
@@ -369,7 +369,7 @@
     pmcMessageProcessor(pMac, &smeRsp);
 
     //Exit Wowl
-    sme_ExitWowl(pMac);
+    sme_ExitWowl(pMac, eWOWL_EXIT_USER);
     smeRsp.messageType = eWNI_PMC_EXIT_WOWL_RSP;
     pmcMessageProcessor(pMac, &smeRsp);
     return p;
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 3e5ff6c..8ef7293 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -4484,7 +4484,7 @@
             eHAL_STATUS_FAILURE  Device cannot exit WoWLAN mode.
             eHAL_STATUS_SUCCESS  Request accepted to exit WoWLAN mode.
   ---------------------------------------------------------------------------*/
-eHalStatus sme_ExitWowl (tHalHandle hHal)
+eHalStatus sme_ExitWowl (tHalHandle hHal, tWowlExitSource wowlExitSrc)
 {
     eHalStatus status = eHAL_STATUS_FAILURE;
     tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
@@ -4493,7 +4493,7 @@
     status = sme_AcquireGlobalLock( &pMac->sme );
     if ( HAL_STATUS_SUCCESS( status ) )
     {
-       status = pmcExitWowl (hHal);
+       status = pmcExitWowl (hHal, wowlExitSrc);
        sme_ReleaseGlobalLock( &pMac->sme );
     }
 
@@ -8244,9 +8244,6 @@
       if (pMac->pmc.wakeReasonIndCB != NULL)
           pMac->pmc.wakeReasonIndCB(pMac->pmc.wakeReasonIndCBContext, pWakeReasonInd);
 
-      pMac->pmc.wakeReasonIndCB = NULL;
-      pMac->pmc.wakeReasonIndCBContext = NULL;
-
       smsLog(pMac, LOG1, "Wake Reason Indication in %s(), reason=%d", __func__, pWakeReasonInd->ulReason);
    }