Move tdls_pre_setup execution from MC thread to worker thread

Move tdls_pre_setup execution to linux worker thread as it invites
deadlock in wait_for_completion for full power request.
Remove the exception of TDLS discovery req frame not wait_for_
completion in cfg80211_tdls_mgmt() to  make sure atomic operation
of halTxFrame().
Call cfg80211_tdls_mgmt() wrapper to send TDLS discovery req
in tlds_pre_setup instead of sme_SendTdlsMgmtFrame.
Introduce compilation flag not to use separate discovery timer as
it is currently obsolete, but leave it for the future reference.

Change-Id: Ia8cc02d96271ed03fcaa351c4918d900d1661aef
CRs-Fixed: 478008
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 45ff906..8a7423d 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -43,7 +43,9 @@
 static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx);
 static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx);
 static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
-static void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx,hddTdlsPeer_t *curr_peer);
+#ifdef CONFIG_TDLS_IMPLICIT
+static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
+#endif
 
 #ifndef WLAN_FEATURE_TDLS_DEBUG
 #define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
@@ -62,6 +64,21 @@
     return key;
 }
 
+#ifdef CONFIG_TDLS_IMPLICIT
+static void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx,
+                                              hddTdlsPeer_t *curr_candidate)
+{
+    if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic)
+    {
+        pHddTdlsCtx->curr_candidate = curr_candidate;
+        pHddTdlsCtx->magic = TDLS_CTX_MAGIC;
+
+        INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup);
+        schedule_work(&pHddTdlsCtx->implicit_setup);
+    }
+}
+#endif
+
 static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx,
                                                         tANI_BOOLEAN mutexLock,
                                                         v_U32_t discoveryExpiry)
@@ -106,6 +123,7 @@
     return;
 }
 
+#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
 static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData )
 {
     int i;
@@ -228,6 +246,7 @@
         mutex_unlock(&tdls_lock);
     return;
 }
+#endif
 
 static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData )
 {
@@ -288,7 +307,7 @@
 
                             VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Tput trigger TDLS pre-setup");
 #ifdef CONFIG_TDLS_IMPLICIT
-                            wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer);
+                            wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
 #endif
                         }
                         else
@@ -359,7 +378,9 @@
                         if (curr_peer->discovery_attempt++ <
                                  pHddTdlsCtx->threshold_config.discovery_tries_n) {
                             VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "TDLS UNKNOWN discover ");
-                            wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer);
+#ifdef CONFIG_TDLS_IMPLICIT
+                            wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
+#endif
                         }
                         else
                         {
@@ -573,10 +594,15 @@
         INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]);
     }
 
+    pHddTdlsCtx->curr_candidate = NULL;
+    pHddTdlsCtx->magic = 0;
+
+#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
     vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
             VOS_TIMER_TYPE_SW,
             wlan_hdd_tdls_discover_peer_cb,
             pHddTdlsCtx);
+#endif
 
     vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
             VOS_TIMER_TYPE_SW,
@@ -658,7 +684,9 @@
     struct list_head *pos;
     hddTdlsPeer_t *curr_peer;
 
+#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
     vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
+#endif
     vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
     vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
 
@@ -687,8 +715,10 @@
     struct list_head *pos;
     hddTdlsPeer_t *curr_peer;
 
+#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER
     vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
     vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
+#endif
     vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
     vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
     vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer);
@@ -1634,15 +1664,31 @@
     mutex_unlock(&tdls_lock);
 }
 
-static void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx,
-                             hddTdlsPeer_t *curr_peer)
+static void wlan_hdd_tdls_pre_setup(struct work_struct *work)
 {
-    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
+    tdlsCtx_t *pHddTdlsCtx =
+       container_of(work, tdlsCtx_t, implicit_setup);
+    hdd_context_t *pHddCtx;
+    hddTdlsPeer_t *curr_peer;
     hddTdlsPeer_t *temp_peer;
+    int status;
+
+    if (NULL == pHddTdlsCtx)
+        return;
+
+    if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic))
+        return;
+
+    pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
 
     if (NULL == pHddCtx)
         return;
 
+    curr_peer = pHddTdlsCtx->curr_candidate;
+
+    if (NULL == curr_peer)
+        return;
+
     if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter)))
     {
         VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Disable BMPS", __func__);
@@ -1654,17 +1700,25 @@
     {
         VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored\n",
             __func__, MAC_ADDR_ARRAY(temp_peer->peerMac));
-        return;
+        goto done;
     }
 
     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);
+    status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy,
+                                            pHddTdlsCtx->pAdapter->dev,
+                                            curr_peer->peerMac);
+
+    if (0 != status)
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " discovery could not sent\n",
+            __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
+        if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
+            curr_peer->link_status = eTDLS_LINK_IDLE;
+        goto done;
+    }
+
     pHddTdlsCtx->discovery_sent_cnt++;
     wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
     VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu timeout %lu msec",
@@ -1675,6 +1729,9 @@
                                 &pHddTdlsCtx->peerDiscoveryTimeoutTimer,
                                 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
 
+done:
+    pHddTdlsCtx->curr_candidate = NULL;
+    pHddTdlsCtx->magic = 0;
     return;
 }