wlan: TDLS Integration from Dev32Sta

Support for TDLS discovery, setup and teardown.
Exit BMPS while in active TDLS link and enable back afterwards.

Change-Id: Ic653c5369cb0b61e04e9a8be5e7f625ab7160365
CR-Fixed: 426223
diff --git a/CORE/MAC/src/pe/lim/limAIDmgmt.c b/CORE/MAC/src/pe/lim/limAIDmgmt.c
index c1e1a4e..0f8afb2 100644
--- a/CORE/MAC/src/pe/lim/limAIDmgmt.c
+++ b/CORE/MAC/src/pe/lim/limAIDmgmt.c
@@ -41,6 +41,11 @@
 #include "limSession.h"
 
 #define LIM_START_AID   1
+#ifdef FEATURE_WLAN_TDLS_INTERNAL 
+#define LIM_START_AID_STA   2
+#else
+#define LIM_START_AID_STA   1
+#endif
 
 
 /**
diff --git a/CORE/MAC/src/pe/lim/limAssocUtils.c b/CORE/MAC/src/pe/lim/limAssocUtils.c
index 214ad8d..c1f1b71 100644
--- a/CORE/MAC/src/pe/lim/limAssocUtils.c
+++ b/CORE/MAC/src/pe/lim/limAssocUtils.c
@@ -2026,8 +2026,12 @@
 
 
     //compute the matching MCS rate set, if peer is 11n capable and self mode is 11n
+#ifdef FEATURE_WLAN_TDLS
+    if(pStaDs->mlmStaContext.htCapability)
+#else
     if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
       (pStaDs->mlmStaContext.htCapability))
+#endif
     {
         val = SIZE_OF_SUPPORTED_MCS_SET;
         if (wlan_cfgGetStr(pMac, WNI_CFG_SUPPORTED_MCS_SET,
@@ -2126,6 +2130,13 @@
         (limGetSystemRole(psessionEntry) == eLIM_STA_IN_IBSS_ROLE) ||
         (limGetSystemRole(psessionEntry) == eLIM_BT_AMP_AP_ROLE) )
         pStaAddr = &pStaDs->staAddr;
+#ifdef FEATURE_WLAN_TDLS
+    /* SystemRole shouldn't be matter if staType is TDLS peer */
+    else if(STA_ENTRY_TDLS_PEER == pStaDs->staType)
+    {
+        pStaAddr = &pStaDs->staAddr ;
+    }
+#endif
     else
         pStaAddr = &staMac;
 
@@ -2170,6 +2181,11 @@
         pAddStaParams->vhtCapable = pStaDs->mlmStaContext.vhtCapability;
 #endif
     }
+#ifdef FEATURE_WLAN_TDLS
+    /* SystemRole shouldn't be matter if staType is TDLS peer */
+    else if(STA_ENTRY_TDLS_PEER == pStaDs->staType)
+        pAddStaParams->htCapable = pStaDs->mlmStaContext.htCapability;
+#endif
     else
     {
         pAddStaParams->htCapable = psessionEntry->htCapability;
@@ -2220,7 +2236,12 @@
     }
 
 #ifdef WLAN_SOFTAP_FEATURE
+#ifdef FEATURE_WLAN_TDLS
+    if(pStaDs->wmeEnabled && \
+       ((eLIM_AP_ROLE == psessionEntry->limSystemRole) || (STA_ENTRY_TDLS_PEER == pStaDs->staType)) )
+#else
     if(pStaDs->wmeEnabled && (eLIM_AP_ROLE == psessionEntry->limSystemRole))
+#endif      
     {
         pAddStaParams->uAPSD = 0;
         /* update UAPSD and send it to LIM to add STA */
@@ -2330,7 +2351,11 @@
     }
 #endif
 
+#ifdef FEATURE_WLAN_TDLS
+    if( ((eLIM_STA_ROLE == GET_LIM_SYSTEM_ROLE(psessionEntry)) && (pStaDs->staType !=  STA_ENTRY_TDLS_PEER)) ||(eLIM_BT_AMP_STA_ROLE == GET_LIM_SYSTEM_ROLE(psessionEntry)) )
+#else
     if( (eLIM_STA_ROLE == GET_LIM_SYSTEM_ROLE(psessionEntry)) ||(eLIM_BT_AMP_STA_ROLE == GET_LIM_SYSTEM_ROLE(psessionEntry)) )
+#endif
       pDelStaParams->staIdx= psessionEntry->staId;
     
     else
diff --git a/CORE/MAC/src/pe/lim/limDebug.h b/CORE/MAC/src/pe/lim/limDebug.h
index d6b49f8..9b8fa17 100644
--- a/CORE/MAC/src/pe/lim/limDebug.h
+++ b/CORE/MAC/src/pe/lim/limDebug.h
@@ -39,4 +39,13 @@
 
 void limLog(tpAniSirGlobal pMac, tANI_U32 loglevel, const char *pString,...) ;
 
+/* define this to show more message in the LIM during TDLS development */
+#define LIM_DEBUG_TDLS
+
+#ifdef LIM_DEBUG_TDLS
+#define LIM_LOG_TDLS(x0) x0
+#else
+#define LIM_LOG_TDLS(x0) 
+#endif
+
 #endif
diff --git a/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
index a125450..0bc4d80 100644
--- a/CORE/MAC/src/pe/lim/limProcessActionFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
@@ -2154,6 +2154,27 @@
               }
            }
             break;
+#ifdef FEATURE_WLAN_TDLS
+           case SIR_MAC_TDLS_DIS_RSP:
+           {
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+               //LIM_LOG_TDLS(printk("Public Action TDLS Discovery RSP ..\n")) ;
+               limProcessTdlsPublicActionFrame(pMac, (tANI_U32*)pRxPacketInfo, psessionEntry) ;
+#else
+               tpSirMacMgmtHdr     pHdr;
+               tANI_U32            frameLen;
+
+               pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
+               frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+               VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, 
+                                    ("Public Action TDLS Discovery RSP ..\n")) ;
+               limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, 
+                  (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), 0, 
+                  WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry);
+#endif
+           }
+               break;
+#endif
 
         default:
             PELOGE(limLog(pMac, LOGE, FL("Unhandled public action frame -- %x \n"), pActionHdr->actionID);)
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 280be96..614e4e7 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -554,11 +554,58 @@
        /*Send disassociation message again*/
        //Dinesh need one more arguement. 
        //limSendDisassocMgmtFrame(pMac, eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON,(tANI_U8 *) pRxPacketInfo);
+    //TODO: verify this   
 #if defined WLAN_FEATURE_P2P
     //This could be a public action frame.
     if( psessionEntry->limSystemRole == eLIM_P2P_DEVICE_ROLE )
         limProcessActionFrameNoSession(pMac, (tANI_U8 *) pRxPacketInfo);
 #endif
+
+#ifdef FEATURE_WLAN_TDLS
+    {
+        tpSirMacDataHdr3a pMacHdr;
+        pMacHdr = WDA_GET_RX_MPDUHEADER3A(pRxPacketInfo);
+
+        if (limIsGroupAddr(pMacHdr->addr2))
+        {
+            PELOG2(limLog(pMac, LOG2, FL("Ignoring A2 Invalid Packet received for MC/BC:\n"));
+                    limPrintMacAddr(pMac, pMacHdr->addr2, LOG2);)
+
+                return;
+        }
+        /* TDLS_hklee: move down here to reject Addr2 == Group (first checking above)
+           and also checking if SystemRole == STA */
+        if (psessionEntry->limSystemRole == eLIM_STA_ROLE)
+        {
+            /* ADD handling of Public Action Frame */
+            LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
+                        ("limHandleUnknownA2IndexFrames: type=0x%x, subtype=0x%x\n"),pMacHdr->fc.type, pMacHdr->fc.subType)); 
+            switch (pMacHdr->fc.type)
+            {
+                case SIR_MAC_MGMT_FRAME:
+                    {
+                        switch (pMacHdr->fc.subType)
+                        {
+                            case SIR_MAC_MGMT_ACTION:
+                                {
+                                    limProcessActionFrame(pMac, pRxPacketInfo, psessionEntry) ;
+                                    break ;
+                                }
+                            default:
+                                {
+                                    break ;
+                                }
+                        }
+                    }
+                default:
+                    {
+                        break ;
+                    }
+            }
+        }
+    }
+#endif
+
 #endif
 
     return;
@@ -951,9 +998,30 @@
 
         }
         break;
-#ifdef FEATURE_WLAN_CCX
         case SIR_MAC_DATA_FRAME:
         {
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+            /*
+             * if we reach here, following cases are possible. 
+             * Possible cases: a) if frame translation is disabled.
+             *                 b) Some frame with ADRR2 filter enabled may come
+             *                    here.
+             */ 
+            tANI_U8 *dataOffset = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
+            tANI_U8 *rfc1042Hdr = (tANI_U8 *)(dataOffset + RFC1042_HDR_LENGTH) ;
+            tANI_U16 ethType = GET_BE16(rfc1042Hdr) ;
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                                ("TDLS frame with 80211 Header\n")) ;
+            if(ETH_TYPE_89_0d == ethType)
+            {
+                tANI_U8 payloadType = (rfc1042Hdr + ETH_TYPE_LEN)[0] ;
+                if(PAYLOAD_TYPE_TDLS == payloadType)
+                {
+                    limProcessTdlsFrame(pMac, (tANI_U32*)pRxPacketInfo) ;
+                }
+            }     
+#endif
+#ifdef FEATURE_WLAN_CCX
              /* We accept data frame (IAPP frame) only if Session is
               * present and ccx connection is established on that
               * session
@@ -961,9 +1029,9 @@
              if (psessionEntry && psessionEntry->isCCXconnection) {
                  limProcessIappFrame(pMac, pRxPacketInfo, psessionEntry);
              }
+#endif
         }
         break;
-#endif
         default:
             // Received frame of type 'reserved'
             break;
@@ -1262,6 +1330,9 @@
                 vos_pkt_t  *pVosPkt;
                 VOS_STATUS  vosStatus;
                 tSirMsgQ    limMsgNew;
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+                tANI_U32    *pBD = NULL ;
+#endif 
 
                 /* The original limMsg which we were deferring have the 
                  * bodyPointer point to 'BD' instead of 'Vos pkt'. If we don't make a copy
@@ -1281,6 +1352,24 @@
                     break;
 
                 }
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+                /* 
+                 * TDLS frames comes as translated frames as well as
+                 * MAC 802.11 data frames..
+                 */
+                limGetBDfromRxPacket(pMac, limMsgNew.bodyptr, &pBD);
+                if(0 != WDA_GET_RX_FT_DONE(pBD))
+                {
+                    /*
+                     * TODO: check for scanning state and set deferMesg flag
+                     * accordingly..
+                     */
+                    deferMsg = false ;
+
+                    limProcessTdlsFrame(pMac, pBD) ;
+                }
+                else
+#endif
                 limHandle80211Frames(pMac, &limMsgNew, &deferMsg);
 
                 if ( deferMsg == true )
@@ -1325,6 +1414,16 @@
 #ifdef FEATURE_OEM_DATA_SUPPORT
         case eWNI_SME_OEM_DATA_REQ:
 #endif
+#ifdef FEATURE_WLAN_TDLS
+        case eWNI_SME_TDLS_SEND_MGMT_REQ:
+        case eWNI_SME_TDLS_ADD_STA_REQ:
+        case eWNI_SME_TDLS_DEL_STA_REQ:
+#endif
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+        case eWNI_SME_TDLS_DISCOVERY_START_REQ:
+        case eWNI_SME_TDLS_LINK_START_REQ:
+        case eWNI_SME_TDLS_TEARDOWN_REQ:
+#endif
             // These messages are from HDD
             limProcessNormalHddMsg(pMac, limMsg, true);  //need to response to hdd
             break;
@@ -1802,6 +1901,92 @@
 
 #endif
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+        /*
+         * Here discovery timer expires, now we can go ahead and collect all
+         * the dicovery responses PE has process till now and send this
+         * responses to SME..
+         */
+        case SIR_LIM_TDLS_DISCOVERY_RSP_WAIT:
+        {
+            //fetch the sessionEntry based on the sessionId
+            tpPESession psessionEntry = peFindSessionBySessionId(pMac, 
+                         pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId) ;
+            if(NULL == psessionEntry) 
+            {
+              limLog(pMac, LOGP,FL("Session Does not exist for given sessionID %d\n"), pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId);
+              return;
+            }
+            
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, 
+                                ("Discovery Rsp timer expires \n")) ;
+#if 0 // TDLS_hklee: D13 no need to open Addr2 unknown data packet 
+            /* restore RXP filters */
+            limSetLinkState(pMac, eSIR_LINK_FINISH_TDLS_DISCOVERY_STATE,
+                                            psessionEntry->bssId) ;
+#endif
+            limSendSmeTdlsDisRsp(pMac, eSIR_SUCCESS, 
+                                eWNI_SME_TDLS_DISCOVERY_START_RSP) ;
+            break ;
+        }
+
+        /*
+         * we initiated link setup and did not receive TDLS setup rsp
+         * from TDLS peer STA, send failure RSP to SME.
+         */
+        case SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT:
+        {
+            tANI_U8 *peerMac = (tANI_U8 *)limMsg->bodyval ;
+            tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+ 
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+                                ("TDLS setup rsp timer expires \n")) ;
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                       ("TDLS setup rsp timer expires for peer:\n")) ;
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                    ("%02X, %02X, %02X,%02X, %02X, %02X\n"), 
+                                    peerMac[0],
+                                    peerMac[1],
+                                    peerMac[2],
+                                    peerMac[3],
+                                    peerMac[4],
+                                    peerMac[5]);
+
+            limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
+            if(NULL != setupPeer)
+            {
+                limTdlsDelLinkPeer( pMac, peerMac) ;
+            }
+
+            limSendSmeTdlsLinkStartRsp(pMac, eSIR_FAILURE, peerMac, 
+                                            eWNI_SME_TDLS_LINK_START_RSP) ;
+            break ;
+        }
+        case SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT:
+        {
+            tANI_U8 *peerMac = (tANI_U8 *)limMsg->bodyval ;
+            tLimTdlsLinkSetupPeer *setupPeer = NULL ;
+
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
+                                ("TDLS setup CNF timer expires \n")) ;
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                      ("TDLS setup CNF timer expires for peer:\n")) ;
+            VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                         ("%02X, %02X, %02X,%02X, %02X, %02X\n"), 
+                                    peerMac[0],
+                                    peerMac[1],
+                                    peerMac[2],
+                                    peerMac[3],
+                                    peerMac[4],
+                                    peerMac[5]);
+            limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
+            if(NULL != setupPeer)
+            {
+                limTdlsDelLinkPeer( pMac, peerMac) ;
+            }
+            break ;
+        }
+#endif   /* FEATURE_WLAN_TDLS TIMER */
         case WDA_ADD_BSS_RSP:
             limProcessMlmAddBssRsp( pMac, limMsg );
             break;
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
index 16eadfb..857710d 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c
@@ -3264,6 +3264,9 @@
     switch( psessionEntry->limSystemRole ) {
     case eLIM_STA_ROLE:
     case eLIM_BT_AMP_STA_ROLE:
+      //In case of TDLS, peerMac address need not be BssId. Skip this check
+      //if TDLS is enabled.
+#ifndef FEATURE_WLAN_TDLS
         if((!limIsAddrBC( pMlmSetKeysReq->peerMacAddr ) ) &&
           (!palEqualMemory( pMac->hHdd,pMlmSetKeysReq->peerMacAddr,
                          currentBssId, sizeof(tSirMacAddr))) ){
@@ -3274,6 +3277,7 @@
         mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
         goto end;
       }
+#endif
       // Fall thru' & 'Plumb' keys below
       break;
     case eLIM_STA_IN_IBSS_ROLE:
diff --git a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
index 84178cd..3023a5f 100644
--- a/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c
@@ -3096,6 +3096,12 @@
                 PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station\n"));)
                 mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED;
             }
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+            else {
+               /* initialize TDLS peer related data */
+               limInitTdlsData(pMac,psessionEntry);
+            }
+#endif            
         }
     }
     else
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index 813b6a6..3c36c37 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -4853,6 +4853,310 @@
 } /*** end __limProcessSmeRegisterMgmtFrameReq() ***/
 #endif
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/*
+ * Process Discovery request recieved from SME and transmit to AP.
+ */
+static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, 
+                                                           tANI_U32 *pMsgBuf)
+{
+    /* get all discovery request parameters */
+    tSirTdlsDisReq *disReq = (tSirTdlsDisReq *) pMsgBuf ;
+    tpPESession psessionEntry;
+    tANI_U8      sessionId;
+
+    VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                                  ("Discovery Req Recieved\n")) ;
+
+    if((psessionEntry = peFindSessionByBssid(pMac, disReq->bssid, &sessionId)) 
+                                                                        == NULL)
+    {
+         VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                    "PE Session does not exist for given sme sessionId %d\n", 
+                                                            disReq->sessionId);
+         goto lim_tdls_dis_start_error;
+    }
+    
+    /* check if we are in proper state to work as TDLS client */ 
+    if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
+    {
+        VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                         "dis req received in wrong system Role %d\n", 
+                                             psessionEntry->limSystemRole);
+        goto lim_tdls_dis_start_error;
+    }
+
+    /*
+     * if we are still good, go ahead and check if we are in proper state to
+     * do TDLS discovery procedure.
+     */
+     if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+                (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
+     {
+     
+         limLog(pMac, LOGE, "dis req received in invalid LIMsme \
+                               state (%d)\n", psessionEntry->limSmeState);
+         goto lim_tdls_dis_start_error;
+     }
+    
+    /*
+     * if we are still good, go ahead and transmit TDLS discovery request,
+     * and save Dis Req info for future reference.
+     */
+
+#if 0 // TDLS_hklee: D13 no need to open Addr2 unknown data packet 
+    /* 
+     * send message to HAL to set RXP filters to receieve frame on 
+     * direct link..
+     */
+     //limSetLinkState(pMac, eSIR_LINK_TDLS_DISCOVERY_STATE, 
+     //                                    psessionEntry->bssId) ;
+#endif
+
+     /* save dis request message for matching dialog token */
+     palCopyMemory( pMac->hHdd, (tANI_U8 *) &pMac->lim.gLimTdlsDisReq, 
+                           (tANI_U8 *) disReq, sizeof(tSirTdlsDisReq));
+
+     VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                             "Transmit Discovery Request Frame\n") ;
+     /* format TDLS discovery request frame and transmit it */
+     limSendTdlsDisReqFrame(pMac, disReq->peerMac, disReq->dialog, 
+                                                       psessionEntry) ;
+
+     /* prepare for response */
+     pMac->lim.gLimTdlsDisStaCount = 0 ;
+     pMac->lim.gLimTdlsDisResultList = NULL ;
+
+    /*
+     * start TDLS discovery request timer to wait for discovery responses
+     * from all TDLS enabled clients in BSS.
+     */
+
+    VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                                ("Start Discovery request Timeout Timer\n")) ;
+    MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, 
+                                             eLIM_TDLS_DISCOVERY_RSP_WAIT));
+
+    /* assign appropriate sessionId to the timer object */
+    pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId = 
+                                            psessionEntry->peSessionId;
+
+    if (tx_timer_activate(&pMac->lim.limTimers.gLimTdlsDisRspWaitTimer)
+                                                               != TX_SUCCESS)
+    {
+        limLog(pMac, LOGP, FL("TDLS discovery response timer \
+                                                  activation failed!\n"));
+        goto lim_tdls_dis_start_error;
+    }
+    /* 
+     * when timer expired, eWNI_SME_TDLS_DISCOVERY_START_RSP is sent 
+     *  back to SME 
+     */
+    return (eSIR_SUCCESS) ; 
+lim_tdls_dis_start_error:
+   /* in error case, PE has to sent the response SME immediately with error code */
+   limSendSmeTdlsDisRsp(pMac, eSIR_FAILURE, 
+                                     eWNI_SME_TDLS_DISCOVERY_START_RSP);
+   return eSIR_FAILURE;
+}
+/*
+ * Process link start request recieved from SME and transmit to AP.
+ */
+eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+    /* get all discovery request parameters */
+    tSirTdlsSetupReq *setupReq = (tSirTdlsSetupReq *) pMsgBuf ;
+    tLimTdlsLinkSetupInfo *linkSetupInfo; 
+    //tLimTdlsLinkSetupPeer *setupPeer;
+    tpPESession psessionEntry;
+    tANI_U8      sessionId;
+    eHalStatus   status;
+    
+    if((psessionEntry = peFindSessionByBssid(pMac, 
+                                    setupReq->bssid, &sessionId)) == NULL)
+    {
+         VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                     "PE Session does not exist for given sme sessionId %d\n", 
+                                                          setupReq->sessionId);
+         goto lim_tdls_link_start_error;
+    }
+    
+    /* check if we are in proper state to work as TDLS client */ 
+    if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
+    {
+        VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                      "TDLS link setup req received in wrong system Role %d\n",
+                                                psessionEntry->limSystemRole);
+        goto lim_tdls_link_start_error;
+    }
+
+    /*
+     * if we are still good, go ahead and check if we are in proper state to
+     * do TDLS setup procedure.
+     */
+    if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+            (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
+    {
+        limLog(pMac, LOGE, "Setup request in invalid LIMsme \
+                              state (%d)\n", pMac->lim.gLimSmeState);
+        goto lim_tdls_link_start_error;
+    }
+    
+    /*
+     * Now, go ahead and transmit TDLS discovery request, and save setup Req 
+     * info for future reference.
+     */
+     /* create node for Link setup */
+    linkSetupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
+    //setupPeer = NULL ;
+   
+    status = limTdlsPrepareSetupReqFrame(pMac, linkSetupInfo, setupReq->dialog, 
+                                          setupReq->peerMac, psessionEntry) ; 
+    if(eHAL_STATUS_SUCCESS == status)
+    /* in case of success, eWNI_SME_TDLS_LINK_START_RSP is sent back to SME later when 
+    TDLS setup cnf TX complete is successful. */
+        return eSIR_SUCCESS;
+#if 0
+
+    /*
+    * we allocate the TDLS setup Peer Memory here, we will free'd this
+    * memory after teardown, if the link is sucessfully setup or
+    * free this memory if any timeout is happen in link setup procedure
+    */
+    if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+                  (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer )))
+    {
+     limLog( pMac, LOGP, 
+                  FL( "Unable to allocate memory during ADD_STA\n" ));
+     VOS_ASSERT(0) ;
+     return eSIR_MEM_ALLOC_FAILED;
+    }
+    setupPeer->dialog = setupReq->dialog ;
+    setupPeer->tdls_prev_link_state =  setupPeer->tdls_link_state ;
+    setupPeer->tdls_link_state = TDLS_LINK_SETUP_START_STATE ;
+    /* TDLS_sessionize: remember sessionId for future */
+    setupPeer->tdls_sessionId = psessionEntry->peSessionId;
+    setupPeer->tdls_bIsResponder = 1;
+
+    /* 
+    * we only populate peer MAC, so it can assit us to find the
+    * TDLS peer after response/or after response timeout
+    */
+    palCopyMemory(pMac->hHdd, setupPeer->peerMac, setupReq->peerMac,
+                                              sizeof(tSirMacAddr)) ;
+    /* format TDLS discovery request frame and transmit it */
+    limSendTdlsLinkSetupReqFrame(pMac, setupReq->peerMac, 
+                                       setupReq->dialog, psessionEntry, NULL, 0) ;
+
+    limStartTdlsTimer(pMac, psessionEntry->peSessionId, 
+                        &setupPeer->gLimTdlsLinkSetupRspTimeoutTimer,
+     (tANI_U32)setupPeer->peerMac, WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT,
+                            SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT) ;
+    /* update setup peer list */
+    setupPeer->next = linkSetupInfo->tdlsLinkSetupList ;
+    linkSetupInfo->tdlsLinkSetupList = setupPeer ;
+    /* in case of success, eWNI_SME_TDLS_LINK_START_RSP is sent back to SME later when 
+    TDLS setup cnf TX complete is successful. --> see limTdlsSetupCnfTxComplete() */
+    return eSIR_SUCCESS ; 
+#endif
+lim_tdls_link_start_error:    
+    /* in case of error, return immediately to SME */
+    limSendSmeTdlsLinkStartRsp(pMac, eSIR_FAILURE, setupReq->peerMac, 
+                                         eWNI_SME_TDLS_LINK_START_RSP);
+    return eSIR_FAILURE ;
+}
+
+/*
+ * Process link teardown request recieved from SME and transmit to AP.
+ */
+eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+    /* get all discovery request parameters */
+    tSirTdlsTeardownReq *teardownReq = (tSirTdlsTeardownReq *) pMsgBuf ;
+    tLimTdlsLinkSetupPeer *setupPeer;
+    tpPESession psessionEntry;
+    tANI_U8      sessionId;
+    
+    if((psessionEntry = peFindSessionByBssid(pMac, teardownReq->bssid, &sessionId)) == NULL)
+    {
+         VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                        "PE Session does not exist for given sme sessionId %d\n", teardownReq->sessionId);
+         goto lim_tdls_teardown_req_error;
+    }
+    
+    /* check if we are in proper state to work as TDLS client */ 
+    if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
+    {
+        VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, 
+                          "TDLS teardown req received in wrong system Role %d\n", psessionEntry->limSystemRole);
+        goto lim_tdls_teardown_req_error;
+    }
+
+    /*
+     * if we are still good, go ahead and check if we are in proper state to
+     * do TDLS setup procedure.
+     */
+    if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+            (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
+    {
+        limLog(pMac, LOGE, "TDLS teardwon req received in invalid LIMsme \
+                               state (%d)\n", psessionEntry->limSmeState);
+        goto lim_tdls_teardown_req_error;
+    }
+    
+    VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+            "Teardown for peer = %02x,%02x,%02x,%02x,%02x,%02x\n",
+                                             teardownReq->peerMac[0],
+                                             teardownReq->peerMac[1],
+                                             teardownReq->peerMac[2],
+                                             teardownReq->peerMac[3],
+                                             teardownReq->peerMac[4],
+                                             teardownReq->peerMac[5]) ;
+    /*
+     * Now, go ahead and transmit TDLS teardown request, and save teardown info
+     * info for future reference.
+     */
+     /* Verify if this link is setup */
+    setupPeer = NULL ;
+    limTdlsFindLinkPeer(pMac, teardownReq->peerMac, &setupPeer);
+    if(NULL == setupPeer)
+    {
+        VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                                ("invalid Peer on teardown \n")) ;
+        goto lim_tdls_teardown_req_error;
+    }
+
+
+    (setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
+    (setupPeer)->tdls_link_state = TDLS_LINK_TEARDOWN_START_STATE ;
+    /* TDLS_sessionize: check sessionId in case */
+    if((setupPeer)->tdls_sessionId != psessionEntry->peSessionId) 
+    {
+        limLog(pMac, LOGE, "TDLS teardown req; stored sessionId (%d) not matched from peSessionId (%d)\n", \
+            (setupPeer)->tdls_sessionId, psessionEntry->limSmeState);
+        (setupPeer)->tdls_sessionId = psessionEntry->peSessionId;
+    }
+    
+    /* format TDLS teardown request frame and transmit it */
+    if(eSIR_SUCCESS != limSendTdlsTeardownFrame(pMac, teardownReq->peerMac, 
+                                eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON, psessionEntry, NULL, 0 ))
+    {
+        VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
+                                ("couldn't send teardown frame \n")) ;
+        goto lim_tdls_teardown_req_error;
+    }
+    /* in case of success, eWNI_SME_TDLS_TEARDOWN_RSP is sent back to SME later when 
+    TDLS teardown TX complete is successful. --> see limTdlsTeardownTxComplete() */
+    return eSIR_SUCCESS;
+lim_tdls_teardown_req_error:    
+    /* in case of error, return immediately to SME */
+    limSendSmeTdlsTeardownRsp(pMac, eSIR_FAILURE, teardownReq->peerMac, 
+                                     eWNI_SME_TDLS_TEARDOWN_RSP);
+    return eSIR_FAILURE;
+}
+
+
+#endif
 
 /**
  * limProcessSmeReqMessages()
@@ -5091,7 +5395,28 @@
             __limProcessSmeRegisterMgmtFrameReq( pMac, pMsgBuf );
             break;
 #endif        
-            
+#ifdef FEATURE_WLAN_TDLS
+        case eWNI_SME_TDLS_SEND_MGMT_REQ:
+            limProcessSmeTdlsMgmtSendReq(pMac, pMsgBuf);
+            break;
+        case eWNI_SME_TDLS_ADD_STA_REQ:
+            limProcessSmeTdlsAddStaReq(pMac, pMsgBuf);
+            break;
+        case eWNI_SME_TDLS_DEL_STA_REQ:
+            limProcessSmeTdlsDelStaReq(pMac, pMsgBuf);
+            break;
+#endif
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+        case eWNI_SME_TDLS_DISCOVERY_START_REQ:
+            limProcessSmeDisStartReq(pMac,  pMsgBuf);
+            break ;
+        case eWNI_SME_TDLS_LINK_START_REQ:
+            limProcessSmeLinkStartReq(pMac,  pMsgBuf);
+            break ;
+        case eWNI_SME_TDLS_TEARDOWN_REQ:
+            limProcessSmeTeardownReq(pMac,  pMsgBuf);
+            break ;
+#endif
 
         default:
             vos_mem_free((v_VOID_t*)pMsg->bodyptr);
diff --git a/CORE/MAC/src/pe/lim/limSendMessages.c b/CORE/MAC/src/pe/lim/limSendMessages.c
index a6c7382..1f16784 100644
--- a/CORE/MAC/src/pe/lim/limSendMessages.c
+++ b/CORE/MAC/src/pe/lim/limSendMessages.c
@@ -705,3 +705,107 @@
     return retCode;
 }
 #endif 
+
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+/** ---------------------------------------------------------
+\fn      limSendTdlsLinkEstablish
+\brief   LIM sends a message to HAL to set tdls direct link
+\param   tpAniSirGlobal  pMac
+\param   
+\return  None
+  -----------------------------------------------------------*/
+tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerResponder, tANI_U8 linkIdenOffset, 
+                tANI_U8 ptiBufStatusOffset, tANI_U8 ptiFrameLen, tANI_U8 *ptiFrame, tANI_U8 *extCapability)
+{
+    tSirMsgQ msgQ;
+    tSirRetStatus retCode;
+    tpSirTdlsLinkEstablishInd pTdlsLinkEstablish = NULL;
+
+    // Allocate memory.
+    if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+          (void **) &pTdlsLinkEstablish,
+          sizeof(tSirTdlsLinkEstablishInd)))
+    {
+        limLog( pMac, LOGP,
+        FL( "Unable to PAL allocate memory while sending Tdls Link Establish \n" ));
+
+        retCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+        return retCode;
+    }
+
+    palZeroMemory( pMac->hHdd, (tANI_U8 *) pTdlsLinkEstablish, sizeof(tSirTdlsLinkEstablishInd));
+
+    pTdlsLinkEstablish->bIsResponder = !!bIsPeerResponder; 
+    pTdlsLinkEstablish->linkIdenOffset = linkIdenOffset;
+    pTdlsLinkEstablish->ptiBufStatusOffset = ptiBufStatusOffset;
+    pTdlsLinkEstablish->ptiTemplateLen = ptiFrameLen;
+    /* Copy ptiFrame template */
+    palCopyMemory( pMac->hHdd, pTdlsLinkEstablish->ptiTemplateBuf, ptiFrame, ptiFrameLen);
+    /* Copy extended capabilities */
+    palCopyMemory( pMac->hHdd, (tANI_U8 *) pTdlsLinkEstablish->extCapability,  extCapability, sizeof(pTdlsLinkEstablish->extCapability));
+
+    msgQ.type = SIR_HAL_TDLS_LINK_ESTABLISH;
+    msgQ.reserved = 0;
+    msgQ.bodyptr = pTdlsLinkEstablish;
+    msgQ.bodyval = 0;
+    
+    MTRACE(macTraceMsgTx(pMac, 0, msgQ.type));
+
+    retCode = (tANI_U32)wdaPostCtrlMsg(pMac, &msgQ);
+    if (retCode != eSIR_SUCCESS)
+    {
+        palFreeMemory(pMac, (void*)pTdlsLinkEstablish);
+        limLog(pMac, LOGP, FL("Posting tdls link establish %d failed, reason = %x \n"), retCode);
+    }
+
+    return retCode;
+}
+
+/** ---------------------------------------------------------
+\fn      limSendTdlsLinkTeardown
+\brief   LIM sends a message to HAL to indicate tdls direct link is teardowned
+\param   tpAniSirGlobal  pMac
+\param   
+\return  None
+  -----------------------------------------------------------*/
+tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId)
+{
+    tSirMsgQ msgQ;
+    tSirRetStatus retCode;
+    tpSirTdlsLinkTeardownInd pTdlsLinkTeardown = NULL;
+
+    // Allocate memory.
+    if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
+          (void **) &pTdlsLinkTeardown,
+          sizeof(tSirTdlsLinkTeardownInd)))
+    {
+        limLog( pMac, LOGP,
+        FL( "Unable to PAL allocate memory while sending Tdls Link Teardown \n" ));
+
+        retCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+        return retCode;
+    }
+
+    palZeroMemory( pMac->hHdd, (tANI_U8 *) pTdlsLinkTeardown, sizeof(tSirTdlsLinkTeardownInd));
+
+    pTdlsLinkTeardown->staId = staId;
+
+    msgQ.type = SIR_HAL_TDLS_LINK_TEARDOWN;
+    msgQ.reserved = 0;
+    msgQ.bodyptr = pTdlsLinkTeardown;
+    msgQ.bodyval = 0;
+    
+    MTRACE(macTraceMsgTx(pMac, 0, msgQ.type));
+
+    retCode = (tANI_U32)wdaPostCtrlMsg(pMac, &msgQ);
+    if (retCode != eSIR_SUCCESS)
+    {
+        palFreeMemory(pMac, (void*)pTdlsLinkTeardown);
+        limLog(pMac, LOGP, FL("Posting tdls link teardown %d failed, reason = %x \n"), retCode);
+    }
+
+    return retCode;
+}
+
+#endif
+
diff --git a/CORE/MAC/src/pe/lim/limSendMessages.h b/CORE/MAC/src/pe/lim/limSendMessages.h
index f3ac061..ebbb35f 100644
--- a/CORE/MAC/src/pe/lim/limSendMessages.h
+++ b/CORE/MAC/src/pe/lim/limSendMessages.h
@@ -84,4 +84,10 @@
 
 tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac, tpPESession psessionEntry);
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerResponder, tANI_U8 linkIdenOffset, \
+                tANI_U8 ptiBufStatusOffset, tANI_U8 ptiFrameLen, tANI_U8 *ptiFrame, tANI_U8 *extCapability);
+tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId);
+#endif
+
 #endif
diff --git a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h
index b777e38..761f63c 100644
--- a/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h
+++ b/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h
@@ -96,6 +96,11 @@
 void limSendSmePreChannelSwitchInd(tpAniSirGlobal pMac);
 void limSendSmePostChannelSwitchInd(tpAniSirGlobal pMac);
 void limSendSmeMaxAssocExceededNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tANI_U8 smesessionId);
+#ifdef FEATURE_WLAN_TDLS
+void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tANI_U16 msgType);
+void limSendSmeTdlsLinkStartRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tSirMacAddr peerMac, tANI_U16 msgType);
+void limSendSmeTdlsTeardownRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tSirMacAddr peerMac, tANI_U16 msgType);
+#endif
 
 #endif /* __LIM_SEND_SME_RSP_H */
 
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index 0dbf0fd..f9077fc 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -466,6 +466,39 @@
             goto err_timer;
         }
 #endif
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+        /* 
+         * create TDLS timers..
+         * a) TDLS discovery response timer.
+         */        
+
+        if (wlan_cfgGetInt(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT,
+                                            &cfgValue) != eSIR_SUCCESS)
+        {
+            /*
+             * Could not get discovery response Timeout value
+             * from CFG. Log error.
+             */
+            limLog(pMac, LOGP,
+               FL("could not retrieve ReassocFailureTimeout value\n"));
+        }
+        cfgValue = SYS_MS_TO_TICKS(cfgValue);
+
+        /* 
+         * create TDLS discovery response wait timer and activate it later
+         */
+        if (tx_timer_create(&pMac->lim.limTimers.gLimTdlsDisRspWaitTimer,
+                            "TDLS discovery response WAIT",
+                            limTimerHandler,
+                            SIR_LIM_TDLS_DISCOVERY_RSP_WAIT,
+                            cfgValue, 0,
+                            TX_NO_ACTIVATE) != TX_SUCCESS)
+        {
+            limLog(pMac, LOGP,
+               FL("could not create TDLS discovery response wait timer\n"));
+        goto err_timer;
+        }
+#endif
     }
 
 
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.h b/CORE/MAC/src/pe/lim/limTimerUtils.h
index b0b990d..5a98d72 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.h
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.h
@@ -75,6 +75,11 @@
 #ifdef FEATURE_WLAN_CCX
     eLIM_TSM_TIMER,
 #endif
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+    eLIM_TDLS_DISCOVERY_RSP_WAIT,
+    eLIM_TDLS_LINK_SETUP_RSP_TIMEOUT,
+    eLIM_TDLS_LINK_SETUP_CNF_TIMEOUT,        
+#endif
     eLIM_DISASSOC_ACK_TIMER,
     eLIM_DEAUTH_ACK_TIMER,
     eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER,
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index cad1f80..4c43899 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -749,6 +749,31 @@
 void limProcessIappFrame(tpAniSirGlobal, tANI_U8 *,tpPESession);
 #endif
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, 
+           tSirMacAddr peer_mac, tANI_U8 dialog, tpPESession psessionEntry);
+tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac,
+           tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry,
+           tANI_U8* addIe, tANI_U16 len); 
+
+eHalStatus limTdlsPrepareSetupReqFrame(tpAniSirGlobal pMac,
+                              tLimTdlsLinkSetupInfo *linkSetupInfo,
+                                 tANI_U8 dialog, tSirMacAddr peerMac,
+                                                 tpPESession psessionEntry);
+#endif
+#ifdef FEATURE_WLAN_TDLS
+tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, 
+                                                           tANI_U32 *pMsgBuf);
+tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, 
+                                                           tANI_U32 *pMsgBuf);
+tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, 
+                                                           tANI_U32 *pMsgBuf);
+eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, tpPESession);
+tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac,
+           tSirMacAddr peerMac, tANI_U16 reason, tpPESession psessionEntry,
+           tANI_U8 *addIe, tANI_U16 addIeLen); 
+#endif
+
 // Algorithms & Link Monitoring related functions
 tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal);
 void limTriggerBackgroundScan(tpAniSirGlobal);
@@ -1083,6 +1108,26 @@
 void limAbortRemainOnChan(tpAniSirGlobal pMac);
 tSirRetStatus __limProcessSmeNoAUpdate(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf);
 #endif
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+void limProcessTdlsFrame(tpAniSirGlobal, tANI_U32 *);
+void limInitTdlsData(tpAniSirGlobal, tpPESession);
+void limProcessTdlsPublicActionFrame(tpAniSirGlobal pMac, tANI_U32 *pBd, 
+                                                               tpPESession) ;
+#ifdef FEATURE_WLAN_TDLS_NEGATIVE
+#define LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_REQ   0x1 /* 5.1.4-5 */
+#define LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_REQ  0x2 /* 5.2.4-16 */
+#define LIM_TDLS_NEGATIVE_STATUS_37_IN_SETUP_CNF    0x4 /* 5.2.4-10 */
+#define LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ     0x8 /* 5.2.4-20/32 */
+#define LIM_TDLS_NEGATIVE_RSP_TIMEOUT_TO_SETUP_REQ  0x10 /* 5.2.3.4 */
+#define LIM_TDLS_NEGATIVE_TREAT_TDLS_PROHIBIT_AP    0x20 /* 5.2.4-49 */
+   /* following is not paticularily tested in WFA test plan, but will help to validate our TDLS behavior in-house */
+#define LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_RSP   0x40
+#define LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_RSP  0x80
+
+void limTdlsSetNegativeBehavior(tpAniSirGlobal pMac, tANI_U8 value, tANI_BOOLEAN on);
+#endif
+#endif
+
 void limProcessDisassocAckTimeout(tpAniSirGlobal pMac);
 void limProcessDeauthAckTimeout(tpAniSirGlobal pMac);
 eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index 95f01ab..b48d55f 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -7472,7 +7472,13 @@
     }
     if (psessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE)
         (void) limIbssAddStaRsp(pMac, limMsgQ->bodyptr,psessionEntry);
-    
+#ifdef FEATURE_WLAN_TDLS
+    else if(pMac->lim.gLimAddStaTdls)
+    {
+        limProcessTdlsAddStaRsp(pMac, limMsgQ->bodyptr, psessionEntry) ;
+        pMac->lim.gLimAddStaTdls = FALSE ;
+    }    
+#endif
     else
         limProcessMlmAddStaRsp(pMac, limMsgQ,psessionEntry);
                 
diff --git a/CORE/MAC/src/pe/lim/limUtils.h b/CORE/MAC/src/pe/lim/limUtils.h
index 5d50a4e..c570693 100644
--- a/CORE/MAC/src/pe/lim/limUtils.h
+++ b/CORE/MAC/src/pe/lim/limUtils.h
@@ -486,6 +486,12 @@
   --------------------------------------------------------------------------*/
 void peGetResumeChannel(tpAniSirGlobal pMac, tANI_U8* resumeChannel, ePhyChanBondState* resumePhyCbState);
 
+#ifdef FEATURE_WLAN_TDLS_INTERNAL
+tANI_U8 limTdlsFindLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac, tLimTdlsLinkSetupPeer  **setupPeer);
+void limTdlsDelLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac);
+void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer, tANI_U32 timerId, 
+                                      tANI_U16 timerType, tANI_U32 timerMsg);
+#endif
 tANI_U8 limGetShortSlotFromPhyMode(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U32 phyMode);
 
 void limCleanUpDisassocDeauthReq(tpAniSirGlobal pMac, tANI_U8 *staMac, tANI_BOOLEAN cleanRxPath);