Fix for device not coming to BMPS after teardown TDLS link

Once the TDLS link is up, the device goes into FULL_POWER mode
and never comes to BMPS mode even after all the TDLS links are
torn down.
Set the pmcState to FULL_POWER at the time of TDLS_ENABLE_LINK
and resets to BMPS mode after all the TDLS links are torn down.

CRs-Fixed: 452166
Change-Id: I3e2a25dca8d10fbf901ae739384c16e98f9abb60
diff --git a/CORE/HDD/inc/wlan_hdd_assoc.h b/CORE/HDD/inc/wlan_hdd_assoc.h
index 40d0b5c..26aab58 100644
--- a/CORE/HDD/inc/wlan_hdd_assoc.h
+++ b/CORE/HDD/inc/wlan_hdd_assoc.h
@@ -44,7 +44,7 @@
 #include <wlan_hdd_mib.h>
 #define HDD_MAX_NUM_IBSS_STA ( 4 )
 #ifdef FEATURE_WLAN_TDLS
-#define HDD_MAX_NUM_TDLS_STA ( 4 )
+#define HDD_MAX_NUM_TDLS_STA ( HDD_MAX_NUM_IBSS_STA - 1 ) // up to 3 as 1 is assigned to AP
 #endif
 #define TKIP_COUNTER_MEASURE_STARTED 1
 #define TKIP_COUNTER_MEASURE_STOPED  0 
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index c0cefb6..6bd34d8 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -99,6 +99,11 @@
 #define QCOM_VENDOR_IE_AGE_TYPE  0x100
 #define QCOM_VENDOR_IE_AGE_LEN   4
 
+#ifdef FEATURE_WLAN_TDLS
+#define WLAN_IS_TDLS_SETUP_ACTION(action) \
+         ((SIR_MAC_TDLS_SETUP_REQ <= action) && (SIR_MAC_TDLS_SETUP_CNF >= action))
+#endif
+
 typedef struct {
    u8 element_id;
    u8 len;
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 23331df..1137c1d 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -126,6 +126,9 @@
 /** Maximum time(ms) to wait for tdls add sta to complete **/
 #define WAIT_TIME_TDLS_ADD_STA      1500
 
+/** Maximum time(ms) to wait for tdls mgmt to complete **/
+#define WAIT_TIME_TDLS_MGMT         2000
+
 /* Maximum time to get crda entry settings */
 #define CRDA_WAIT_TIME 300
 
@@ -722,10 +725,15 @@
 
 #ifdef FEATURE_WLAN_TDLS
    struct completion tdls_add_station_comp;
+   struct completion tdls_mgmt_comp;
+   eHalStatus tdlsAddStaStatus;
 #endif
    /* Track whether the linkup handling is needed  */
    v_BOOL_t isLinkUpSvcNeeded;
 
+   /* Mgmt Frames TX completion status code */
+   tANI_U32 mgmtTxCompletionStatus;
+
 /*************************************************************
  *  Tx Queues
  */
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index 7303361..3b4672d 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -107,6 +107,7 @@
     tANI_U16    tx_pkt;
     tANI_U16    rx_pkt;
     vos_timer_t     peerIdleTimer;
+    tANI_U8         isTDLSInProgress;
 } hddTdlsPeer_t;
 
 
@@ -118,6 +119,7 @@
     vos_timer_t     peerUpdateTimer;
     tdls_config_params_t threshold_config;
     tANI_S32        discovery_peer_cnt;
+    tANI_U16        connected_peer_count;
     tANI_S8         ap_rssi;
 } tdlsCtx_t;
 
@@ -157,7 +159,7 @@
 
 int wlan_hdd_tdls_reset_peer(u8 *mac);
 
-u8 wlan_hdd_tdlsConnectedPeers(void);
+tANI_U16 wlan_hdd_tdlsConnectedPeers(void);
 
 int wlan_hdd_tdls_get_all_peers(char *buf, int buflen);
 
@@ -165,5 +167,16 @@
 
 void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter);
 
+void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode);
+
+void wlan_hdd_tdls_increment_peer_count(void);
+
+void wlan_hdd_tdls_decrement_peer_count(void);
+
+void wlan_hdd_tdls_check_bmps(hdd_context_t *pHddCtx);
+
+void wlan_hdd_tdls_set_connection_progress(u8* mac, u8 isProgress);
+
+u8 wlan_hdd_tdls_is_progress(u8* mac, u8 skip_self);
 
 #endif // __HDD_TDSL_H
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 20e1a7a..d6e1762 100755
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -1947,7 +1947,7 @@
                  * check if there is available index for this new TDLS STA
                  * since TDLS is setup in BSS, we need to start from +1
                  */
-                for ( staIdx = 1; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+                for ( staIdx = 1; staIdx <= HDD_MAX_NUM_TDLS_STA; staIdx++ )
                 {
                     if (0 == pHddStaCtx->conn_info.staId[staIdx] )
                     {
@@ -1971,7 +1971,7 @@
                         break ;
                     }
                 }
-                if (staIdx < HDD_MAX_NUM_TDLS_STA)
+                if (staIdx <= HDD_MAX_NUM_TDLS_STA)
                 {
                     if (-1 == wlan_hdd_tdls_set_sta_id(pRoamInfo->peerMac, pRoamInfo->staId)) {
                         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
@@ -1987,9 +1987,11 @@
                 }
                 else
                 {
+                    status = eHAL_STATUS_FAILURE;
                     VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                     "no availalbe slot in conn_info. staId %d cannot be stored", pRoamInfo->staId);
                 }
+                pAdapter->tdlsAddStaStatus = status;
             }
             complete(&pAdapter->tdls_add_station_comp);
             break ;
@@ -1997,7 +1999,7 @@
         case eCSR_ROAM_RESULT_DELETE_TDLS_PEER:
         {
             /* 0 staIdx is assigned to AP we dont want to touch that */
-            for ( staIdx = 1; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+            for ( staIdx = 1; staIdx <= HDD_MAX_NUM_TDLS_STA; staIdx++ )
             {
                 if (pRoamInfo->staId == pHddStaCtx->conn_info.staId[staIdx] )
                 {
@@ -2006,12 +2008,14 @@
 
                     wlan_hdd_tdls_reset_peer(pRoamInfo->peerMac);
                     hdd_roamDeregisterTDLSSTA ( pAdapter, pRoamInfo->staId );
+                    wlan_hdd_tdls_decrement_peer_count();
 
                     (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = NULL;
 
                     pHddStaCtx->conn_info.staId[staIdx] = 0 ;
                     vos_mem_zero(&pHddStaCtx->conn_info.peerMacAddress[staIdx],
                                                sizeof(v_MACADDR_t)) ;
+                    wlan_hdd_tdls_check_bmps(WLAN_HDD_GET_CTX( pAdapter ));
                     status = eHAL_STATUS_SUCCESS ;
                     break ;
                 }
@@ -2037,7 +2041,7 @@
         case eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND:
         {
             /* 0 staIdx is assigned to AP we dont want to touch that */
-            for ( staIdx = 1; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+            for ( staIdx = 1; staIdx <= HDD_MAX_NUM_TDLS_STA; staIdx++ )
             {
                 if (pHddStaCtx->conn_info.staId[staIdx])
                 {
@@ -2052,6 +2056,7 @@
                                 pHddStaCtx->conn_info.peerMacAddress[staIdx].bytes[5]) ;
                     wlan_hdd_tdls_reset_peer(pHddStaCtx->conn_info.peerMacAddress[staIdx].bytes);
                     hdd_roamDeregisterTDLSSTA ( pAdapter,  pHddStaCtx->conn_info.staId[staIdx] );
+                    wlan_hdd_tdls_decrement_peer_count();
 
                     (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[staIdx] = NULL;
                     vos_mem_zero(&pHddStaCtx->conn_info.peerMacAddress[staIdx],
@@ -2060,6 +2065,7 @@
 
                     status = eHAL_STATUS_SUCCESS ;
                 }
+                wlan_hdd_tdls_check_bmps(WLAN_HDD_GET_CTX( pAdapter ));
             }
             break ;
         }
@@ -2317,9 +2323,12 @@
 #endif
 #ifdef FEATURE_WLAN_TDLS
         case eCSR_ROAM_TDLS_STATUS_UPDATE:
-              halStatus = hdd_RoamTdlsStatusUpdateHandler( pAdapter, pRoamInfo, 
+            halStatus = hdd_RoamTdlsStatusUpdateHandler( pAdapter, pRoamInfo,
                                                 roamId, roamStatus, roamResult );
             break ;
+        case eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND:
+            wlan_hdd_tdls_mgmt_completion_callback(pAdapter, pRoamInfo->reasonCode);
+            break;
 #endif
         default:
             break;
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 1d04460..2754078 100755
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -5382,7 +5382,7 @@
 
 #ifdef FEATURE_WLAN_TDLS
             /* First clean up the tdls peers if any */
-            for (staIdx = 1 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
+            for (staIdx = 1 ; staIdx <= HDD_MAX_NUM_TDLS_STA; staIdx++)
             {
                 if (pHddStaCtx->conn_info.staId[staIdx])
                 {
@@ -6377,7 +6377,7 @@
 
     if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
     {
-        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, 
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                 "Invalid arguments");
         return -EINVAL;
     }
@@ -6389,23 +6389,45 @@
     }
 
     if (FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
-        FALSE == sme_IsFeatureSupportedByFW(TDLS)) 
+        FALSE == sme_IsFeatureSupportedByFW(TDLS))
     {
-        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, 
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                 "TDLS Disabled in INI OR not enabled in FW.\
                 Cannot process TDLS commands \n");
         return -ENOTSUPP;
     }
+
+    if (wlan_hdd_tdls_is_progress(mac, TRUE))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+            "%s: TDLS setup is ongoing. Request declined.",__func__);
+        return -EPERM;
+    }
+
     /* first to check if we reached to maximum supported TDLS peer.
        TODO: for now, return -EPERM looks working fine,
        but need to check if any other errno fit into this category.*/
-    if (HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
+    if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers())
     {
         VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
                 "%s: TDLS Max peer already connected. Request declined. \n",
                 __func__);
         return -EPERM;
     }
+    else
+    {
+        hddTdlsPeer_t *pTdlsPeer;
+        pTdlsPeer = wlan_hdd_tdls_find_peer(mac);
+        if (pTdlsPeer && (eTDLS_LINK_CONNECTED == pTdlsPeer->link_status))
+        {
+            VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+                    "%s: %02x:%02x:%02x:%02x:%02x:%02x already connected. Request declined.",
+                    __func__, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+            return -EPERM;
+        }
+    }
+
+    wlan_hdd_tdls_set_connection_progress(mac,TRUE);
 
     INIT_COMPLETION(pAdapter->tdls_add_station_comp);
 
@@ -6417,21 +6439,30 @@
 
     if (!status)
     {
-        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+        VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
                 "%s: timeout waiting for tdls add station indication",
                 __func__);
+        wlan_hdd_tdls_set_connection_progress(mac, FALSE);
+        return -EPERM;
+    }
+    if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+                "%s: Add Station is unsucessful", __func__);
+        wlan_hdd_tdls_set_connection_progress(mac, FALSE);
+        return -EPERM;
     }
 
-    return (int) status;
+    return 0;
 }
 #endif
 
 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
           struct net_device *dev, u8 *mac, struct station_parameters *params)
 {
+    int status = -EPERM;
 #ifdef FEATURE_WLAN_TDLS
     u32 mask, set;
-    int status;
     ENTER();
     mask = params->sta_flags_mask;
 
@@ -6446,8 +6477,7 @@
         }
     }
 #endif
-
-    return 0;
+    return status;
 }
 
 
@@ -6605,6 +6635,7 @@
     hdd_context_t *pHddCtx = wiphy_priv(wiphy);
     u8 peerMac[6];
     VOS_STATUS status;
+    int ret = 0;
     int responder;
 
     if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
@@ -6630,10 +6661,20 @@
         return -ENOTSUPP;
     }
 
+    if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
+    {
+        if (wlan_hdd_tdls_is_progress(peer, TRUE))
+        {
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                       "%s: TDLS setup is ongoing. Request declined.", __func__);
+            return -EPERM;
+        }
+    }
+
     if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
         SIR_MAC_TDLS_SETUP_RSP == action_code )
     {
-        if (HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
+        if (HDD_MAX_NUM_TDLS_STA <= wlan_hdd_tdlsConnectedPeers())
         {
             /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
                we return error code at 'add_station()'. Hence we have this
@@ -6648,10 +6689,15 @@
             }
             else
             {
+                /* maximum reached. tweak to send error code to peer and return
+                   error code to supplicant */
                 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
                 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
                         "%s: TDLS Max peer already connected send response status %d \n",
                         __func__,status_code);
+                ret = -EPERM;
+                /* fall through to send setup resp with failure status
+                code */
             }
         }
         else
@@ -6691,14 +6737,43 @@
        }
     }
 
+    if(ret == 0 && /* if failure, don't need to set the progress bit */
+       (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
+        wlan_hdd_tdls_set_connection_progress(peer, TRUE);
+
+    INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
+
     status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
             peerMac, action_code, dialog_token, status_code, (tANI_U8 *)buf, len, responder);
 
-    if (VOS_STATUS_SUCCESS != status) {
+    status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
+                                                        msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
+
+    if (VOS_STATUS_SUCCESS != status)
+    {
+        if(ret == 0 && /* if failure, don't need to set the progress bit */
+           (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
+           wlan_hdd_tdls_set_connection_progress(peer, FALSE);
+
         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
+        return -EPERM;
     }
 
+    if (TRUE != pAdapter->mgmtTxCompletionStatus)
+    {
+        if(ret == 0 && /* if failure, don't need to set the progress bit */
+           (WLAN_IS_TDLS_SETUP_ACTION(action_code)))
+            wlan_hdd_tdls_set_connection_progress(peer, FALSE);
+
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Mgmt Tx Completion failed!", __func__);
+        return -EPERM;
+    }
+
+    if (ret)
+      return ret;
+
     if (SIR_MAC_TDLS_SETUP_RSP == action_code)
     {
         wlan_hdd_tdls_set_responder(peerMac, TRUE);
@@ -6728,7 +6803,7 @@
 
     if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
     {
-        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, 
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                 "Invalid arguments");
         return -EINVAL;
     }
@@ -6782,10 +6857,15 @@
                         return -EINVAL;
                     }
 
-                    /* start TDLS client registration with TL */
-                    status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
-
-                    wlan_hdd_tdls_set_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
+                    if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
+                    {
+                        /* start TDLS client registration with TL */
+                        status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature);
+                        wlan_hdd_tdls_increment_peer_count();
+                        wlan_hdd_tdls_set_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
+                        wlan_hdd_tdls_check_bmps(pHddCtx);
+                        wlan_hdd_tdls_set_connection_progress(peer, FALSE);
+                    }
 
                 } else {
                     hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
@@ -6794,10 +6874,13 @@
             break;
         case NL80211_TDLS_DISABLE_LINK:
             {
-                if(NULL != wlan_hdd_tdls_find_peer(peer))
+                hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(peer);
+
+                if(NULL != curr_peer)
                 {
                     sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
                             pAdapter->sessionId, peer );
+                    curr_peer->isTDLSInProgress = FALSE;
                 }
                 else
                 {
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index f396ed2..c20cf6d 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -1746,6 +1746,7 @@
 #endif
 #ifdef FEATURE_WLAN_TDLS
       init_completion(&pAdapter->tdls_add_station_comp);
+      init_completion(&pAdapter->tdls_mgmt_comp);
 #endif
       init_completion(&pHddCtx->mc_sus_event_var);
       init_completion(&pHddCtx->tx_sus_event_var);
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index 5b07f94..29fb905 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -1487,7 +1487,7 @@
                     hdd_sendActionCnf(pAdapter, TRUE);
                 }
             }
-#ifdef WLAN_FEATURE_TDLS_DEBUG
+#ifdef FEATURE_WLAN_TDLS
             else if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP)
             {
                 wlan_hdd_tdls_set_cap(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6], 1);
@@ -1496,7 +1496,7 @@
             }
 #endif
         }
-#ifdef WLAN_FEATURE_TDLS_DEBUG
+#ifdef FEATURE_WLAN_TDLS
         if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
         {
             actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index db86f80..f222593 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -226,15 +226,22 @@
                     if (curr_peer->tx_pkt >=
                             pHddTdlsCtx->threshold_config.tx_packet_n) {
 
-                    VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
-                    "-> Tput trigger TDLS SETUP: " MAC_ADDRESS_STR,
-                           MAC_ADDR_ARRAY(curr_peer->peerMac));
+                        if (HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers())
+                        {
+
+                            VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "-> Tput trigger TDLS SETUP");
 #ifdef CONFIG_TDLS_IMPLICIT
-                        cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
-                                                   curr_peer->peerMac,
-                                                   NL80211_TDLS_SETUP, FALSE,
-                                                   GFP_KERNEL);
+                            cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
+                                                       curr_peer->peerMac,
+                                                       NL80211_TDLS_SETUP, FALSE,
+                                                       GFP_KERNEL);
 #endif
+                        }
+                        else
+                        {
+                            VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+                                      "%s: TDLS max peer already connected.", __func__);
+                        }
                         goto next_peer;
                     }
 #ifdef WLAN_FEATURE_TDLS_DEBUG
@@ -244,9 +251,7 @@
 #endif
                     if (((tANI_S32)curr_peer->rssi >
                             (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis +
-                                pHddTdlsCtx->ap_rssi)) ||
-                         ((tANI_S32)(curr_peer->rssi >
-                            pHddTdlsCtx->threshold_config.rssi_trigger_threshold))) {
+                                pHddTdlsCtx->ap_rssi))&&(HDD_MAX_NUM_TDLS_STA > wlan_hdd_tdlsConnectedPeers())) {
 
                         VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
                                 "%s: RSSI (peer %d > ap %d + hysteresis %d) triggering to %02x:%02x:%02x:%02x:%02x:%02x ",
@@ -948,28 +953,12 @@
     return discovery_peer_cnt;
 }
 
-/* TODO: Currently I am using conn_info.staId
-   here as per current design but tdls.c shouldn't
-   have touch this.*/
-u8 wlan_hdd_tdlsConnectedPeers(void)
+tANI_U16 wlan_hdd_tdlsConnectedPeers(void)
 {
-    hdd_adapter_t *pAdapter;
-    hdd_station_ctx_t *pHddStaCtx;
-    u8 staIdx;
-    u8 count = 0;
+    if (NULL == pHddTdlsCtx)
+        return 0;
 
-    if (NULL == pHddTdlsCtx) return -1;
-
-    pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
-    pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
-
-    /* 0 staIdx is assigned to AP we dont want to touch that */
-    for (staIdx = 1 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
-    {
-        if (0 != pHddStaCtx->conn_info.staId[staIdx] )
-            count++;
-    }
-    return count;
+    return pHddTdlsCtx->connected_peer_count;
 }
 
 int wlan_hdd_tdls_get_all_peers(char *buf, int buflen)
@@ -1032,6 +1021,8 @@
         pHddTdlsCtx->threshold_config.tx_period_t,
         pHddTdlsCtx->threshold_config.discovery_period_t);
 
+    pHddTdlsCtx->connected_peer_count = 0;
+
     wlan_hdd_tdls_peer_reset_discovery_processed();
 
     vos_timer_start(&pHddTdlsCtx->peerDiscoverTimer,
@@ -1052,3 +1043,101 @@
     wlan_hdd_tdls_timers_stop();
     wlan_hdd_tdls_free_list();
 }
+
+void wlan_hdd_tdls_mgmt_completion_callback(hdd_adapter_t *pAdapter, tANI_U32 statusCode)
+{
+    pAdapter->mgmtTxCompletionStatus = statusCode;
+    VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"%s: Mgmt TX Completion %d",
+               __func__, statusCode);
+    complete(&pAdapter->tdls_mgmt_comp);
+}
+
+void wlan_hdd_tdls_increment_peer_count(void)
+{
+    if (NULL == pHddTdlsCtx) return;
+
+    pHddTdlsCtx->connected_peer_count++;
+}
+
+void wlan_hdd_tdls_decrement_peer_count(void)
+{
+    if (NULL == pHddTdlsCtx) return;
+
+    if (pHddTdlsCtx->connected_peer_count)
+        pHddTdlsCtx->connected_peer_count--;
+}
+
+void wlan_hdd_tdls_check_bmps(hdd_context_t *pHddCtx)
+{
+    if (NULL == pHddTdlsCtx) return;
+
+    if (0 == pHddTdlsCtx->connected_peer_count)
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"No TDLS peer connected so Enable BMPS");
+        hdd_enable_bmps_imps(pHddCtx);
+    }
+    else if (1 == pHddTdlsCtx->connected_peer_count)
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,"TDLS peer connected so Disable BMPS");
+        hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
+    }
+    return;
+}
+
+/* return TRUE if TDLS is ongoing
+ * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE
+ * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if
+   mac is NULL, this argument is ignored, and check for all the peer list.
+ */
+u8 wlan_hdd_tdls_is_progress(u8 *mac, u8 skip_self)
+{
+    int i;
+    struct list_head *head;
+    hddTdlsPeer_t *curr_peer;
+    struct list_head *pos;
+
+    if (NULL == pHddTdlsCtx) return FALSE;
+
+    if (mutex_lock_interruptible(&pHddTdlsCtx->lock))
+    {
+       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                 "%s: unable to lock list", __func__);
+       return FALSE;
+    }
+
+    for (i = 0; i < 256; i++) {
+        head = &pHddTdlsCtx->peer_list[i];
+        list_for_each(pos, head) {
+            curr_peer = list_entry (pos, hddTdlsPeer_t, node);
+            if (skip_self && mac && !memcmp(mac, curr_peer->peerMac, 6)) {
+                continue;
+            }
+            else
+            {
+                if (curr_peer->isTDLSInProgress)
+                {
+                  mutex_unlock(&pHddTdlsCtx->lock);
+                  return TRUE;
+                }
+            }
+        }
+    }
+
+    mutex_unlock(&pHddTdlsCtx->lock);
+    return FALSE;
+}
+
+void wlan_hdd_tdls_set_connection_progress(u8* mac, u8 isProgress)
+{
+    hddTdlsPeer_t *curr_peer;
+
+    if (NULL == pHddTdlsCtx) return;
+
+    curr_peer = wlan_hdd_tdls_find_peer(mac);
+    if (curr_peer == NULL)
+        return;
+
+    curr_peer->isTDLSInProgress = isProgress;
+
+    return;
+}
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index 1cd94d0..9921c53 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -958,8 +958,8 @@
 #ifdef WLAN_FEATURE_P2P
     tSirRemainOnChnReq  *gpLimRemainOnChanReq; //hold remain on chan request in this buf
     vos_list_t  gLimMgmtFrameRegistratinQueue;
-    tANI_U32    actionFrameSessionId;
 #endif
+    tANI_U32    mgmtFrameSessionId;
     tSirBackgroundScanMode gLimBackgroundScanMode;
 
 #if  defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
@@ -1096,7 +1096,7 @@
 #ifdef FEATURE_OEM_DATA_SUPPORT
     tOemDataStruct oemData;
 #endif
-#ifdef FEATURE_WLAN_TDLS
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
     tCsrTdlsCtxStruct tdlsCtx ;
 #endif
 #ifdef ANI_PRODUCT_TYPE_CLIENT
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index b139e7b..382b6e6 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -4244,6 +4244,13 @@
    tANI_U16               length;
    tANI_U8                sessionId;     // Session ID
 } tSirTdlsDelAllPeerInd, *tpSirTdlsDelAllPeerInd;
+typedef struct sSirMgmtTxCompletionInd
+{
+   tANI_U16               messageType;
+   tANI_U16               length;
+   tANI_U8                sessionId;     // Session ID
+   tANI_U32               txCompleteStatus;
+} tSirMgmtTxCompletionInd, *tpSirMgmtTxCompletionInd;
 #endif /* FEATURE_WLAN_TDLS */
 
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index b78af22..6c555a1 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -355,6 +355,7 @@
     eWNI_SME_TDLS_DEL_STA_RSP,
     eWNI_SME_TDLS_DEL_STA_IND,
     eWNI_SME_TDLS_DEL_ALL_PEER_IND,
+    eWNI_SME_MGMT_FRM_TX_COMPLETION_IND,
 #endif
     //NOTE: If you are planning to add more mesages, please make sure that 
     //SIR_LIM_ITC_MSG_TYPES_BEGIN is moved appropriately. It is set as
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index a49a1ba..071b9cb 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -1082,10 +1082,8 @@
         return eSIR_FAILURE;
     }
 #endif
+    pMac->lim.mgmtFrameSessionId = 0xff;
 
-#ifdef WLAN_FEATURE_P2P
-    pMac->lim.actionFrameSessionId = 0xff;
-#endif
     if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pMac->lim.lkPeGlobalLock ) ) )
     {
         PELOGE(limLog(pMac, LOGE, FL("pe lock init failed!\n"));)
diff --git a/CORE/MAC/src/pe/lim/limP2P.c b/CORE/MAC/src/pe/lim/limP2P.c
index f3757d5..638ca96 100644
--- a/CORE/MAC/src/pe/lim/limP2P.c
+++ b/CORE/MAC/src/pe/lim/limP2P.c
@@ -563,7 +563,7 @@
 
     /* If remain on channel timer expired and action frame is pending then 
      * indicaiton confirmation with status failure */
-    if (pMac->lim.actionFrameSessionId != 0xff)
+    if (pMac->lim.mgmtFrameSessionId != 0xff)
     {
        limP2PActionCnf(pMac, 0);
     }
@@ -678,14 +678,14 @@
 
 eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess)
 {
-    if (pMac->lim.actionFrameSessionId != 0xff)
+    if (pMac->lim.mgmtFrameSessionId != 0xff)
     {
         /* The session entry might be invalid(0xff) action confirmation received after
          * remain on channel timer expired */
         limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
                 (txCompleteSuccess ? eSIR_SME_SUCCESS : eSIR_SME_SEND_ACTION_FAIL),
-                pMac->lim.actionFrameSessionId, 0);
-        pMac->lim.actionFrameSessionId = 0xff;
+                pMac->lim.mgmtFrameSessionId, 0);
+        pMac->lim.mgmtFrameSessionId = 0xff;
     }
 
     return eHAL_STATUS_SUCCESS;
@@ -1018,7 +1018,7 @@
            limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, 
                halstatus, pMbMsg->sessionId, 0);
         }
-        pMac->lim.actionFrameSessionId = 0xff;
+        pMac->lim.mgmtFrameSessionId = 0xff;
     }
     else
     {
@@ -1032,13 +1032,13 @@
              limLog( pMac, LOGE, FL("could not send action frame!\n" ));
              limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, halstatus, 
                 pMbMsg->sessionId, 0);
-             pMac->lim.actionFrameSessionId = 0xff;
+             pMac->lim.mgmtFrameSessionId = 0xff;
         }
         else
         {
-             pMac->lim.actionFrameSessionId = pMbMsg->sessionId;
+             pMac->lim.mgmtFrameSessionId = pMbMsg->sessionId;
              limLog( pMac, LOG2, FL("lim.actionFrameSessionId = %lu\n" ), 
-                     pMac->lim.actionFrameSessionId);
+                     pMac->lim.mgmtFrameSessionId);
 
         }
     }
diff --git a/CORE/MAC/src/pe/lim/limProcessTdls.c b/CORE/MAC/src/pe/lim/limProcessTdls.c
index 5a0b86e..920ea4b 100644
--- a/CORE/MAC/src/pe/lim/limProcessTdls.c
+++ b/CORE/MAC/src/pe/lim/limProcessTdls.c
@@ -441,6 +441,29 @@
 }
 
 /*
+ * TX Complete for Management frames
+ */
+ eHalStatus limMgmtTXComplete(tpAniSirGlobal pMac,
+                                   tANI_U32 txCompleteSuccess)
+{
+    tpPESession psessionEntry = NULL ;
+
+    if (0xff != pMac->lim.mgmtFrameSessionId)
+    {
+        psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.mgmtFrameSessionId);
+        if (NULL == psessionEntry)
+        {
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+                      ("%s: sessionID %d is not found"), __func__, pMac->lim.mgmtFrameSessionId);
+            return eHAL_STATUS_FAILURE;
+        }
+        limSendSmeMgmtTXCompletion(pMac, psessionEntry, txCompleteSuccess);
+        pMac->lim.mgmtFrameSessionId = 0xff;
+    }
+    return eHAL_STATUS_SUCCESS;
+}
+
+/*
  * This function can be used for bacst or unicast discovery request
  * We are not differentiating it here, it will all depnds on peer MAC address,
  */
@@ -608,22 +631,26 @@
     LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, ("[TDLS] action %d (%s) -AP-> OTA "),
             SIR_MAC_TDLS_DIS_REQ, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_REQ) ));
 
-    halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+    halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
                             HAL_TXRX_FRM_802_11_DATA,
                             ANI_TXDIR_TODS,
                             7,
-                            limTxComplete, pFrame, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME);
+                            limTxComplete, pFrame,
+                            limMgmtTXComplete,
+                            HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME);
     if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
     {
+        pMac->lim.mgmtFrameSessionId = 0xff;
         limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
         return eSIR_FAILURE;
-
     }
+    pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
 
     return eSIR_SUCCESS;
 
 }
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
 /*
  * Once Discovery response is sent successfully (or failure) on air, now send
  * response to PE and send del STA to HAL.
@@ -632,7 +659,6 @@
                                            tANI_U32 txCompleteSuccess)
 {
     eHalStatus status = eHAL_STATUS_SUCCESS ;
-#ifdef FEATURE_WLAN_TDLS_INTERNAL
     tpDphHashNode pStaDs = NULL ;
     tSirTdlsPeerInfo *peerInfo = 0 ;
 
@@ -703,10 +729,12 @@
         status = eHAL_STATUS_SUCCESS ;
     }
     //pMac->hal.pCBackFnTxComp = NULL ;
-#endif 
     return status ;
 
 }
+#endif
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
 /*
  * Once setup CNF is sent successfully (or failure) on air, now send
  * response to PE and send del STA to HAL.
@@ -715,7 +743,6 @@
                                            tANI_U32 txCompleteSuccess)
 {
     eHalStatus status = eHAL_STATUS_SUCCESS ;
-#ifdef FEATURE_WLAN_TDLS_INTERNAL
     tLimTdlsLinkSetupPeer *peerInfo = 0 ;
     /* find peer by looking into the list by expected state */
     limTdlsFindSetupPeerByState(pMac, 
@@ -762,11 +789,11 @@
         status = eHAL_STATUS_SUCCESS ;
     }
     //pMac->hal.pCBackFnTxComp = NULL ;
-#endif 
     return status ;
-
 }
+#endif
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
 /*
  * Tx Complete for Teardown frame
  */
@@ -774,7 +801,6 @@
                                            tANI_U32 txCompleteSuccess)  
 {
     eHalStatus status = eHAL_STATUS_SUCCESS ;
-#ifdef FEATURE_WLAN_TDLS_INTERNAL
     tpDphHashNode pStaDs = NULL ;
     tLimTdlsLinkSetupPeer *peerInfo = 0 ;
     tpPESession psessionEntry = NULL ;
@@ -883,9 +909,9 @@
     }
 #endif  
     status = eHAL_STATUS_SUCCESS ;
-#endif
     return status ;
 }
+#endif
 
 /*
  * Send TDLS discovery response frame on direct link.
@@ -1074,14 +1100,15 @@
                             ANI_TXDIR_IBSS,
                             0,
                             limTxComplete, pFrame, 
-                            limTdlsDisRspTxComplete,
+                            limMgmtTXComplete,
                             HAL_USE_SELF_STA_REQUESTED_MASK );
     if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
     {
+        pMac->lim.mgmtFrameSessionId = 0xff;
         limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
         return eSIR_FAILURE;
-
     }
+    pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
 
     return eSIR_SUCCESS;
 
@@ -1272,17 +1299,21 @@
     LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, ("[TDLS] action %d (%s) -AP-> OTA"),
             SIR_MAC_TDLS_SETUP_REQ, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_REQ) ));
 
-    halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+    halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
                             HAL_TXRX_FRM_802_11_DATA,
                             ANI_TXDIR_TODS,
                             7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
-                            limTxComplete, pFrame, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME );
+                            limTxComplete, pFrame,
+                            limMgmtTXComplete,
+                            HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME );
+
     if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
     {
+        pMac->lim.mgmtFrameSessionId = 0xff;
         limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
         return eSIR_FAILURE;
-
     }
+    pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
 
     return eSIR_SUCCESS;
 
@@ -1468,14 +1499,16 @@
                             ANI_TXDIR_TODS,
                             7,
                             limTxComplete, pFrame, 
-                            limTdlsTeardownTxComplete,
+                            limMgmtTXComplete,
                             HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME );
     if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
     {
+        pMac->lim.mgmtFrameSessionId = 0xff;
         limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
         return eSIR_FAILURE;
 
     }
+    pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
     return eSIR_SUCCESS;
 
 }
@@ -1664,18 +1697,21 @@
     LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, ("[TDLS] action %d (%s) -AP-> OTA"),
          SIR_MAC_TDLS_SETUP_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_RSP) ));
 
-    halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+    halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
                             HAL_TXRX_FRM_802_11_DATA,
                             ANI_TXDIR_TODS,
                             //ANI_TXDIR_IBSS,
                             7,
-                            limTxComplete, pFrame, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME );
+                            limTxComplete, pFrame,
+                            limMgmtTXComplete,
+                            HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME );
     if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
     {
+        pMac->lim.mgmtFrameSessionId = 0xff;
         limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
         return eSIR_FAILURE;
-
     }
+    pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
 
     return eSIR_SUCCESS;
 
@@ -1890,16 +1926,18 @@
                             ANI_TXDIR_TODS,
                             7,
                             limTxComplete, pFrame, 
-                            limTdlsSetupCnfTxComplete,
+                            limMgmtTXComplete,
                             HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME );
 
 
     if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
     {
+        pMac->lim.mgmtFrameSessionId = 0xff;
         limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
         return eSIR_FAILURE;
 
     }
+    pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
 
     return eSIR_SUCCESS;
 }
diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
index 853872f..dc25d9a 100644
--- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c
@@ -1522,6 +1522,57 @@
     limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
     return;
 }/*** end limSendSmeTDLSDeleteAllPeerInd() ***/
+
+/**
+ * limSendSmeMgmtTXCompletion()
+ *
+ *FUNCTION:
+ * This function is called to send the eWNI_SME_MGMT_FRM_TX_COMPLETION_IND
+ * message to SME.
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ *
+ *NOTE:
+ * NA
+ *
+ * @param  pMac   - Pointer to global MAC structure
+ * @param  psessionEntry - Pointer to the session entry
+ * @param  txCompleteStatus - TX Complete Status of Mgmt Frames
+ * @return None
+ */
+void
+limSendSmeMgmtTXCompletion(tpAniSirGlobal pMac,
+                           tpPESession psessionEntry,
+                           tANI_U32 txCompleteStatus)
+{
+    tSirMsgQ  mmhMsg;
+    tSirMgmtTxCompletionInd  *pSirMgmtTxCompletionInd;
+
+    if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirMgmtTxCompletionInd, sizeof(tSirMgmtTxCompletionInd)))
+    {
+        limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_MGMT_FRM_TX_COMPLETION_IND"));
+        return;
+    }
+
+    //messageType
+    pSirMgmtTxCompletionInd->messageType = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND;
+    pSirMgmtTxCompletionInd->length = sizeof(tSirMgmtTxCompletionInd);
+
+    //sessionId
+    pSirMgmtTxCompletionInd->sessionId = psessionEntry->smeSessionId;
+
+    pSirMgmtTxCompletionInd->txCompleteStatus = txCompleteStatus;
+
+    mmhMsg.type = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND;
+    mmhMsg.bodyptr = pSirMgmtTxCompletionInd;
+    mmhMsg.bodyval = 0;
+
+
+    limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
+    return;
+}/*** end limSendSmeTDLSDeleteAllPeerInd() ***/
 #endif
 
 
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index a7c9ead..9812f4f 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -789,6 +789,9 @@
 tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, 
                                                            tANI_U32 *pMsgBuf);
 void limSendSmeTDLSDeleteAllPeerInd(tpAniSirGlobal pMac, tpPESession psessionEntry);
+void limSendSmeMgmtTXCompletion(tpAniSirGlobal pMac,
+                                tpPESession psessionEntry,
+                                tANI_U32 txCompleteStatus);
 tSirRetStatus limDeleteTDLSPeers(tpAniSirGlobal pMac, tpPESession psessionEntry);
 eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, tpPESession);
 tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac,
diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h
index 87253a6..4f87e38 100644
--- a/CORE/SME/inc/csrApi.h
+++ b/CORE/SME/inc/csrApi.h
@@ -448,6 +448,7 @@
 #endif
 #ifdef FEATURE_WLAN_TDLS
     eCSR_ROAM_TDLS_STATUS_UPDATE,
+    eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND,
 #endif
     eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, //Disaconnect all the clients
     eCSR_ROAM_SEND_P2P_STOP_BSS, //Stopbss triggered from SME due to different 
diff --git a/CORE/SME/inc/csrInternal.h b/CORE/SME/inc/csrInternal.h
index 3d29840..c91b76c 100644
--- a/CORE/SME/inc/csrInternal.h
+++ b/CORE/SME/inc/csrInternal.h
@@ -737,28 +737,25 @@
     tANI_BOOLEAN fIgnore_chan165;
 }tCsrScanStruct;
 
-#ifdef FEATURE_WLAN_TDLS
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
 /*
  * struct to carry TDLS discovery info..
  */
 typedef struct sCsrTdlsContext
 {
-#ifdef FEATURE_WLAN_TDLS_INTERNAL
     tDblLinkList tdlsPotentialPeerList ;
     tANI_U16 tdlsCommonFlag ;
     tANI_U16 tdlsCommonState ;
-#endif
     tANI_U16 tdlsPeerCount ;
 }tCsrTdlsCtxStruct;
 
-#ifdef FEATURE_WLAN_TDLS_INTERNAL
 typedef struct sCsrTdlsPeerLinkInfo
 {
     tListElem tdlsPeerStaLink ;
     tSirTdlsPeerInfo tdlsDisPeerInfo ;
 }tCsrTdlsPeerLinkinfo ;
 #endif
-#endif
+
 
 
 
diff --git a/CORE/SME/inc/smeInside.h b/CORE/SME/inc/smeInside.h
index 494fbb2..b084320 100644
--- a/CORE/SME/inc/smeInside.h
+++ b/CORE/SME/inc/smeInside.h
@@ -291,8 +291,6 @@
 eHalStatus csrTdlsProcessCmd(tpAniSirGlobal pMac,tSmeCmd *pCommand );
 eHalStatus tdlsMsgProcessor(tpAniSirGlobal pMac,v_U16_t msg_type,
                                                            void *pMsgBuf);
-eHalStatus csrTdlsOpen(tHalHandle hHal);
-tANI_BOOLEAN csrTdlsPowerSaveCheck( void* hHal );
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
 eHalStatus csrTdlsDiscoveryReq(tHalHandle hHal, tANI_U8 sessionId,
                                           tCsrTdlsDisRequest *tdlsDisReq);
diff --git a/CORE/SME/src/csr/csrTdlsProcess.c b/CORE/SME/src/csr/csrTdlsProcess.c
index 6c3f88c..ab7c9d4 100644
--- a/CORE/SME/src/csr/csrTdlsProcess.c
+++ b/CORE/SME/src/csr/csrTdlsProcess.c
@@ -82,30 +82,6 @@
 }
 #endif
 
-tANI_BOOLEAN csrTdlsPowerSaveCheck( void *hHal )
-{
-    tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
-    
-    //Avoid entering into BMPS if any TDLS peer is connected
-    return ((pMac->tdlsCtx.tdlsPeerCount > 0) ? FALSE : TRUE) ;
-}
-/*
- * open TDLS context for SME
- */
-eHalStatus csrTdlsOpen(tHalHandle hHal)
-{
-    tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
-#ifdef FEATURE_WLAN_TDLS_INTERNAL
-    csrTdlsInitPeerList(pMac) ;
-#endif
-    pMac->tdlsCtx.tdlsPeerCount = 0;
-    if( eHAL_STATUS_SUCCESS != pmcRegisterPowerSaveCheck (pMac, csrTdlsPowerSaveCheck, pMac) )
-    {
-        smsLog( pMac, LOGE, FL("Register power save check failed\n") );
-    }
-    return eHAL_STATUS_SUCCESS ;
-}
-
 /*
  * common routine to remove TDLS cmd from SME command list..
  * commands are removed after getting reponse from PE.
@@ -828,7 +804,6 @@
             roamInfo.ucastSig = addStaRsp->ucastSig ;
             roamInfo.bcastSig = addStaRsp->bcastSig ;
             roamInfo.statusCode = addStaRsp->statusCode ;
-            pMac->tdlsCtx.tdlsPeerCount++;
             /*
              * register peer with TL, we have to go through HDD as this is
              * the only way to register any STA with TL.
@@ -858,13 +833,6 @@
                          eCSR_ROAM_TDLS_STATUS_UPDATE, 
                                eCSR_ROAM_RESULT_DELETE_TDLS_PEER);
 
-            pMac->tdlsCtx.tdlsPeerCount--;
-            //If all tdls connection is teared down, start bmps timer again.
-            if( pMac->tdlsCtx.tdlsPeerCount == 0 )
-            {
-                pmcStartAutoBmpsTimer(pMac);
-            }
-            /* remove pending eSmeCommandTdlsDiscovery command */
             csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsDelPeer) ;
         }
         break;
@@ -892,10 +860,17 @@
             csrRoamCallCallback(pMac, pSirTdlsDelAllPeerInd->sessionId, &roamInfo, 0,
                                 eCSR_ROAM_TDLS_STATUS_UPDATE,
                                 eCSR_ROAM_RESULT_DELETE_ALL_TDLS_PEER_IND);
-
-            pMac->tdlsCtx.tdlsPeerCount = 0;
             break ;
         }
+        case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND:
+        {
+            tpSirMgmtTxCompletionInd pSirTdlsDelAllPeerInd = (tpSirMgmtTxCompletionInd) pMsgBuf ;
+            tCsrRoamInfo roamInfo = {0} ;
+            roamInfo.reasonCode = pSirTdlsDelAllPeerInd->txCompleteStatus;
+
+            csrRoamCallCallback(pMac, pSirTdlsDelAllPeerInd->sessionId, &roamInfo,
+                                0, eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND, 0);
+        }
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
         case eWNI_SME_TDLS_DISCOVERY_START_RSP:
         {
diff --git a/CORE/SME/src/pmc/pmc.c b/CORE/SME/src/pmc/pmc.c
index b420df6..ff96800 100644
--- a/CORE/SME/src/pmc/pmc.c
+++ b/CORE/SME/src/pmc/pmc.c
@@ -2572,13 +2572,6 @@
         smsLog(pMac, LOG1, FL("Multiple Sessions/GO/SAP sessions . BMPS should not be started"));
         return eANI_BOOLEAN_FALSE;
     }
-#ifdef FEATURE_WLAN_TDLS
-    if( !csrTdlsPowerSaveCheck( pMac ) )
-    {
-        smsLog(pMac, LOGE, FL("TDLS peer(s) connected. Dont start BMPS timer\n"));
-        return eANI_BOOLEAN_FALSE;
-    }
-#endif
     /* Check if there is an Infra session. BMPS is possible only if there is
      * an Infra session */
     if (!csrIsInfraConnected(pMac))
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index f9a3c08..a651b39 100755
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -995,16 +995,6 @@
 #if defined WLAN_FEATURE_P2P
       sme_p2pOpen(pMac);
 #endif
-#ifdef FEATURE_WLAN_TDLS
-      status = csrTdlsOpen(pMac) ;
-      if ( ! HAL_STATUS_SUCCESS( status ) )
-      {
-          smsLog( pMac, LOGE, "Tdlspen open failed during initialization with \
-                  status=%d\n", status );
-          break;
-      }
-#endif
-
 
    }while (0);
 
@@ -1724,6 +1714,7 @@
           case eWNI_SME_TDLS_DEL_STA_RSP:
           case eWNI_SME_TDLS_DEL_STA_IND:
           case eWNI_SME_TDLS_DEL_ALL_PEER_IND:
+          case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND:
 #ifdef FEATURE_WLAN_TDLS_INTERNAL
           case eWNI_SME_TDLS_DISCOVERY_START_RSP:
           case eWNI_SME_TDLS_DISCOVERY_START_IND: