prima: Send Deauth and delete all TDLS stations.

Send Deauth to TDLS peers, delete TDLS stations
and clear hdd structures if concurrency is detected.

Change-Id: Icc2019d78fc2447d388afd8a0ccb290df056e5e3
CRs-Fixed: 878382
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index fe44b4f..3b87e96 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -78,6 +78,7 @@
 {
     u16 connected_tdls_peers = 0;
     u8 staIdx;
+    hddTdlsPeer_t *curr_peer = NULL;
     hdd_adapter_t *adapter = NULL;
 
     if (eTDLS_SUPPORT_NOT_ENABLED == hddctx->tdls_mode) {
@@ -98,31 +99,65 @@
          return;
     }
 
-    /*Send Msg to PE for deleting all the TDLS peers*/
-    sme_DeleteAllTDLSPeers(hddctx->hHal, adapter->sessionId);
-    /* 0 staIdx is assigned to AP we dont want to touch that */
-    for ( staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
-    {
-        if (hddctx->tdlsConnInfo[staIdx].staId)
-        {
-            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
-                    ("hdd_tdlsStatusUpdate: staIdx %d " MAC_ADDRESS_STR),
-                    hddctx->tdlsConnInfo[staIdx].staId,
-                    MAC_ADDR_ARRAY(hddctx->tdlsConnInfo[staIdx].peerMac.bytes));
-            wlan_hdd_tdls_reset_peer(
-                                adapter,
-                                hddctx->tdlsConnInfo[staIdx].peerMac.bytes);
-            hdd_roamDeregisterTDLSSTA(adapter,
-                                      hddctx->tdlsConnInfo[staIdx].staId );
-            wlan_hdd_tdls_decrement_peer_count(adapter);
-
-            vos_mem_zero(&hddctx->tdlsConnInfo[staIdx].peerMac,
-                    sizeof(v_MACADDR_t)) ;
-            hddctx->tdlsConnInfo[staIdx].staId = 0 ;
-            hddctx->tdlsConnInfo[staIdx].sessionId = 255;
+    /* TDLS is not supported in case of concurrency
+     * Disable TDLS Offchannel to avoid more than two concurrent channels.
+     */
+    if (connected_tdls_peers == 1) {
+        curr_peer = wlan_hdd_tdls_get_connected_peer(adapter);
+        if (curr_peer && (curr_peer->isOffChannelConfigured == TRUE)) {
+            hddLog(LOG1, FL("%s: Concurrency detected, Disable "
+                        "TDLS channel switch"), __func__);
+            curr_peer->isOffChannelEstablished = FALSE;
+            sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(adapter),
+                    adapter->sessionId,
+                    curr_peer->peerMac,
+                    curr_peer->peerParams.channel,
+                    TDLS_OFF_CHANNEL_BW_OFFSET,
+                    TDLS_CHANNEL_SWITCH_DISABLE);
         }
     }
-    wlan_hdd_tdls_check_bmps(adapter);
+
+    /* Send Msg to PE for sending deauth and deleting all the TDLS peers */
+    sme_DeleteAllTDLSPeers(hddctx->hHal, adapter->sessionId);
+
+    /* As mentioned above TDLS is not supported in case of concurrency
+     * Find the connected peer and generate TDLS teardown indication to
+     * supplicant.
+     */
+    for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++) {
+        if (!hddctx->tdlsConnInfo[staIdx].staId)
+            continue;
+
+        curr_peer = wlan_hdd_tdls_find_all_peer(hddctx,
+                hddctx->tdlsConnInfo[staIdx].peerMac.bytes);
+
+        if (!curr_peer)
+            continue;
+
+        /* Del Sta happened already as part of sme_DeleteAllTDLSPeers
+         * Hence clear hdd data structure.
+         */
+        hdd_roamDeregisterTDLSSTA(adapter,
+                                  hddctx->tdlsConnInfo[staIdx].staId);
+        wlan_hdd_tdls_decrement_peer_count(adapter);
+        wlan_hdd_tdls_reset_peer(adapter, curr_peer->peerMac);
+
+        hddctx->tdlsConnInfo[staIdx].staId = 0 ;
+        hddctx->tdlsConnInfo[staIdx].sessionId = 255;
+        vos_mem_zero(&hddctx->tdlsConnInfo[staIdx].peerMac,
+                 sizeof(v_MACADDR_t)) ;
+        wlan_hdd_tdls_check_bmps(adapter);
+
+        hddLog(LOG1, FL("indicate TDLS teardown (staId %d)"),
+                curr_peer->staId);
+
+        /* Indicate teardown to supplicant */
+        wlan_hdd_tdls_indicate_teardown(
+                curr_peer->pHddTdlsCtx->pAdapter,
+                curr_peer,
+                eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+    }
+
     wlan_hdd_tdls_set_mode(hddctx, eTDLS_SUPPORT_DISABLED, FALSE);
     hddLog(LOG1, FL("TDLS Support Disabled"));
 }