Fix for the pmcState messed up during TDLS setup

Change the device state to FULL_POWER defore sending discovery
request and if the discovery request is followed by TDLS setup
then remain in FULL_POWER mode otherwise put the device into
BMPS as soon as discovery response is received or discovery
response timeout is happened.
Change the value of discover response timeout to one sec less
than the update peer timer.
Check for the TDLS connection everytime before entering into
BMPS state when pmc traffic timer expired.

CRs-Fixed: 464212
Change-Id: Iddd7d84d0c3d1a3bcc862d2802cd323daca64df0
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index 45ce039..7b2d753 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -44,7 +44,9 @@
 
 #define TDLS_RSSI_TRIGGER_HYSTERESIS 50
 
-#define TDLS_DISCOVERY_TIMEOUT       1000
+/* before UpdateTimer expires, we want to timeout discovery response.
+should not be more than 2000 */
+#define TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE     1000
 
 typedef struct
 {
@@ -195,4 +197,8 @@
 
 void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, hddTdlsPeer_t *curr_peer);
 
+tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx);
+
+void wlan_hdd_tdls_set_power_save_prohibited(hdd_adapter_t *pAdapter);
+
 #endif // __HDD_TDSL_H
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 56b5281..4891e9e 100755
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -2725,7 +2725,7 @@
         return -EBUSY;
     }
 
-    if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE))
+    if ((0 == update) && wlan_hdd_tdls_is_progress(pAdapter, mac, FALSE))
     {
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: " MAC_ADDRESS_STR
@@ -6977,10 +6977,13 @@
 
                 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
                 {
+                    wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
                     /* start TDLS client registration with TL */
                     status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
-                    wlan_hdd_tdls_increment_peer_count(pAdapter);
-                    wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
+                    if (VOS_STATUS_SUCCESS == status)
+                    {
+                        wlan_hdd_tdls_increment_peer_count(pAdapter);
+                    }
                     wlan_hdd_tdls_check_bmps(pAdapter);
                 }
 
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index bf69952..2b3f31d 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -384,12 +384,7 @@
 
                         if (++curr_peer->discovery_attempt <
                                  pHddTdlsCtx->threshold_config.discovery_tries_n) {
-
-                            sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
-                                                  pHddTdlsCtx->pAdapter->sessionId,
-                                                  curr_peer->peerMac,
-                                                  WLAN_TDLS_DISCOVERY_REQUEST,
-                                                  1, 0, NULL, 0, 0);
+                            wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer);
                         }
                         else
                         {
@@ -442,13 +437,45 @@
 
 static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData)
 {
+    int i;
+    struct list_head *head;
+    hddTdlsPeer_t *tmp;
+    struct list_head *pos, *q;
     tdlsCtx_t *pHddTdlsCtx;
 
+    if (mutex_lock_interruptible(&tdls_lock))
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: unable to lock list", __func__);
+        return ;
+    }
     pHddTdlsCtx = (tdlsCtx_t *)userData;
-    if (NULL == pHddTdlsCtx)
-        return;
+
+    if ( NULL == pHddTdlsCtx )
+    {
+        mutex_unlock(&tdls_lock);
+        return ;
+    }
+
+    for (i = 0; i < 256; i++) {
+        head = &pHddTdlsCtx->peer_list[i];
+        list_for_each_safe (pos, q, head) {
+            tmp = list_entry(pos, hddTdlsPeer_t, node);
+            if (eTDLS_LINK_DISCOVERING == tmp->link_status)
+            {
+                VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+                           "%s: " MAC_ADDRESS_STR " to idle state", __func__,
+                           MAC_ADDR_ARRAY(tmp->peerMac));
+                tmp->link_status = eTDLS_LINK_IDLE;
+            }
+        }
+    }
 
     pHddTdlsCtx->discovery_sent_cnt = 0;
+    wlan_hdd_tdls_set_power_save_prohibited(pHddTdlsCtx->pAdapter);
+
+    mutex_unlock(&tdls_lock);
+
     wlan_hdd_tdls_check_bmps(pHddTdlsCtx->pAdapter);
 
     return;
@@ -506,6 +533,7 @@
 
     /* initialize TDLS global context */
     pHddCtx->connected_peer_count = 0;
+    sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
 
     for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
     {
@@ -771,9 +799,11 @@
     if (pHddTdlsCtx->discovery_sent_cnt)
         pHddTdlsCtx->discovery_sent_cnt--;
 
+    wlan_hdd_tdls_set_power_save_prohibited(pAdapter);
     if (0 == pHddTdlsCtx->discovery_sent_cnt)
+    {
         vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
-    wlan_hdd_tdls_check_bmps(pAdapter);
+    }
 
     VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
                "Discovery(%lu) Response from " MAC_ADDRESS_STR " link_status %d",
@@ -790,6 +820,10 @@
                                    GFP_KERNEL);
         curr_peer->link_status = eTDLS_LINK_DISCOVERED;
     }
+    else
+    {
+        wlan_hdd_tdls_check_bmps(pAdapter);
+    }
 
     curr_peer->tdls_support = eTDLS_CAP_SUPPORTED;
     return 0;
@@ -1247,6 +1281,7 @@
     {
        wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
        pHddTdlsCtx->discovery_sent_cnt = 0;
+       wlan_hdd_tdls_set_power_save_prohibited(pHddTdlsCtx->pAdapter);
 
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
        vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
@@ -1275,6 +1310,8 @@
         mutex_unlock(&tdls_lock);
         return;
     }
+    pHddTdlsCtx->discovery_sent_cnt = 0;
+    wlan_hdd_tdls_set_power_save_prohibited(pHddTdlsCtx->pAdapter);
 
     wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
     wlan_hdd_tdls_free_list(pHddTdlsCtx);
@@ -1297,6 +1334,10 @@
     if (NULL == pHddCtx) return;
 
     pHddCtx->connected_peer_count++;
+    wlan_hdd_tdls_set_power_save_prohibited(pAdapter);
+
+    VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
+               __func__, pHddCtx->connected_peer_count);
 }
 
 void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter)
@@ -1307,6 +1348,11 @@
 
     if (pHddCtx->connected_peer_count)
         pHddCtx->connected_peer_count--;
+    wlan_hdd_tdls_set_power_save_prohibited(pAdapter);
+
+    VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: %d",
+               __func__, pHddCtx->connected_peer_count);
+
 }
 
 void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter)
@@ -1322,7 +1368,8 @@
         if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
         {
             VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
-                       "No TDLS peer connected/discovery sent. Enable BMPS");
+                       "%s: No TDLS peer connected/discovery sent. Enable BMPS",
+                       __func__);
             hdd_enable_bmps_imps(pHddCtx);
         }
     }
@@ -1330,7 +1377,8 @@
     {
         if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
         {
-            VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"TDLS peer connected. Disable BMPS");
+            VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+                       "%s: TDLS peer connected. Disable BMPS", __func__);
             hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
         }
     }
@@ -1407,6 +1455,8 @@
     wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
     pHddTdlsCtx->discovery_sent_cnt = 0;
     wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx);
+    wlan_hdd_tdls_set_power_save_prohibited(pHddTdlsCtx->pAdapter);
+
 
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
     vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
@@ -1454,19 +1504,72 @@
 
     if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter)))
     {
+        VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Disable BMPS", __func__);
         hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
     }
-    curr_peer->link_status = eTDLS_LINK_DISCOVERING;
+
+    if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
+        curr_peer->link_status = eTDLS_LINK_DISCOVERING;
+
     sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter),
                           pHddTdlsCtx->pAdapter->sessionId,
                           curr_peer->peerMac,
                           WLAN_TDLS_DISCOVERY_REQUEST,
                           1, 0, NULL, 0, 0);
     pHddTdlsCtx->discovery_sent_cnt++;
-    VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu",
-               __func__, pHddTdlsCtx->discovery_sent_cnt);
+    wlan_hdd_tdls_set_power_save_prohibited(pHddTdlsCtx->pAdapter);
+    VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu timeout %lu msec",
+               __func__, pHddTdlsCtx->discovery_sent_cnt,
+               pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
     vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
-    vos_timer_start(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, TDLS_DISCOVERY_TIMEOUT);
+    vos_timer_start(&pHddTdlsCtx->peerDiscoveryTimeoutTimer,
+        pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
 
     return;
 }
+
+tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx)
+{
+    hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
+    hdd_adapter_t *pAdapter = NULL;
+    tdlsCtx_t *pHddTdlsCtx = NULL;
+    VOS_STATUS status = 0;
+    tANI_U32 count = 0;
+
+    status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
+    while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
+    {
+        pAdapter = pAdapterNode->pAdapter;
+
+        if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
+            (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
+        {
+            pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
+            if (NULL != pHddTdlsCtx)
+            {
+                count = count + pHddTdlsCtx->discovery_sent_cnt;
+            }
+        }
+        status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
+        pAdapterNode = pNext;
+    }
+    return count;
+}
+
+void wlan_hdd_tdls_set_power_save_prohibited(hdd_adapter_t *pAdapter)
+{
+    tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+    if ((NULL == pHddTdlsCtx) || (NULL == pHddCtx))
+        return;
+
+    if ((0 == pHddCtx->connected_peer_count) &&
+        (0 == wlan_hdd_tdls_discovery_sent_cnt(pHddCtx)))
+    {
+        sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 0);
+        return;
+    }
+    sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), 1);
+    return;
+}