prima: implicit TDLS Discovery Request event through supplicant

This commit introduces sending implicit TDLS Discovery Request to
TDLS Peer through wpa_supplicant instead of work-queue mechanism which
is used to trigger the TDLS Discovery request.
This eliminates concurrent TDLS data structures access.

Change-Id: Id6d6b38d2b17c4b1bab9b616b52e5a2d8c3475dc
Crs-Fixed: 798119
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 83fa05a..413a974 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -8308,7 +8308,7 @@
     }
 
     /* when others are on-going, we want to change link_status to idle */
-    if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
+    if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
     {
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: " MAC_ADDRESS_STR
@@ -14583,7 +14583,7 @@
 
     if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
     {
-        if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
+        if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
         {
             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                        "%s: " MAC_ADDRESS_STR
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index c27c304..42e2ab5 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -51,7 +51,7 @@
 static void wlan_hdd_tdls_peer_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
 int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac);
 #ifdef CONFIG_TDLS_IMPLICIT
-static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
+static void wlan_hdd_tdls_implicit_send_discovery_request(tdlsCtx_t *pHddTdlsCtx);
 #endif
 
 static u8 wlan_hdd_tdls_hash_key (u8 *mac)
@@ -65,20 +65,6 @@
     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;
-
-        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)
@@ -198,11 +184,12 @@
 
                         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, 0, NULL, 0, 0);
+                            cfg80211_tdls_oper_request(
+                                               pHddTdlsCtx->pAdapter->dev,
+                                               curr_peer->peerMac,
+                                               NL80211_TDLS_DISCOVERY_REQ,
+                                               FALSE,
+                                               GFP_KERNEL);
                             curr_peer->discovery_attempt++;
                         }
                         else
@@ -326,7 +313,8 @@
                             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                                        "Tput trigger TDLS pre-setup");
 #ifdef CONFIG_TDLS_IMPLICIT
-                            wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
+                            pHddTdlsCtx->curr_candidate = curr_peer;
+                            wlan_hdd_tdls_implicit_send_discovery_request(pHddTdlsCtx);
 #endif
                         }
                         else
@@ -413,7 +401,8 @@
                             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                                        "TDLS UNKNOWN discover ");
 #ifdef CONFIG_TDLS_IMPLICIT
-                            wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer);
+                            pHddTdlsCtx->curr_candidate = curr_peer;
+                            wlan_hdd_tdls_implicit_send_discovery_request(pHddTdlsCtx);
 #endif
                         }
                         else
@@ -726,7 +715,7 @@
         }
 
         /* tdls is in progress */
-        currPeer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
+        currPeer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
         if (NULL != currPeer)
         {
             wlan_hdd_tdls_set_peer_link_status (currPeer,
@@ -926,7 +915,6 @@
     pHddTdlsCtx->threshold_config.rssi_trigger_threshold = pHddCtx->cfg_ini->fTDLSRSSITriggerThreshold;
     pHddTdlsCtx->threshold_config.rssi_teardown_threshold = pHddCtx->cfg_ini->fTDLSRSSITeardownThreshold;
 
-    INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup);
     INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, wlan_hdd_tdls_schedule_scan);
     set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
 
@@ -974,19 +962,6 @@
     }
 
 #ifdef WLAN_OPEN_SOURCE
-    if (mutexLock)
-    {
-        mutex_unlock(&pHddCtx->tdls_lock);
-    }
-    /* Holding mutex in tdls implicit_setup work queue and
-     * while cancelling it is leading to deadlock.
-     * So avoid holding mutex while cancelling the workqueue.
-     */
-    cancel_work_sync(&pHddTdlsCtx->implicit_setup);
-    if (mutexLock)
-    {
-        mutex_lock(&pHddCtx->tdls_lock);
-    }
     cancel_delayed_work_sync(&pHddCtx->tdls_scan_ctxt.tdls_scan_work);
 #endif
 
@@ -2163,7 +2138,7 @@
        return;
     }
 
-    curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
+    curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
     if (NULL != curr_peer)
     {
         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -2253,7 +2228,8 @@
     return NULL;
 }
 
-hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac, u8 skip_self)
+hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac,
+                                         u8 skip_self, tANI_BOOLEAN mutexLock)
 {
     hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
     hdd_adapter_t *pAdapter = NULL;
@@ -2261,8 +2237,10 @@
     hddTdlsPeer_t *curr_peer= NULL;
     VOS_STATUS status = 0;
 
-    mutex_lock(&pHddCtx->tdls_lock);
-
+    if (mutexLock)
+    {
+        mutex_lock(&pHddCtx->tdls_lock);
+    }
     status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
     while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
     {
@@ -2274,14 +2252,16 @@
             curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self);
             if (curr_peer)
             {
-                mutex_unlock(&pHddCtx->tdls_lock);
+                if (mutexLock)
+                    mutex_unlock(&pHddCtx->tdls_lock);
                 return curr_peer;
             }
         }
         status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
         pAdapterNode = pNext;
     }
-    mutex_unlock(&pHddCtx->tdls_lock);
+    if (mutexLock)
+        mutex_unlock(&pHddCtx->tdls_lock);
     return NULL;
 }
 
@@ -2368,14 +2348,11 @@
     EXIT();
 }
 
-static void __wlan_hdd_tdls_pre_setup(struct work_struct *work)
+static
+void wlan_hdd_tdls_implicit_send_discovery_request(tdlsCtx_t * pHddTdlsCtx)
 {
-    tdlsCtx_t *pHddTdlsCtx =
-       container_of(work, tdlsCtx_t, implicit_setup);
-    hdd_context_t *pHddCtx;
-    hddTdlsPeer_t *curr_peer;
-    hddTdlsPeer_t *temp_peer;
-    int status;
+    hdd_context_t *pHddCtx = NULL;
+    hddTdlsPeer_t *curr_peer = NULL, *temp_peer = NULL;
 
     ENTER();
     if (NULL == pHddTdlsCtx)
@@ -2385,13 +2362,6 @@
         return;
     }
 
-    if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic))
-    {
-        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
-                 "%s: tdls magic no missmatch %u", __func__, pHddTdlsCtx->magic);
-        return;
-    }
-
     pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter);
 
     if(0 != (wlan_hdd_validate_context(pHddCtx)))
@@ -2400,7 +2370,6 @@
     }
 
     curr_peer = pHddTdlsCtx->curr_candidate;
-
     if (NULL == curr_peer)
     {
         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
@@ -2416,11 +2385,13 @@
         hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
     }
 
-    temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
+    /* This function is called in mutex_lock */
+    temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, FALSE);
     if (NULL != temp_peer)
     {
-        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored",
-            __func__, MAC_ADDR_ARRAY(temp_peer->peerMac));
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                  "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored",
+                  __func__, MAC_ADDR_ARRAY(temp_peer->peerMac));
         goto done;
     }
 
@@ -2429,37 +2400,26 @@
                                            eTDLS_LINK_DISCOVERING,
                                            eTDLS_LINK_SUCCESS);
 
-    status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy,
-                                            pHddTdlsCtx->pAdapter->dev,
-                                            curr_peer->peerMac);
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+              "%s: Implicit TDLS, Send Discovery request event", __func__);
 
-    if (0 != status)
-    {
-        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
-                   "%s: " MAC_ADDRESS_STR " discovery could not sent",
-                   __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
-        if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
-            wlan_hdd_tdls_set_peer_link_status(curr_peer,
-                                               eTDLS_LINK_IDLE,
-                                               eTDLS_LINK_UNSPECIFIED);
-        goto done;
-    }
-
+    cfg80211_tdls_oper_request(pHddTdlsCtx->pAdapter->dev,
+                                   curr_peer->peerMac,
+                                   NL80211_TDLS_DISCOVERY_REQ,
+                                   FALSE,
+                                   GFP_KERNEL);
     pHddTdlsCtx->discovery_sent_cnt++;
 
-    mutex_lock(&pHddCtx->tdls_lock);
-
     wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
 
     wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
                                 &pHddTdlsCtx->peerDiscoveryTimeoutTimer,
                                 pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
 
-    mutex_unlock(&pHddCtx->tdls_lock);
-    VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
-               "%s: discovery count %u timeout %u msec",
-               __func__, pHddTdlsCtx->discovery_sent_cnt,
-               pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+              "%s: discovery count %u timeout %u msec",
+              __func__, pHddTdlsCtx->discovery_sent_cnt,
+              pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
 
 done:
     pHddTdlsCtx->curr_candidate = NULL;
@@ -2468,16 +2428,6 @@
     return;
 }
 
-
-static void wlan_hdd_tdls_pre_setup(struct work_struct *work)
-{
-    vos_ssr_protect(__func__);
-    __wlan_hdd_tdls_pre_setup(work);
-    vos_ssr_unprotect(__func__);
-
-    return;
-}
-
 tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx)
 {
     hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
@@ -2627,7 +2577,7 @@
     if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
         (pHddCtx->is_tdls_btc_enabled == FALSE))
         return 1;
-    curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
+    curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE);
     if (NULL != curr_peer)
     {
         if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT)