TDLS: Move tdls_lock to HDD Context

Concurrent access to the data structures betweeen the TDLS
and other modules require an access to mutex lock.Hence move the
tdls_lock to the HDD context which is currently accessed only
by the tdls module.

Change-Id: Ia38d8117d9e8cd2f60bbec08e618af398e897afd
CRs-fixed: 553670
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index cde55bf..68d55aa 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1108,6 +1108,8 @@
     /* TDLS peer connected count */
     tANI_U16 connected_peer_count;
     tdls_scan_context_t tdls_scan_ctxt;
+   /* Lock to avoid race condition during TDLS operations*/
+   struct mutex tdls_lock;
 #endif
 
     hdd_traffic_monitor_t traffic_monitor;
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 6cee911..71bfa8f 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -7161,6 +7161,9 @@
    }
 
    mutex_init(&pHddCtx->sap_lock);
+#ifdef FEATURE_WLAN_TDLS
+   mutex_init(&pHddCtx->tdls_lock);
+#endif
 
    pHddCtx->isLoadUnloadInProgress = FALSE;
 
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 51bb3ca..87e5723 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -39,7 +39,6 @@
 #include "wlan_hdd_cfg80211.h"
 
 
-static struct mutex tdls_lock;
 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);
@@ -85,29 +84,28 @@
                                                         v_U32_t discoveryExpiry)
 {
     hdd_station_ctx_t *pHddStaCtx;
+    hdd_context_t *pHddCtx;
+
+    if ((NULL == pHddTdlsCtx))
+        return;
+
+    if ((NULL == pHddTdlsCtx->pAdapter) )
+        return;
+
+    pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
+
+    if (NULL == pHddCtx)
+        return;
 
     if ( mutexLock )
     {
-        if (mutex_lock_interruptible(&tdls_lock))
+        if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
         {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                      "%s: unable to lock list: %d", __func__, __LINE__);
            return;
         }
     }
-    if (NULL == pHddTdlsCtx)
-    {
-        if ( mutexLock )
-            mutex_unlock(&tdls_lock);
-        return;
-    }
-
-    if (NULL == pHddTdlsCtx->pAdapter)
-    {
-        if ( mutexLock )
-            mutex_unlock(&tdls_lock);
-        return;
-    }
 
     pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
@@ -119,7 +117,7 @@
                pHddTdlsCtx->ap_rssi);
 
     if ( mutexLock )
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
 
     return;
 }
@@ -132,30 +130,31 @@
     struct list_head *pos;
     hddTdlsPeer_t *curr_peer;
     hdd_station_ctx_t *pHddStaCtx;
+    hdd_context_t *pHddCtx;
     tdlsCtx_t *pHddTdlsCtx = (tdlsCtx_t *)userData;
     int discover_req_sent = 0;
     v_U32_t discover_expiry = TDLS_SUB_DISCOVERY_PERIOD;
     tANI_BOOLEAN doMutexLock = eANI_BOOLEAN_TRUE;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if ((NULL == pHddTdlsCtx))
+        return;
+
+    if (NULL == pHddTdlsCtx->pAdapter)
+        return;
+
+    pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
+
+    if (NULL == pHddCtx)
+        return;
+
+
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list : %d", __func__, __LINE__);
        return;
     }
 
-    if (NULL == pHddTdlsCtx)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
-
-    if (NULL == pHddTdlsCtx->pAdapter)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
-
     pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pHddTdlsCtx->pAdapter);
 
     VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: ", __func__);
@@ -228,7 +227,7 @@
 
     wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
 
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 
     /* Commenting out the following function as it was introducing
      * a race condition when pHddTdlsCtx is deleted. Also , this
@@ -244,7 +243,7 @@
     wlan_hdd_tdls_start_peer_discover_timer(pHddTdlsCtx, doMutexLock, discover_expiry);
 
     if ( !doMutexLock )
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
     return;
 }
 #endif
@@ -255,26 +254,26 @@
     struct list_head *head;
     struct list_head *pos;
     hddTdlsPeer_t *curr_peer;
-    tdlsCtx_t *pHddTdlsCtx;
+    tdlsCtx_t *pHddTdlsCtx = (tdlsCtx_t *)userData;
+    hdd_context_t *pHddCtx;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if ((NULL == pHddTdlsCtx))
+        return;
+
+    if (NULL == pHddTdlsCtx->pAdapter)
+        return;
+
+    pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
+
+    if (NULL == pHddCtx)
+        return;
+
+    if (mutex_lock_interruptible(&pHddCtx->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)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
-
-    if (NULL == pHddTdlsCtx->pAdapter)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
 
     for (i = 0; i < 256; i++) {
         head = &pHddTdlsCtx->peer_list[i];
@@ -401,13 +400,15 @@
     wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
                                 &pHddTdlsCtx->peerUpdateTimer,
                                 pHddTdlsCtx->threshold_config.tx_period_t);
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 }
 
 static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
 {
 #ifdef CONFIG_TDLS_IMPLICIT
     hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
+    tdlsCtx_t *pHddTdlsCtx;
+    hdd_context_t *pHddCtx;
 
     if (NULL == curr_peer)
     {
@@ -415,6 +416,16 @@
                "%s: Invalid tdls idle timer expired", __func__);
       return;
     }
+    pHddTdlsCtx = curr_peer->pHddTdlsCtx;
+
+    if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter) )
+        return;
+
+    pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
+
+    if (NULL == pHddCtx)
+        return;
+
 
     VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
               "%s: Tx/Rx Idle " MAC_ADDRESS_STR " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d\n",
@@ -423,7 +434,7 @@
               curr_peer->rx_pkt,
               curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n);
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
@@ -451,7 +462,7 @@
                                       curr_peer,
                                       eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
     }
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 #endif
 }
 
@@ -462,20 +473,24 @@
     hddTdlsPeer_t *tmp;
     struct list_head *pos, *q;
     tdlsCtx_t *pHddTdlsCtx;
+    hdd_context_t *pHddCtx;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    pHddTdlsCtx = (tdlsCtx_t *)userData;
+
+    if ((NULL == pHddTdlsCtx) || (NULL == pHddTdlsCtx->pAdapter) )
+        return;
+
+    pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
+
+    if (NULL == pHddCtx)
+        return;
+
+    if (mutex_lock_interruptible(&pHddCtx->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 )
-    {
-        mutex_unlock(&tdls_lock);
-        return ;
-    }
 
     for (i = 0; i < 256; i++) {
         head = &pHddTdlsCtx->peer_list[i];
@@ -494,7 +509,7 @@
     pHddTdlsCtx->discovery_sent_cnt = 0;
     wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
 
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 
     wlan_hdd_tdls_check_bmps(pHddTdlsCtx->pAdapter);
 
@@ -545,8 +560,6 @@
     int i;
     v_U8_t staIdx;
 
-    mutex_init(&tdls_lock);
-
     if ((FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport) ||
         (FALSE == sme_IsFeatureSupportedByFW(TDLS)))
     {
@@ -665,24 +678,23 @@
     tdlsCtx_t *pHddTdlsCtx;
     hdd_context_t *pHddCtx;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
+    if (NULL == pHddCtx)
+    {
+        return;
+    }
+
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
        return;
     }
 
-    pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
-    if (NULL == pHddCtx)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
-
     pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
     if (NULL == pHddTdlsCtx)
     {
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
         hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
         return;
     }
@@ -696,7 +708,7 @@
 
     vos_mem_free(pHddTdlsCtx);
     pHddTdlsCtx = NULL;
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 }
 
 /* stop all monitoring timers per Adapter */
@@ -793,6 +805,9 @@
     hddTdlsPeer_t *peer;
     u8 key;
     tdlsCtx_t *pHddTdlsCtx;
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+    if ((NULL == pHddCtx)) return NULL;
 
     /* if already there, just update */
     peer = wlan_hdd_tdls_find_peer(pAdapter, mac);
@@ -808,7 +823,7 @@
         return NULL;
     }
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
@@ -820,7 +835,7 @@
     if (NULL == pHddTdlsCtx)
     {
         vos_mem_free(peer);
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
         return NULL;
     }
 
@@ -842,7 +857,7 @@
                     peer);
 
     list_add_tail(&peer->node, head);
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 
     return peer;
 }
@@ -1205,9 +1220,11 @@
     struct list_head *head;
     hddTdlsPeer_t *curr_peer;
     tdlsCtx_t *pHddTdlsCtx;
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
 
+    if ((NULL == pHddCtx)) return NULL;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
@@ -1216,7 +1233,7 @@
     pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
     if (NULL == pHddTdlsCtx)
     {
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
         return NULL;
     }
 
@@ -1229,12 +1246,12 @@
         if (!memcmp(mac, curr_peer->peerMac, 6)) {
             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                      "findTdlsPeer: found staId %d", curr_peer->staId);
-            mutex_unlock(&tdls_lock);
+            mutex_unlock(&pHddCtx->tdls_lock);
             return curr_peer;
         }
     }
 
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
     return NULL;
 }
 
@@ -1369,6 +1386,12 @@
     struct list_head *pos;
     hddTdlsPeer_t *curr_peer;
     tdlsCtx_t *pHddTdlsCtx;
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+
+    if ((NULL == pHddCtx)) {
+        len = snprintf(buf, buflen, "NULL HddCtx\n");
+        return len;
+    }
 
 
     init_len = buflen;
@@ -1381,7 +1404,7 @@
     buf += len;
     buflen -= len;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
@@ -1389,7 +1412,7 @@
     }
     pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
     if (NULL == pHddTdlsCtx) {
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
         len = scnprintf(buf, buflen, "TDLS not enabled\n");
         return len;
     }
@@ -1412,28 +1435,24 @@
             buflen -= len;
         }
     }
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
     return init_len-buflen;
 }
 
 void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
 {
-    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
     tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return;
+
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
        return;
     }
 
-    if (NULL == pHddCtx || NULL == pHddTdlsCtx)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
-
     VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
     "%s, update %d discover %d", __func__,
         pHddTdlsCtx->threshold_config.tx_period_t,
@@ -1454,17 +1473,20 @@
                                    &pHddTdlsCtx->peerUpdateTimer,
                                    pHddTdlsCtx->threshold_config.tx_period_t);
     }
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 
 }
 
 void wlan_hdd_tdls_disconnection_callback(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 == pHddCtx) || (NULL == pHddTdlsCtx)) return;
 
     VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s", __func__);
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
@@ -1472,7 +1494,7 @@
     }
     if (NULL == pHddTdlsCtx)
     {
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
         return;
     }
     pHddTdlsCtx->discovery_sent_cnt = 0;
@@ -1482,7 +1504,7 @@
     wlan_hdd_tdls_peer_timers_destroy(pHddTdlsCtx);
     wlan_hdd_tdls_free_list(pHddTdlsCtx);
 
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 }
 
 void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
@@ -1585,23 +1607,26 @@
     hddTdlsPeer_t *curr_peer;
     struct list_head *pos;
     tdlsCtx_t *pHddTdlsCtx;
+    hdd_context_t *pHddCtx;
+
+    pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
+    if (NULL == pHddTdlsCtx)
+        return NULL;
+
+    pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter );
+
+    if (NULL == pHddCtx)
+        return NULL;
 
     if (mutexLock)
     {
-        if (mutex_lock_interruptible(&tdls_lock))
+        if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
         {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
            return NULL;
         }
     }
-    pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
-    if (NULL == pHddTdlsCtx)
-    {
-        if (mutexLock)
-            mutex_unlock(&tdls_lock);
-        return NULL;
-    }
 
     for (i = 0; i < 256; i++) {
         head = &pHddTdlsCtx->peer_list[i];
@@ -1618,7 +1643,7 @@
                             "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING",
                             __func__, MAC_ADDR_ARRAY(curr_peer->peerMac));
                   if (mutexLock)
-                      mutex_unlock(&tdls_lock);
+                      mutex_unlock(&pHddCtx->tdls_lock);
                   return curr_peer;
                 }
             }
@@ -1626,7 +1651,7 @@
     }
 
     if (mutexLock)
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
     return NULL;
 }
 
@@ -1689,24 +1714,21 @@
     tdlsCtx_t *pHddTdlsCtx;
 
     VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s mode %d", __func__, (int)tdls_mode);
+    if (NULL == pHddCtx)
+        return;
 
-    if (mutex_lock_interruptible(&tdls_lock))
+    if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
     {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: unable to lock list", __func__);
        return;
     }
 
-    if (NULL == pHddCtx)
-    {
-        mutex_unlock(&tdls_lock);
-        return;
-    }
 
     if (pHddCtx->tdls_mode == tdls_mode)
     {
         hddLog(TDLS_LOG_LEVEL, "%s already in mode %d", __func__, (int)tdls_mode);
-        mutex_unlock(&tdls_lock);
+        mutex_unlock(&pHddCtx->tdls_lock);
         return;
     }
 
@@ -1737,7 +1759,7 @@
     }
     pHddCtx->tdls_mode = tdls_mode;
 
-    mutex_unlock(&tdls_lock);
+    mutex_unlock(&pHddCtx->tdls_lock);
 }
 
 static void wlan_hdd_tdls_pre_setup(struct work_struct *work)