wlan: IBSS HeartBeat offload.

HeartBeat implementation has been offloaded for most of the device
modes except Ad-Hoc. The HB offload is a requirement not to wakeup
the host processor for connectivity actions.

CRs-Fixed: 517100
Change-Id: If41fd2dd86d5941231e999c5a4b9d3b99602c110
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index ac5412f..04b1a01 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1801,6 +1801,14 @@
 #define CFG_FLEX_CONNECT_POWER_FACTOR_MAX           ( 9 )
 #define CFG_FLEX_CONNECT_POWER_FACTOR_DEFAULT       ( 0 )
 
+/*
+ * Enable heart beat monitoring offload to FW
+ */
+#define CFG_ENABLE_HEART_BEAT_OFFLOAD          "gEnableIbssHeartBeatOffload"
+#define CFG_ENABLE_HEART_BEAT_OFFLOAD_MIN      ( 0 )
+#define CFG_ENABLE_HEART_BEAT_OFFLOAD_MAX      ( 1 )
+#define CFG_ENABLE_HEART_BEAT_OFFLOAD_DEFAULT  ( 1 )
+
 /*--------------------------------------------------------------------------- 
   Type declarations
   -------------------------------------------------------------------------*/ 
@@ -2183,6 +2191,7 @@
    v_BOOL_t                    fEnableAdaptRxDrain;
    v_BOOL_t                    enableOxygenNwk;
    v_U8_t                      flexConnectPowerFactor;
+   v_BOOL_t                    enableIbssHeartBeatOffload;
 } 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 8ecd2cc..4f16c84 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -2357,6 +2357,13 @@
                  CFG_FLEX_CONNECT_POWER_FACTOR_MIN,
                  CFG_FLEX_CONNECT_POWER_FACTOR_MAX ),
 
+   REG_VARIABLE( CFG_ENABLE_HEART_BEAT_OFFLOAD, WLAN_PARAM_Integer,
+                 hdd_config_t, enableIbssHeartBeatOffload,
+                 VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+                 CFG_ENABLE_HEART_BEAT_OFFLOAD_DEFAULT,
+                 CFG_ENABLE_HEART_BEAT_OFFLOAD_MIN,
+                 CFG_ENABLE_HEART_BEAT_OFFLOAD_MAX),
+
 };
 
 /*
@@ -2739,6 +2746,7 @@
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableTrafficMonitor] Value = [%u] ", pHddCtx->cfg_ini->enableTrafficMonitor);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gTrafficIdleTimeout] Value = [%u] ", pHddCtx->cfg_ini->trafficIdleTimeout);
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gFlexConnectPowerFactor] Value = [%u] ", pHddCtx->cfg_ini->flexConnectPowerFactor);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableIbssHeartBeatOffload] Value = [%u] ", pHddCtx->cfg_ini->enableIbssHeartBeatOffload);
 }
 
 
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 7045bb2..a850e40 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -5387,6 +5387,12 @@
          if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
             sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
 #endif
+         /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
+         if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
+         {
+            sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
+         }
+
          sme_featureCapsExchange(pHddCtx->hHal);
       }
 
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 4aa2b39..972bd31 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -2719,6 +2719,14 @@
     //Beacon will be appended for new Peer indication.
 }tSmeIbssPeerInd, *tpSmeIbssPeerInd;
 
+typedef struct sSirIbssPeerInactivityInd
+{
+   tANI_U8       bssIdx;
+   tANI_U8       staIdx;
+   tSirMacAddr   peerAddr;
+}tSirIbssPeerInactivityInd, *tpSirIbssPeerInactivityInd;
+
+
 typedef struct sLimScanChn
 {
     tANI_U16 numTimeScan;   //how many time this channel is scan
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 964c756..e072f5d 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -97,6 +97,7 @@
 #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
    WLAN_ROAM_SCAN_OFFLOAD = 23,
 #endif
+   IBSS_HEARTBEAT_OFFLOAD = 26
    //MAX_FEATURE_SUPPORTED = 128
 } placeHolderInCapBitmap;
 
@@ -585,6 +586,7 @@
 #define SIR_HAL_RX_SCAN_EVENT              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 203)
 #define SIR_HAL_DHCP_START_IND             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 204)
 #define SIR_HAL_DHCP_STOP_IND              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 205)
+#define SIR_HAL_IBSS_PEER_INACTIVITY_IND   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 206)
 
 #define SIR_HAL_LPHB_CONF_IND              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 206)
 #define SIR_HAL_LPHB_WAIT_EXPIRE_IND       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 207)
diff --git a/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c b/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c
index 56ce4f5..6231f22 100644
--- a/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c
+++ b/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c
@@ -1515,7 +1515,7 @@
         limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_IBSS_ACTIVE, NULL, 0, psessionEntry->smeSessionId);
         limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry);
         MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
-        if (limActivateHearBeatTimer(pMac) != TX_SUCCESS)
+        if (limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS)
             limLog(pMac, LOGP, FL("could not activate Heartbeat timer"));
     }
 
@@ -1700,3 +1700,136 @@
         }
     }
 }
+
+/** -----------------------------------------------------------------
+\fn __limIbssPeerInactivityHandler
+\brief Internal function. Deletes FW indicated peer which is inactive
+\
+\param  tpAniSirGlobal    pMac
+\param  tpPESession       psessionEntry
+\param  tpSirIbssPeerInactivityInd peerInactivityInd
+\return None
+  -----------------------------------------------------------------*/
+static void
+__limIbssPeerInactivityHandler(tpAniSirGlobal    pMac,
+                               tpPESession psessionEntry,
+                               tpSirIbssPeerInactivityInd peerInactivityInd)
+{
+   tLimIbssPeerNode *pTempNode, *pPrevNode;
+   tLimIbssPeerNode *pTempNextNode = NULL;
+   tpDphHashNode     pStaDs;
+   tANI_U16          peerIdx;
+   tANI_U16          staIndex;
+   tANI_U8           ucUcastSig;
+   tANI_U8           ucBcastSig;
+
+   if(psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE)
+   {
+      limReactivateHeartBeatTimer(pMac, psessionEntry);
+      return;
+   }
+
+   pPrevNode = pTempNode  = pMac->lim.gLimIbssPeerList;
+
+   /** Monitor the HeartBeat with the Individual PEERS in the IBSS */
+   while (NULL != pTempNode)
+   {
+      pTempNextNode = pTempNode->next;
+      PELOGE(limLog(pMac, LOGE, FL("Heartbeat fail = %d  thres = %d"),
+               pTempNode->heartbeatFailure, pMac->lim.gLimNumIbssPeers);)
+
+      /* this is the main control loop */
+      if (palEqualMemory( pMac->hHdd, (tANI_U8 *) peerInactivityInd->peerAddr,
+                          (tANI_U8 *) &pTempNode->peerMacAddr,
+                          sizeof(tSirMacAddr)) )
+      {
+         //Remove this entry from the list.
+         pStaDs = dphLookupHashEntry(pMac, peerInactivityInd->peerAddr,
+               &peerIdx, &psessionEntry->dph.dphHashTable);
+         if (pStaDs)
+         {
+            staIndex = pStaDs->staIndex;
+            ucUcastSig = pStaDs->ucUcastSig;
+            ucBcastSig = pStaDs->ucBcastSig;
+
+            (void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry);
+            limDeleteDphHashEntry(pMac, pStaDs->staAddr, peerIdx, psessionEntry);
+            limReleasePeerIdx(pMac, peerIdx, psessionEntry);
+
+            // Send indication to upper layers
+            ibss_status_chg_notify(pMac, peerInactivityInd->peerAddr, staIndex,
+                                   ucUcastSig, ucBcastSig,
+                                   eWNI_SME_IBSS_PEER_DEPARTED_IND,
+                                   psessionEntry->smeSessionId );
+            if (pTempNode == pMac->lim.gLimIbssPeerList)
+            {
+               pMac->lim.gLimIbssPeerList = pTempNode->next;
+               pPrevNode = pMac->lim.gLimIbssPeerList;
+            }
+            else
+               pPrevNode->next = pTempNode->next;
+
+            palFreeMemory(pMac->hHdd, pTempNode);
+            pMac->lim.gLimNumIbssPeers--;
+
+            pTempNode = pTempNextNode;
+            break;
+         }
+      }
+      pPrevNode = pTempNode;
+      pTempNode = pTempNextNode;
+   }
+}
+
+
+/** -------------------------------------------------------------
+\fn limProcessIbssPeerInactivity
+\brief Peer inactivity message handler
+\
+\param  tpAniSirGlobal    pMac
+\param  void*             buf
+\return None
+  -------------------------------------------------------------*/
+void
+limProcessIbssPeerInactivity(tpAniSirGlobal pMac, void *buf)
+{
+   /*
+    * --------------- HEARTBEAT OFFLOAD CASE ------------------
+    * This message handler is executed when the firmware identifies
+    * inactivity from one or more peer devices. We will come here
+    * for every inactive peer device
+    */
+   tANI_U8       i;
+
+   tSirIbssPeerInactivityInd *peerInactivityInd =
+      (tSirIbssPeerInactivityInd *) buf;
+
+   /*
+    * If IBSS is not started or heartbeat offload is not enabled
+    * we should not handle this request
+    */
+   if (eLIM_STA_IN_IBSS_ROLE != pMac->lim.gLimSystemRole &&
+         !IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE)
+   {
+      return;
+   }
+
+   /** If LinkMonitor is Disabled */
+   if (!pMac->sys.gSysEnableLinkMonitorMode)
+   {
+      return;
+   }
+
+   for (i = 0; i < pMac->lim.maxBssId; i++)
+   {
+      if (VOS_TRUE == pMac->lim.gpSession[i].valid &&
+            eSIR_IBSS_MODE == pMac->lim.gpSession[i].bssType)
+      {
+         __limIbssPeerInactivityHandler(pMac,
+               &pMac->lim.gpSession[i],
+               peerInactivityInd);
+         break;
+      }
+   }
+}
+
diff --git a/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h b/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h
index f677932..bed0be1 100644
--- a/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h
+++ b/CORE/MAC/src/pe/lim/limIbssPeerMgmt.h
@@ -64,4 +64,4 @@
 void limIbssAddBssRspWhenCoalescing(tpAniSirGlobal  pMac, void * msg, tpPESession pSessionEntry);
 void limIbssDecideProtectionOnDelete(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpUpdateBeaconParams pBeaconParams,tpPESession pSessionEntry);
 void limIbssHeartBeatHandle(tpAniSirGlobal pMac,tpPESession psessionEntry);
-
+void limProcessIbssPeerInactivity(tpAniSirGlobal pMac, void *buf);
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 3d1f7fe..14423d6 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1947,6 +1947,14 @@
         limProcessRxScanEvent(pMac, limMsg->bodyptr);
         break;
 
+    case WDA_IBSS_PEER_INACTIVITY_IND:
+    {
+       limProcessIbssPeerInactivity(pMac, limMsg->bodyptr);
+       vos_mem_free((v_VOID_t *)(limMsg->bodyptr));
+       limMsg->bodyptr = NULL;
+       break;
+    }
+
     default:
         vos_mem_free((v_VOID_t*)limMsg->bodyptr);
         limMsg->bodyptr = NULL;
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
index f6f18a5..1e5b69b 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
@@ -2434,7 +2434,7 @@
             limResetHBPktCount( psessionEntry );
             limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry);
             MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
-            if (limActivateHearBeatTimer(pMac) != TX_SUCCESS)
+            if (limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS)
                 limLog(pMac, LOGP, FL("could not activate Heartbeat timer"));
         }
         psessionEntry->bssIdx     = (tANI_U8) pAddBssParams->bssIdx;
@@ -2542,7 +2542,7 @@
         /* Timer related functions are not modified for BT-AMP : To be Done */
         limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry);
         MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
-        if (limActivateHearBeatTimer(pMac) != TX_SUCCESS)
+        if (limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS)
             limLog(pMac, LOGP, FL("could not activate Heartbeat timer"));
         psessionEntry->bssIdx     = (tANI_U8) pAddBssParams->bssIdx;
         psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE;
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index db8e9b7..9b7e5e9 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -1893,13 +1893,38 @@
     MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
 
     //only start the hearbeat-timer if the timeout value is non-zero
-    if(pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs > 0) {
-        if (tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS)
-        {
-            limLog(pMac, LOGP,FL("could not activate Heartbeat timer"));
-        }
-        limLog(pMac, LOGW, FL("Reactivated heartbeat link monitoring"));
-        limResetHBPktCount(psessionEntry);
+    if(pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs > 0)
+    {
+       /*
+        * There is increasing need to limit the apps wakeup due to WLAN
+        * activity. During HB monitoring, the beacons from peer are sent to
+        * the host causing the host to wakeup. Hence, offloading the HB
+        * monitoring to LMAC
+        */
+       if (psessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE &&
+             IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE)
+       {
+          if (tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS)
+          {
+             limLog(pMac, LOGP,FL("IBSS HeartBeat Offloaded, Could not deactivate Heartbeat timer"));
+          }
+          else
+          {
+             limLog(pMac, LOGE, FL("IBSS HeartBeat Offloaded, Deactivated heartbeat link monitoring"));
+          }
+       }
+       else
+       {
+          if (tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS)
+          {
+             limLog(pMac, LOGP,FL("could not activate Heartbeat timer"));
+          }
+          else
+          {
+             limLog(pMac, LOGW, FL("Reactivated heartbeat link monitoring"));
+          }
+       }
+       limResetHBPktCount(psessionEntry);
     }
 
 } /****** end limReactivateHeartBeatTimer() ******/
@@ -1919,11 +1944,12 @@
  * @note   staId for eLIM_AUTH_RSP_TIMER is auth Node Index.
  *
  * @param  pMac    - Pointer to Global MAC structure
+ * @param  psessionEntry - Session Entry
  *
  * @return TX_SUCCESS - timer is activated
  *         errors - fail to start the timer
  */
-v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac)
+v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry)
 {
     v_UINT_t status = TX_TIMER_ERROR;
 
@@ -1937,12 +1963,39 @@
         //consider 0 interval a ok case
         if( pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs )
         {
-            status = tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer);
-            if( TX_SUCCESS != status )
-            {
-                PELOGE(limLog(pMac, LOGE,
-                   FL("could not activate Heartbeat timer status(%d)"), status);)
-            }
+           if (psessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE &&
+               IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE)
+           {
+              /* HB offload in IBSS mode */
+              status = tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer);
+              if (TX_SUCCESS != status)
+              {
+                 PELOGE(limLog(pMac, LOGE,
+                 FL("IBSS HB Offload, Could not deactivate HB timer status(%d)"),
+                 status);)
+              }
+              else
+              {
+                 PELOGE(limLog(pMac, LOGE,
+                 FL("%s] IBSS HB Offloaded, Heartbeat timer deactivated"),
+                 __func__);)
+              }
+
+           }
+           else
+           {
+              status = tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer);
+              if ( TX_SUCCESS != status )
+              {
+                 PELOGE(limLog(pMac, LOGE,
+                 FL("could not activate Heartbeat timer status(%d)"), status);)
+              }
+              else
+              {
+                 PELOGE(limLog(pMac, LOGW,
+                 FL("%s] Activated Heartbeat timer status(%d)"), __func__, status);)
+              }
+           }
         }
         else
         {
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index 0715227..7244064 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -142,11 +142,12 @@
  * @note   staId for eLIM_AUTH_RSP_TIMER is auth Node Index.
  *
  * @param  pMac    - Pointer to Global MAC structure
+ * @param  psessionEntry - Pointer to PE session entry
  *
  * @return TX_SUCCESS - timer is activated
  *         errors - fail to start the timer
  */
-v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac);
+v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry);
 
 #if 0
 void limWPSOverlapTimerHandler(void *pMacGlobal, tANI_U32 param);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 693dba4..37f1abb 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -6710,7 +6710,8 @@
 
         if (val > 0 && TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer))
         {
-            MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_BACKGROUND_SCAN_TIMER));
+            MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE,
+                     psessionEntry->peSessionId, eLIM_BACKGROUND_SCAN_TIMER));
             if(tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS)
             {
                 limLog(pMac, LOGP, FL("Could not restart background scan timer, doing LOGP"));
@@ -6723,8 +6724,10 @@
     /* Enable heartbeat timer */
     if (TX_TIMER_VALID(pMac->lim.limTimers.gLimHeartBeatTimer))
     {
-        MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
-        if((limActivateHearBeatTimer(pMac) != TX_SUCCESS) && (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
+        MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE,
+                 psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
+        if((limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) &&
+              (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
         {
             limLog(pMac, LOGP, FL("Could not restart heartbeat timer, doing LOGP"));
             return (eSIR_FAILURE);
@@ -6786,7 +6789,7 @@
     if (TX_TIMER_VALID(pMac->lim.limTimers.gLimHeartBeatTimer))
     {
         MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
-        if(limActivateHearBeatTimer(pMac) != TX_SUCCESS)
+        if(limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS)
         {
             limLog(pMac, LOGP, FL("Could not restart heartbeat timer, doing LOGP"));
             return (eSIR_FAILURE);
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index b2844e3..1eb601f 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -655,6 +655,10 @@
     tANI_U8   txLdpcEnable;
     tANI_BOOLEAN  enableOxygenNwk;
 
+    /*
+     * Enable/Disable heartbeat offload
+     */
+    tANI_BOOLEAN enableHeartBeatOffload;
 }tCsrConfig;
 
 typedef struct tagCsrChannelPowerInfo
diff --git a/CORE/WDA/inc/legacy/halMsgApi.h b/CORE/WDA/inc/legacy/halMsgApi.h
index 28c938c..f613021 100644
--- a/CORE/WDA/inc/legacy/halMsgApi.h
+++ b/CORE/WDA/inc/legacy/halMsgApi.h
@@ -1213,6 +1213,15 @@
 } tBaActivityInd, * tpBaActivityInd;
 
 
+// Mesg Type = SIR_LIM_IBSS_PEER_INACTIVITY_IND
+typedef struct sIbssPeerInactivityInd
+{
+   tANI_U8     bssIdx;
+   tANI_U8     staIdx;
+   tSirMacAddr staAddr;
+}tIbssPeerInactivityInd, *tpIbssPeerInactivityInd;
+
+
 typedef struct tHalIndCB
 {
 
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 5a94f6b..44fa9e9 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -167,6 +167,9 @@
 #define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 0
 #endif
 
+/* Check if heartbeat offload is enabled */
+#define IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE ((WDI_getHostWlanFeatCaps(IBSS_HEARTBEAT_OFFLOAD)) & (WDA_getFwWlanFeatCaps(IBSS_HEARTBEAT_OFFLOAD)))
+
 /*--------------------------------------------------------------------------
   Definitions for Data path APIs
  --------------------------------------------------------------------------*/
@@ -1084,6 +1087,7 @@
 #define WDA_UPDATE_CHAN_LIST_REQ    SIR_HAL_UPDATE_CHAN_LIST_REQ
 #define WDA_UPDATE_CHAN_LIST_RSP    SIR_HAL_UPDATE_CHAN_LIST_RSP
 #define WDA_RX_SCAN_EVENT           SIR_HAL_RX_SCAN_EVENT
+#define WDA_IBSS_PEER_INACTIVITY_IND SIR_HAL_IBSS_PEER_INACTIVITY_IND
 
 #ifdef FEATURE_WLAN_LPHB
 #define WDA_LPHB_CONF_REQ          SIR_HAL_LPHB_CONF_IND
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 81c14e6..5c7b655 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -11818,6 +11818,31 @@
       }
 #endif /* FEATURE_WLAN_LPHB */
 
+      case WDI_IBSS_PEER_INACTIVITY_IND:
+      {
+         tSirIbssPeerInactivityInd  *pIbssInd =
+            (tSirIbssPeerInactivityInd *)
+            vos_mem_malloc(sizeof(tSirIbssPeerInactivityInd));
+
+         if (NULL == pIbssInd)
+         {
+            VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "Memory allocation failure, "
+                  "WDI_IBSS_PEER_INACTIVITY_IND not forwarded");
+            break;
+         }
+
+         pIbssInd->bssIdx =
+            wdiLowLevelInd->wdiIndicationData.wdiIbssPeerInactivityInd.bssIdx;
+         pIbssInd->staIdx =
+            wdiLowLevelInd->wdiIndicationData.wdiIbssPeerInactivityInd.staIdx;
+         vos_mem_copy(pIbssInd->peerAddr,
+               wdiLowLevelInd->wdiIndicationData.wdiIbssPeerInactivityInd.staMacAddr,
+               sizeof(tSirMacAddr));
+         WDA_SendMsg(pWDA, WDA_IBSS_PEER_INACTIVITY_IND, (void *)pIbssInd, 0) ;
+         break;
+      }
+
       default:
       {
          /* TODO error */
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 0c565e6..659875f 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -396,6 +396,9 @@
   /* LPHB Timeout Indication from FW to umac */
   WDI_LPHB_WAIT_TIMEOUT_IND,
 
+  /* IBSS Peer Inactivity Indication */
+  WDI_IBSS_PEER_INACTIVITY_IND,
+
   WDI_MAX_IND
 }WDI_LowLevelIndEnumType;
 
@@ -618,6 +621,16 @@
 #endif /* FEATURE_WLAN_LPHB */
 
 /*---------------------------------------------------------------------------
+ WDI_IbssPeerInactivityIndType
+-----------------------------------------------------------------------------*/
+typedef struct
+{
+   wpt_uint8   bssIdx;
+   wpt_uint8   staIdx;
+   wpt_macAddr staMacAddr;
+}WDI_IbssPeerInactivityIndType;
+
+/*---------------------------------------------------------------------------
   WDI_LowLevelIndType
     Inidcation type and information about the indication being carried
     over
@@ -666,9 +679,14 @@
     WDI_WakeReasonIndType        wdiWakeReasonInd;
 #endif // WLAN_WAKEUP_EVENTS
     WDI_MissedBeaconIndType      wdiMissedBeaconInd;
+
 #ifdef FEATURE_WLAN_LPHB
     WDI_LPHBTimeoutIndData       wdiLPHBTimeoutInd;
 #endif /* FEATURE_WLAN_LPHB */
+
+    /* IBSS Peer Inactivity Indication */
+    WDI_IbssPeerInactivityIndType   wdiIbssPeerInactivityInd;
+
   }  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 026f01a..32de8f3 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -782,6 +782,10 @@
 
   /* LPHB timeout indication */
   WDI_HAL_LPHB_WAIT_TIMEOUT_IND        = WDI_HAL_IND_MIN + 14,
+
+  /* IBSS Peer Inactivity Indication from FW to Host */
+  WDI_HAL_IBSS_PEER_INACTIVITY_IND     = WDI_HAL_IND_MIN + 15,
+
   WDI_MAX_RESP
 }WDI_ResponseEnumType; 
 
@@ -4371,6 +4375,26 @@
   WDI_ControlBlockType*  pWDICtx,
   WDI_EventInfoType*     pEventData
 );
+
+/**
+ @brief WDI_ProcessIbssPeerInactivityInd
+        Process peer inactivity indication coming from HAL.
+
+  @param  pWDICtx:         pointer to the WLAN DAL context
+          pEventData:      pointer to the event information structure
+
+  @see
+  @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessIbssPeerInactivityInd
+
+(
+ WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
+
 /*========================================================================
          Internal Helper Routines 
 ========================================================================*/
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index e2afdec..6814ae5 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -128,26 +128,43 @@
 static placeHolderInCapBitmap supportEnabledFeatures[] =
    {MCC, P2P, DOT11AC, SLM_SESSIONIZATION, DOT11AC_OPMODE
 #ifdef WLAN_SOFTAP_VSTA_FEATURE
-    ,SAP32STA
+    ,SAP32STA                       //5
 #else
     ,FEATURE_NOT_SUPPORTED
 #endif
 #ifdef FEATURE_WLAN_TDLS
-    ,TDLS
+    ,TDLS                           //6
 #else
     ,FEATURE_NOT_SUPPORTED
 #endif
-    ,P2P_GO_NOA_DECOUPLE_INIT_SCAN
+    ,P2P_GO_NOA_DECOUPLE_INIT_SCAN  //7
 #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
-    ,WLANACTIVE_OFFLOAD
+    ,WLANACTIVE_OFFLOAD             //8
 #else
     ,FEATURE_NOT_SUPPORTED
 #endif
+    ,FEATURE_NOT_SUPPORTED          //9
+    ,FEATURE_NOT_SUPPORTED          //10
+    ,FEATURE_NOT_SUPPORTED          //11
+    ,FEATURE_NOT_SUPPORTED          //12
+    ,FEATURE_NOT_SUPPORTED          //13
+    ,FEATURE_NOT_SUPPORTED          //14
+    ,FEATURE_NOT_SUPPORTED          //15
+    ,FEATURE_NOT_SUPPORTED          //16
+    ,FEATURE_NOT_SUPPORTED          //17
+    ,FEATURE_NOT_SUPPORTED          //18
+    ,FEATURE_NOT_SUPPORTED          //19
+    ,FEATURE_NOT_SUPPORTED          //20
+    ,FEATURE_NOT_SUPPORTED          //21
 #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
-    ,WLAN_ROAM_SCAN_OFFLOAD
+    ,WLAN_ROAM_SCAN_OFFLOAD         //22
 #else
     ,FEATURE_NOT_SUPPORTED
 #endif
+    ,FEATURE_NOT_SUPPORTED          //23
+    ,FEATURE_NOT_SUPPORTED          //24
+    ,FEATURE_NOT_SUPPORTED          //25
+    ,IBSS_HEARTBEAT_OFFLOAD         //26
    };
 
 /*-------------------------------------------------------------------------- 
@@ -606,6 +623,8 @@
 #else
   NULL,
 #endif /* FEATURE_WLAN_LPHB */
+
+  WDI_ProcessIbssPeerInactivityInd,     /* WDI_HAL_IBSS_PEER_INACTIVITY_IND */
 };
 
 
@@ -22524,12 +22543,17 @@
   case WLAN_HAL_GET_ROAM_RSSI_RSP:
     return WDI_GET_ROAM_RSSI_RESP;
 #endif
+
 #ifdef FEATURE_WLAN_LPHB
   case WLAN_HAL_LPHB_IND:
     return WDI_HAL_LPHB_WAIT_TIMEOUT_IND;
   case WLAN_HAL_LPHB_CFG_RSP:
     return WDI_LPHB_CFG_RESP;
 #endif /* FEATURE_WLAN_LPHB */
+
+  case WLAN_HAL_IBSS_PEER_INACTIVITY_IND:
+    return WDI_HAL_IBSS_PEER_INACTIVITY_IND;
+
   default:
     return eDRIVER_TYPE_MAX;
   }
@@ -27629,7 +27653,6 @@
 
  @param  pWDICtx : wdi context
          pEventData : indication data
-
  @see
  @return Result of the function call
 */
@@ -27931,3 +27954,62 @@
 }
 #endif /* FEATURE_WLAN_LPHB */
 
+/**
+  @brief WDI_ProcessIbssPeerInactivityInd
+  Process peer inactivity indication coming from HAL
+
+  @param pWDICtx: pointer to the WLAN DAL context
+         pEventData: pointer to the event information structure
+  @see
+  @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessIbssPeerInactivityInd
+(
+   WDI_ControlBlockType* pWDICtx,
+   WDI_EventInfoType* pEventData
+)
+{
+   WDI_LowLevelIndType  wdiInd;
+   tIbssPeerInactivityIndMsg halIbssIndMsg;
+
+   /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+   /*-------------------------------------------------------------------------
+   Sanity check
+   -------------------------------------------------------------------------*/
+   if (( NULL == pWDICtx ) || ( NULL == pEventData ) ||
+      ( NULL == pEventData->pEventData ))
+   {
+     WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                 "%s: Invalid parameters", __func__);
+     WDI_ASSERT( 0 );
+     return WDI_STATUS_E_FAILURE;
+   }
+
+   /*-------------------------------------------------------------------------
+   Extract indication and send it to UMAC
+   -------------------------------------------------------------------------*/
+   wpalMemoryCopy( &halIbssIndMsg.ibssPeerInactivityIndParams,
+                  pEventData->pEventData,
+                  sizeof(halIbssIndMsg.ibssPeerInactivityIndParams) );
+
+   /*Fill in the indication parameters*/
+   wdiInd.wdiIndicationType = WDI_IBSS_PEER_INACTIVITY_IND;
+
+   wdiInd.wdiIndicationData.wdiIbssPeerInactivityInd.bssIdx
+                          = halIbssIndMsg.ibssPeerInactivityIndParams.bssIdx;
+
+   wdiInd.wdiIndicationData.wdiIbssPeerInactivityInd.staIdx
+                          = halIbssIndMsg.ibssPeerInactivityIndParams.staIdx;
+
+   wpalMemoryCopy(wdiInd.wdiIndicationData.wdiIbssPeerInactivityInd.staMacAddr,
+                 halIbssIndMsg.ibssPeerInactivityIndParams.staAddr,
+                 sizeof(tSirMacAddr));
+
+   /*Notify UMAC*/
+   pWDICtx->wdiLowLevelIndCB( &wdiInd, pWDICtx->pIndUserData );
+
+   return WDI_STATUS_SUCCESS;
+
+} /*WDI_ProcessIbssPeerInactivityInd*/