Fix for teardown of link on wrong session in Activmode offload context

In Active mode offload context when both P2P and STA links are present,
the heartbeatfailure on one session results in link loss on the other
session.handle missed beacon indication using the bssIdx passed by
firmware

Change-Id: Ie3208b18dc35685cae6499eba081195d7d4d4fea
CRs-fixed: 457247,454235
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index a9b1600..79fdbd6 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -1682,6 +1682,12 @@
     tSirMicFailureInfo     info;
 } tSirSmeMicFailureInd, *tpSirSmeMicFailureInd;
 
+typedef struct sSirSmeMissedBeaconInd
+{
+    tANI_U16                    messageType; // eWNI_SME_MISSED_BEACON_IND
+    tANI_U16                    length;
+    tANI_U8                     bssIdx;
+} tSirSmeMissedBeaconInd, *tpSirSmeMissedBeaconInd;
 
 /// Definition for Set Context request
 /// ---> MAC
diff --git a/CORE/MAC/src/pe/include/limApi.h b/CORE/MAC/src/pe/include/limApi.h
index 3848992..b3c7ab4 100644
--- a/CORE/MAC/src/pe/include/limApi.h
+++ b/CORE/MAC/src/pe/include/limApi.h
@@ -204,7 +204,7 @@
 
 void limHandleLowRssiInd(tpAniSirGlobal pMac);
 void limHandleBmpsStatusInd(tpAniSirGlobal pMac);
-void limHandleMissedBeaconInd(tpAniSirGlobal pMac);
+void limHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
 tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U32 subType);
 void limMicFailureInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
 /* ----------------------------------------------------------------------- */
diff --git a/CORE/MAC/src/pe/include/limSession.h b/CORE/MAC/src/pe/include/limSession.h
index 95f0624..d07c0cb 100644
--- a/CORE/MAC/src/pe/include/limSession.h
+++ b/CORE/MAC/src/pe/include/limSession.h
@@ -400,6 +400,21 @@
 
 
 /*--------------------------------------------------------------------------
+  \brief peFindSessionByBssIdx() - looks up the PE session given the bssIdx.
+
+  This function returns the session context  if the session
+  corresponding to the given bssIdx is found in the PE session table.
+   \param pMac                   - pointer to global adapter context
+  \param bssIdx                   - bss index of the session
+  \return tpPESession          - pointer to the session context or NULL if session is not found.
+  \sa
+  --------------------------------------------------------------------------*/
+tpPESession peFindSessionByBssIdx(tpAniSirGlobal pMac,  tANI_U8 bssIdx);
+
+
+
+
+/*--------------------------------------------------------------------------
   \brief peFindSessionByPeerSta() - looks up the PE session given the Peer Station Address.
 
   This function returns the session context and the session ID if the session 
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index 5fc6bc2..5007828 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -1973,8 +1973,20 @@
   \return - none 
   \sa
   ----------------------------------------------------------------- */
-void limHandleMissedBeaconInd(tpAniSirGlobal pMac)
+void limHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
 {
+#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
+    tpSirSmeMissedBeaconInd  pSirMissedBeaconInd =
+                           (tpSirSmeMissedBeaconInd)pMsg->bodyptr;
+    tpPESession psessionEntry = peFindSessionByBssIdx(pMac,pSirMissedBeaconInd->bssIdx);
+    if (psessionEntry == NULL)
+    {
+         limLog(pMac, LOGE,
+               FL("session does not exist for given BSSIdx:%d"),
+               pSirMissedBeaconInd->bssIdx);
+         return;
+    }
+#endif
     if ( (pMac->pmm.gPmmState == ePMM_STATE_BMPS_SLEEP) ||
          (pMac->pmm.gPmmState == ePMM_STATE_UAPSD_SLEEP)||
          (pMac->pmm.gPmmState == ePMM_STATE_WOWLAN) )
@@ -1991,7 +2003,7 @@
     {
         pMac->pmm.inMissedBeaconScenario = TRUE;
         PELOGE(limLog(pMac, LOGE, FL("Received Heart Beat Failure\n"));)
-        limMissedBeaconInActiveMode(pMac);
+        limMissedBeaconInActiveMode(pMac, psessionEntry);
     }
 #endif
     else
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 44aa2e4..80e23ef 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -1553,7 +1553,9 @@
             break;
 
         case WDA_MISSED_BEACON_IND:
-            limHandleMissedBeaconInd(pMac);
+            limHandleMissedBeaconInd(pMac, limMsg);
+            palFreeMemory(pMac->hHdd, (tANI_U8 *)limMsg->bodyptr);
+            limMsg->bodyptr = NULL;
             break;
         case WDA_MIC_FAILURE_IND:
            limMicFailureInd(pMac, limMsg);
@@ -1664,10 +1666,17 @@
             }
             else
             {
-                 limHandleHeartBeatTimeout(pMac);
+                 if (NULL == limMsg->bodyptr)
+                 {
+                     limHandleHeartBeatTimeout(pMac);
+                 }
+                 else
+                 {
+                     limHandleHeartBeatTimeoutForSession(pMac, (tpPESession)limMsg->bodyptr);
+                 }
             }            
             break;
-           
+
         case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT:
             limHandleHeartBeatFailureTimeout(pMac);            
             break;
diff --git a/CORE/MAC/src/pe/lim/limSession.c b/CORE/MAC/src/pe/lim/limSession.c
index 9bfe281..35015f2 100644
--- a/CORE/MAC/src/pe/lim/limSession.c
+++ b/CORE/MAC/src/pe/lim/limSession.c
@@ -237,6 +237,30 @@
 }
 
 
+/*--------------------------------------------------------------------------
+  \brief peFindSessionByBssIdx() - looks up the PE session given the bssIdx.
+
+  This function returns the session context  if the session
+  corresponding to the given bssIdx is found in the PE session table.
+  \param pMac                   - pointer to global adapter context
+  \param bssIdx                   - bss index of the session
+  \return tpPESession          - pointer to the session context or NULL if session is not found.
+  \sa
+  --------------------------------------------------------------------------*/
+tpPESession peFindSessionByBssIdx(tpAniSirGlobal pMac,  tANI_U8 bssIdx)
+{
+    tANI_U8 i;
+    for (i = 0; i < pMac->lim.maxBssId; i++)
+    {
+        /* If BSSID matches return corresponding tables address*/
+        if ( (pMac->lim.gpSession[i].valid) && (pMac->lim.gpSession[i].bssIdx == bssIdx))
+        {
+            return &pMac->lim.gpSession[i];
+        }
+    }
+    limLog(pMac, LOG4, FL("Session lookup fails for bssIdx: %d"), bssIdx);
+    return NULL;
+}
 
 /*--------------------------------------------------------------------------
   \brief peFindSessionBySessionId() - looks up the PE session given the session ID.
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index c64fdab..eb582c1 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -2346,7 +2346,7 @@
  * @return None
  */
 void
-limMissedBeaconInActiveMode(void *pMacGlobal)
+limMissedBeaconInActiveMode(void *pMacGlobal, tpPESession psessionEntry)
 {
     tANI_U32         statusCode;
     tSirMsgQ    msg;
@@ -2356,7 +2356,7 @@
     if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)
     {
        msg.type = (tANI_U16) SIR_LIM_HEART_BEAT_TIMEOUT;
-       msg.bodyptr = NULL;
+       msg.bodyptr = psessionEntry;
        msg.bodyval = 0;
        limLog(pMac, LOGE,
                  FL("Heartbeat failure from Riva\n"));
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index 264c375..858bd1a 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -153,6 +153,6 @@
 void limWPSOverlapTimerHandler(void *pMacGlobal, tANI_U32 param);
 #endif
 #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
-void limMissedBeaconInActiveMode(void *pMacGlobal);
+void limMissedBeaconInActiveMode(void *pMacGlobal, tpPESession psessionEntry);
 #endif
 #endif /* __LIM_TIMER_UTILS_H */
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 5e4d8cb..32e4103 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -6965,6 +6965,45 @@
     }
 }
 
+void limHandleHeartBeatTimeoutForSession(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+    if(psessionEntry->valid == TRUE )
+    {
+        if(psessionEntry->bssType == eSIR_IBSS_MODE)
+        {
+            limIbssHeartBeatHandle(pMac,psessionEntry);
+        }
+        if((psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
+             (psessionEntry->limSystemRole == eLIM_STA_ROLE))
+        {
+            limHandleHeartBeatFailure(pMac,psessionEntry);
+        }
+    }
+    /* In the function limHandleHeartBeatFailure things can change so check for the session entry  valid
+     and the other things again */
+    if(psessionEntry->valid == TRUE )
+    {
+        if((psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
+            (psessionEntry->limSystemRole == eLIM_STA_ROLE))
+        {
+            if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE)
+            {
+                /* Activate Probe After HeartBeat Timer incase HB Failure detected */
+                PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"),
+                       psessionEntry->bssIdx);)
+                limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER);
+                MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER));
+                if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS)
+                {
+                    limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer"));
+                    limReactivateHeartBeatTimer(pMac, psessionEntry);
+                }
+            }
+        }
+    }
+}
+
+
 tANI_U8 limGetCurrentOperatingChannel(tpAniSirGlobal pMac)
 {
     tANI_U8 i;
diff --git a/CORE/MAC/src/pe/lim/limUtils.h b/CORE/MAC/src/pe/lim/limUtils.h
index cb4b220..df564ab 100644
--- a/CORE/MAC/src/pe/lim/limUtils.h
+++ b/CORE/MAC/src/pe/lim/limUtils.h
@@ -358,6 +358,8 @@
 tSirNwType limGetNwType(tpAniSirGlobal pMac, tANI_U8 channelNum, tANI_U32 type, tpSchBeaconStruct pBeacon);
 void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 action);
 void limHandleHeartBeatTimeout(tpAniSirGlobal pMac);
+void limHandleHeartBeatTimeoutForSession(tpAniSirGlobal pMac, tpPESession psessionEntry);
+
 //void limProcessBtampAddBssRsp(tpAniSirGlobal pMac,tpSirMsgQ pMsgQ,tpPESession peSession);
 void limProcessAddStaRsp(tpAniSirGlobal pMac,tpSirMsgQ pMsgQ);