wlan: check if tdls exists when tdls peer timer expires.

when wlan_hdd_tdls_initiator_wait_cb gets called, the tdls peer
might not exists as there is a chance that the peer may get deleted
as part of disconnection.

So check if tdls exists before accessing the peer in
wlan_hdd_tdls_initiator_wait_cb.

Change-Id: I90a7a765997bf3641bf2c8de2f3c9e5068e89122
CRs-Fixed: 906303
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index b928904..823e11c 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1569,6 +1569,8 @@
 void hdd_dump_concurrency_info(hdd_context_t *pHddCtx);
 hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name );
 hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx, tSirMacAddr macAddr );
+hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
+                                        tANI_U32 sme_session_id );
 hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx );
 VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter );
 hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode );
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index 03d91f9..b004f6c 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -486,4 +486,11 @@
 #endif
 void wlan_hdd_tdls_update_rx_pkt_cnt_n_rssi(hdd_adapter_t *pAdapter,
         u8 *mac, v_S7_t rssiAvg);
+
+
+tdlsConnInfo_t *wlan_hdd_get_conn_info(hdd_context_t *pHddCtx,
+                                       tANI_U8 idx);
+
+v_VOID_t wlan_hdd_tdls_initiator_wait_cb(v_PVOID_t userData);
+
 #endif // __HDD_TDSL_H
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 12ed8ab..34d39f1 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -16420,6 +16420,16 @@
                         if (pTdlsPeer->is_responder == 0)
                         {
                             v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
+                            tdlsConnInfo_t *tdlsInfo;
+
+                            tdlsInfo = wlan_hdd_get_conn_info(pHddCtx, staId);
+
+                            /* Initialize initiator wait callback */
+                            vos_timer_init(
+                                    &pTdlsPeer->initiatorWaitTimeoutTimer,
+                                    VOS_TIMER_TYPE_SW,
+                                    wlan_hdd_tdls_initiator_wait_cb,
+                                    tdlsInfo);
 
                             wlan_hdd_tdls_timer_restart(pAdapter,
                                                         &pTdlsPeer->initiatorWaitTimeoutTimer,
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index a0d6da2..cee77a3 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8048,6 +8048,34 @@
 
 } 
 
+hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
+                                        tANI_U32 sme_session_id )
+{
+    hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+    hdd_adapter_t *pAdapter;
+    VOS_STATUS vos_status;
+
+
+    vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
+
+    while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
+    {
+        pAdapter = pAdapterNode->pAdapter;
+
+        if (pAdapter->sessionId == sme_session_id)
+            return pAdapter;
+
+        vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
+        pAdapterNode = pNext;
+    }
+
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+            "%s: sme_session_id %d does not exist with host",
+            __func__, sme_session_id);
+
+    return NULL;
+}
+
 hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
 {
    hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 3d69137..eea0994 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -682,19 +682,57 @@
     return;
 }
 
-static v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData )
+v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData )
 {
-    hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
+    tdlsConnInfo_t *tdlsInfo = (tdlsConnInfo_t *) userData;
     tdlsCtx_t   *pHddTdlsCtx;
+    hdd_context_t *pHddCtx = NULL;
+    hdd_adapter_t *pAdapter = NULL;
+    v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_HDD, NULL);
+    hddTdlsPeer_t *curr_peer = NULL;
 
     ENTER();
-    if ( NULL == curr_peer )
+
+    if (!tdlsInfo->staId)
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
-                 FL("curr_peer is NULL"));
+                 FL("peer (staidx %u) doesn't exists"), tdlsInfo->staId);
+        return;
+    }
+    if (!pVosContext)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                FL("pVosContext is NULL"));
         return;
     }
 
+    pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
+    if (!pHddCtx)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                FL("pHddCtx is NULL"));
+        return;
+    }
+
+    pAdapter = hdd_get_adapter_by_sme_session_id(pHddCtx, tdlsInfo->sessionId);
+
+    if (!pAdapter)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                FL("pAdapter is NULL"));
+        return;
+    }
+
+    mutex_lock(&pHddCtx->tdls_lock);
+    curr_peer = wlan_hdd_tdls_find_peer(pAdapter,
+            (u8 *) &tdlsInfo->peerMac.bytes[0], FALSE);
+    if (curr_peer == NULL)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                FL("peer doesn't exists"));
+        mutex_unlock(&pHddCtx->tdls_lock);
+        return;
+    }
     pHddTdlsCtx = curr_peer->pHddTdlsCtx;
 
     if ( NULL == pHddTdlsCtx )
@@ -710,6 +748,7 @@
     }
     WLANTL_ResumeDataTx( (WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter))->pvosContext,
                            (v_U8_t *)&curr_peer->staId);
+    mutex_unlock(&pHddCtx->tdls_lock);
     EXIT();
 }
 
@@ -1107,7 +1146,8 @@
                        __func__,
                        MAC_ADDR_ARRAY(curr_peer->peerMac));
             vos_timer_stop ( &curr_peer->peerIdleTimer );
-            vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer );
+            if (vos_timer_is_initialized(&curr_peer->initiatorWaitTimeoutTimer))
+                vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer );
         }
     }
 }
@@ -1150,8 +1190,11 @@
                        MAC_ADDR_ARRAY(curr_peer->peerMac));
             vos_timer_stop ( &curr_peer->peerIdleTimer );
             vos_timer_destroy ( &curr_peer->peerIdleTimer );
-            vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer);
-            vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer);
+            if (vos_timer_is_initialized(&curr_peer->initiatorWaitTimeoutTimer))
+            {
+                vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer);
+                vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer);
+            }
         }
     }
 
@@ -1229,12 +1272,6 @@
                     VOS_TIMER_TYPE_SW,
                     wlan_hdd_tdls_idle_cb,
                     peer);
-
-    vos_timer_init(&peer->initiatorWaitTimeoutTimer,
-                    VOS_TIMER_TYPE_SW,
-                    wlan_hdd_tdls_initiator_wait_cb,
-                    peer);
-
     list_add_tail(&peer->node, head);
 
     return peer;
@@ -3310,4 +3347,22 @@
                                     FALSE);
     }
 }
+
+tdlsConnInfo_t *wlan_hdd_get_conn_info(hdd_context_t *pHddCtx,
+                                       tANI_U8 idx)
+{
+    tANI_U8 staIdx;
+
+    /* check if there is available index for this new TDLS STA */
+    for ( staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+    {
+        if (idx == pHddCtx->tdlsConnInfo[staIdx].staId )
+        {
+            hddLog(LOG1, FL("tdls peer with staIdx %u exists"), idx );
+            return (&pHddCtx->tdlsConnInfo[staIdx]);
+        }
+    }
+    hddLog(LOGE, FL("tdls peer with staIdx %u not exists"), idx );
+    return NULL;
+}
 /*EXT TDLS*/
diff --git a/CORE/VOSS/inc/vos_timer.h b/CORE/VOSS/inc/vos_timer.h
index c056a7e..49414e1 100644
--- a/CORE/VOSS/inc/vos_timer.h
+++ b/CORE/VOSS/inc/vos_timer.h
@@ -328,6 +328,6 @@
   ------------------------------------------------------------------------*/
 v_TIME_t vos_timer_get_system_time( v_VOID_t );
 
-
+v_BOOL_t vos_timer_is_initialized(vos_timer_t *timer);
 
 #endif // #if !defined __VOSS_TIMER_H
diff --git a/CORE/VOSS/src/vos_timer.c b/CORE/VOSS/src/vos_timer.c
index f67ba33..27e7ca9 100644
--- a/CORE/VOSS/src/vos_timer.c
+++ b/CORE/VOSS/src/vos_timer.c
@@ -886,3 +886,24 @@
    do_gettimeofday(&tv);
    return tv.tv_sec*1000 + tv.tv_usec/1000;  
 }
+
+/*--------------------------------------------------------------------------
+
+  \brief vos_timer_is_initialized() - check if timer is initialized or not
+
+  The \a vos_timer_is_initialized() function returns VOS_TRUE if timer is
+  initialized and VOS_FALSE if timer is not initialized
+
+  \returns - VOS_TRUE or VOS_FALSE
+
+  \sa
+
+  ------------------------------------------------------------------------*/
+v_BOOL_t vos_timer_is_initialized(vos_timer_t *timer)
+{
+    if (LINUX_TIMER_COOKIE == timer->platformInfo.cookie)
+        return VOS_TRUE;
+    else
+        return VOS_FALSE;
+}
+