Example #1
0
/*
========================================================================
Routine Description:
	Receive a traffic indication frame.

Arguments:
	pAd				- WLAN control block pointer
	pElem			- the frame information

Return Value:
	None

Note:
========================================================================
*/
static VOID TDLS_UAPSD_PeerTrafficIndAction(
    IN	PRTMP_ADAPTER				pAd,
    IN	MLME_QUEUE_ELEM				*pElem)
{
	UCHAR Token;
	UCHAR PeerAddr[6];
	UCHAR PeerAddr1[6];
	ULONG OffsetPuBuff;
	INT LinkId = 0xff;
	PRT_802_11_TDLS	pTDLS = NULL;
	PFRAME_802_11 pFrame = (PFRAME_802_11)pElem->Msg;

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> ====> %s\n", __FUNCTION__));

	/* Not TDLS Capable, ignore it */
	if (!IS_TDLS_SUPPORT(pAd))
		return;

	/* Not BSS mode, ignore it */
	if (!INFRA_ON(pAd))
		return;

	hex_dump("TDLS UAPSD Peer Traffic Ind receive pack", pElem->Msg, pElem->MsgLen);

	/* sanity check */
	if (TDLS_UAPSD_ARE_WE_IN_ACTIVE(pAd))
		return; /* we are not in power-save mode */

	COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3);
	// Drop not within my TDLS Table that created before !
	LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
	if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
	{
		DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_UAPSD_PeerTrafficIndAction() can not find the LinkId!\n"));
		return;
	}

	// Point to the current Link ID
	pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

	OffsetPuBuff = PeerTdlsBasicSanity(pAd,
									pElem->Msg,
									pElem->MsgLen,
									pTDLS->bInitiator,
									&Token,
									PeerAddr1);
	if (OffsetPuBuff <= 0)
		return;

/*	hex_dump("PeerAddr=", PeerAddr, 6); */
	DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> PU Buffer Status = 0x%x\n",
			pElem->Msg[OffsetPuBuff+2])); /* 2: skip ID and length field */

	/* reply a response frame with UP = 5 */
	/* for TDLS UAPSD, all AC will be UAPSD mode */
	TDLS_UAPSD_TrafficRspSend(pAd, PeerAddr, Token);
}
Example #2
0
/*
========================================================================
Routine Description:
	Receive a traffic response frame.

Arguments:
	pAd				- WLAN control block pointer
	pElem			- the frame information
Return Value:
	None

Note:
========================================================================
*/
static VOID TDLS_UAPSD_PeerTrafficRspAction(
	IN	PRTMP_ADAPTER				pAd,
    IN	MLME_QUEUE_ELEM				*pElem)
{
	UCHAR Token;
	UCHAR PeerAddr[6];
	UCHAR PeerAddr1[6];
	RT_802_11_TDLS *pTDLS;
	INT32 LinkId = 0xff;
	BOOLEAN TimerCancelled;
	PFRAME_802_11 pFrame = (PFRAME_802_11)pElem->Msg;

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> ====> %s\n", __FUNCTION__));

	/* Not TDLS Capable, ignore it */
	if (!IS_TDLS_SUPPORT(pAd))
		return;
	
	/* Not BSS mode, ignore it */
	if (!INFRA_ON(pAd))
		return;

	hex_dump("TDLS UAPSD Peer Traffic Response receive pack", pElem->Msg, pElem->MsgLen);

	COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr2);
	// Drop not within my TDLS Table that created before !
	LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_ERROR, ("%s: can not find the LinkId!\n", __FUNCTION__));
		return;
	}

	// Point to the current Link ID
	pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

	/* sanity check */
	PeerTdlsBasicSanity(pAd,
						pElem->Msg,
						pElem->MsgLen,
						pTDLS->bInitiator,
						&Token,
						PeerAddr1);

/*	hex_dump("PeerAddr=", PeerAddr, 6); */

	/* search TDLS entry */
	LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_TRACE,
				("%s: can not find the LinkId!\n", __FUNCTION__));
		TDLS_UAPSD_REBUILD_LINK(pAd, PeerAddr);
		return;
	}

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId));

	/* cancel waiting flag to avoid tear down the link */
	pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId);
	pTDLS->FlgIsWaitingUapsdTraRsp = FALSE;
	RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);

	/* check if we can sleep if we are sleep mode */
	RtmpAsicSleepHandle(pAd);
}
/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerChannelSwitchRspAction(
    IN PRTMP_ADAPTER pAd,
    IN MLME_QUEUE_ELEM *Elem)
{
    PRT_802_11_TDLS		pTDLS = NULL;
    int					LinkId = 0xff;
    UCHAR				PeerAddr[MAC_ADDR_LEN];
    //BOOLEAN				IsInitator;
    BOOLEAN				TimerCancelled;
    //UCHAR				RegulatoryClass;
    //UCHAR				NewExtChannelOffset = 0xff;
    UCHAR				LinkIdentLen;
    USHORT				PeerChSwitchTime;
    USHORT				PeerChSwitchTimeOut;
    TDLS_LINK_IDENT_ELEMENT	LinkIdent;
    //NDIS_STATUS			NStatus = NDIS_STATUS_SUCCESS;
    USHORT				StatusCode = MLME_SUCCESS;

    DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_PeerChannelSwitchRspAction() \n"));

    // Not TDLS Capable, ignore it
    if (!IS_TDLS_SUPPORT(pAd))
        return;

    if (!INFRA_ON(pAd))
        return;

    hex_dump("TDLS peer channel switch response receive pack", Elem->Msg, Elem->MsgLen);

    if (!PeerTdlsChannelSwitchRspSanity(pAd,
                                        Elem->Msg,
                                        Elem->MsgLen,
                                        PeerAddr,
                                        &StatusCode,
                                        &PeerChSwitchTime,
                                        &PeerChSwitchTimeOut,
                                        &LinkIdentLen,
                                        &LinkIdent))
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    // Drop not within my TDLS Table that created before !
    LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
    if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    // Point to the current Link ID
    pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

    if ((pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE) &&
            (StatusCode == MLME_REQUEST_DECLINED))
    {
        DBGPRINT(RT_DEBUG_OFF,("%s(%d): received a failed StatusCode = %d on Unsolicited response !!!\n",
                               __FUNCTION__, __LINE__, StatusCode));
        return;
    }

    if (StatusCode == MLME_REQUEST_DECLINED)
    {
        if ((pAd->StaCfg.TdlsChannelSwitchRetryCount > 0) &&
                (pTDLS->bDoingPeriodChannelSwitch) &&
                (pAd->StaCfg.bDoingPeriodChannelSwitch))
        {
            pAd->StaCfg.TdlsChannelSwitchRetryCount--;

            DBGPRINT(RT_DEBUG_OFF,("%s(%d): received a failed StatusCode = %d  re-try again !!!\n",
                                   __FUNCTION__, __LINE__, StatusCode));
        }
        else
        {
            pTDLS->bDoingPeriodChannelSwitch = FALSE;
            pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE;
            pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;
            pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE;
            RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
        }

        DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_PeerChannelSwitchRspAction() received a failed StatusCode = %d !!!\n", StatusCode ));
        return;
    }

    DBGPRINT(RT_DEBUG_WARN,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
                            __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));



    if (StatusCode == MLME_SUCCESS)
    {
        if (pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE)
        {
            if (pAd->StaCfg.bChannelSwitchInitiator == FALSE)
            {
                RTMPCancelTimer(&pAd->StaCfg.TdlsResponderGoBackBaseChTimer, &TimerCancelled);
                DBGPRINT(RT_DEBUG_WARN,("%s(%d): i am responder!!!\n",  __FUNCTION__,__LINE__));
            }
            else
            {
                RTMPCancelTimer(&pAd->StaCfg.TdlsPeriodGoBackBaseChTimer, &TimerCancelled);
                DBGPRINT(RT_DEBUG_WARN,("%s(%d): i am Initiator !!!\n", __FUNCTION__,__LINE__));
            }

            if (pAd->StaCfg.TdlsCurrentOperateChannel != pAd->CommonCfg.Channel)
            {
                DBGPRINT(RT_DEBUG_ERROR, ("106. %ld !!!\n", (jiffies * 1000) / OS_HZ));

                RTMPusecDelay(300);
                NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime);

                RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
                else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
                else
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
                TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
                RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
            }
        }
        else
        {
            if (pAd->StaCfg.TdlsCurrentChannel != pAd->CommonCfg.Channel)
            {
                if (pAd->StaCfg.bChannelSwitchInitiator)
                {
                    UINT16 SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds
                    UINT16 SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds

                    pAd->StaCfg.TdlsChannelSwitchPairCount--;
                    pAd->StaCfg.TdlsChannelSwitchRetryCount = 10;
                    //pAd->StaCfg.bDoingPeriodChannelSwitch = TRUE;

                    if (SwitchTime >= PeerChSwitchTime)
                        PeerChSwitchTime = SwitchTime;

                    if (SwitchTimeout >= PeerChSwitchTimeOut)
                        PeerChSwitchTimeOut = SwitchTimeout;

                    pTDLS->ChSwitchTime = PeerChSwitchTime;
                    pAd->StaCfg.TdlsGlobalSwitchTime = PeerChSwitchTime;
                    pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut;
                    pAd->StaCfg.TdlsGlobalSwitchTimeOut = PeerChSwitchTimeOut;
                    pTDLS->ChannelSwitchCurrentState = TDLS_CHANNEL_SWITCH_NONE;

                    RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                    //Cancel the timer since the received packet to me.
#ifdef TDLS_HWTIMER_SUPPORT
                    TDLS_SetChannelSwitchTimer(pAd,  ((PeerChSwitchTime + pAd->StaCfg.TdlsOffChannelDelay) / 1000));
#else
                    RTMPCancelTimer(&pTDLS->ChannelSwitchTimer, &TimerCancelled);
                    pTDLS->bEnableChSwitchTime = TRUE;
                    NdisGetSystemUpTime(&pTDLS->ChannelSwitchTimerStartTime);
                    RTMPSetTimer(&pTDLS->ChannelSwitchTimer, ((PeerChSwitchTime + pAd->StaCfg.TdlsOffChannelDelay) / 1000));
#endif // TDLS_HWTIMER_SUPPORT //

                    if (RTDebugLevel < RT_DEBUG_ERROR)
                        RTMPusecDelay(300);
                    else
                        DBGPRINT(RT_DEBUG_ERROR, ("104. %ld !!!\n", (jiffies * 1000) / OS_HZ));
                    TDLS_InitChannelRelatedValue(pAd, pAd->StaCfg.TdlsCurrentChannel, pAd->StaCfg.TdlsCurrentChannelBW);
                }
            }
            else
            {
                pTDLS->bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE;
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;

                if (pAd->StaCfg.bChannelSwitchInitiator == FALSE)
                {
                    DBGPRINT(RT_DEBUG_OFF,("%s(%d): i am channel switch responder!!!\n",  __FUNCTION__,__LINE__));
                }
                else
                {
                    RTMPCancelTimer(&pAd->StaCfg.TdlsDisableChannelSwitchTimer, &TimerCancelled);
                    pAd->StaCfg.bChannelSwitchInitiator = FALSE;
                    DBGPRINT(RT_DEBUG_OFF,("%s(%d): i am channel switch Initiator !!!\n", __FUNCTION__,__LINE__));
                }

                if (pAd->StaCfg.TdlsCurrentOperateChannel != pAd->CommonCfg.Channel)
                {
                    RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                    if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                        TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
                    else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                        TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
                    else
                        TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
                    TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
                    RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                }

                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
            }
        }
    }




    DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_PeerChannelSwitchRspAction() \n"));

    return;
}
/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerChannelSwitchReqAction(
    IN PRTMP_ADAPTER pAd,
    IN MLME_QUEUE_ELEM *Elem)
{
    PRT_802_11_TDLS		pTDLS = NULL;
    int					LinkId = 0xff;
    UCHAR				PeerAddr[MAC_ADDR_LEN];
    BOOLEAN				IsInitator;
    //BOOLEAN				TimerCancelled;
    UCHAR				TargetChannel;
    UCHAR				RegulatoryClass;
    UCHAR				NewExtChannelOffset = 0xff;
    UCHAR				LinkIdentLen;
    USHORT				PeerChSwitchTime;
    USHORT				PeerChSwitchTimeOut;
    TDLS_LINK_IDENT_ELEMENT	LinkIdent;
    NDIS_STATUS			NStatus = NDIS_STATUS_SUCCESS;
    USHORT				StatusCode = MLME_SUCCESS;
    UINT16				SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds
    UINT16				SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds

    DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_PeerChannelSwitchReqAction() \n"));

    // Not TDLS Capable, ignore it
    if (!IS_TDLS_SUPPORT(pAd))
        return;

    if (!INFRA_ON(pAd))
        return;

    if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE)
    {
        DBGPRINT(RT_DEBUG_OFF,("%s(%d): AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__, __LINE__));
        return;
    }

    tdls_hex_dump("TDLS peer channel switch request receive pack", Elem->Msg, Elem->MsgLen);

    if (!PeerTdlsChannelSwitchReqSanity(pAd,
                                        Elem->Msg,
                                        Elem->MsgLen,
                                        PeerAddr,
                                        &IsInitator,
                                        &TargetChannel,
                                        &RegulatoryClass,
                                        &NewExtChannelOffset,
                                        &PeerChSwitchTime,
                                        &PeerChSwitchTimeOut,
                                        &LinkIdentLen,
                                        &LinkIdent))
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    DBGPRINT(RT_DEBUG_WARN,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
                            __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));

    DBGPRINT(RT_DEBUG_ERROR, ("300. %ld !!!\n", (jiffies * 1000) / OS_HZ));

    // Drop not within my TDLS Table that created before !
    LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
    if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    if (pAd->StaCfg.bChannelSwitchInitiator == FALSE)
    {
        pAd->StaCfg.TdlsForcePowerSaveWithAP = TRUE;

        if (pAd->StaCfg.bTdlsNoticeAPPowerSave == FALSE)
        {
            pAd->StaCfg.TdlsSendNullFrameCount = 0;
            pAd->StaCfg.bTdlsNoticeAPPowerSave = TRUE;
            RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, TRUE);
        }
        else
        {
            pAd->StaCfg.TdlsSendNullFrameCount++;
            if (pAd->StaCfg.TdlsSendNullFrameCount >= 200)
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;
        }
    }



    // Point to the current Link ID
    pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

    if (SwitchTime >= PeerChSwitchTime)
        PeerChSwitchTime = SwitchTime;

    if (SwitchTimeout >= PeerChSwitchTimeOut)
        PeerChSwitchTimeOut = SwitchTimeout;

    if (RtmpPktPmBitCheck(pAd))
    {
        RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
        TDLS_SendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, 0);
    }

    {
        UINT32 macCfg, TxCount;
        UINT32 MTxCycle;

        RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg);

        if  (TargetChannel != pAd->CommonCfg.Channel)
            NStatus = TDLS_ChannelSwitchRspAction(pAd, pTDLS, PeerChSwitchTime, PeerChSwitchTimeOut, StatusCode, RTMP_TDLS_SPECIFIC_CS_RSP_WAIT_ACK);
        else
            NStatus = TDLS_ChannelSwitchRspAction(pAd, pTDLS, PeerChSwitchTime, PeerChSwitchTimeOut, StatusCode, (RTMP_TDLS_SPECIFIC_CS_RSP_WAIT_ACK + RTMP_TDLS_SPECIFIC_HCCA));


        for (MTxCycle = 0; MTxCycle < 500; MTxCycle++)
        {
            RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg);
            TxCount = macCfg & 0x0000ffff;
            if (TxCount > 0)
            {
                DBGPRINT(RT_DEBUG_ERROR, ("MTxCycle = %d, %ld !!!\n", MTxCycle, (jiffies * 1000) / OS_HZ));
                break;
            }
            else
                RTMPusecDelay(50);
        }

        if (MTxCycle >= 500)
        {
            NStatus = NDIS_STATUS_FAILURE;
            DBGPRINT(RT_DEBUG_OFF,("TDLS Transmit Channel Switch Response Fail !!!\n"));
        }
    }

    if (NStatus == NDIS_STATUS_SUCCESS)
    {

        {
            if  (TargetChannel != pAd->CommonCfg.Channel)
            {
                BOOLEAN TimerCancelled;
                //ULONG Now, temp1, temp2, temp3;

                pAd->StaCfg.TdlsCurrentChannel = TargetChannel;

                if (NewExtChannelOffset != 0)
                    pAd->StaCfg.TdlsCurrentChannelBW = NewExtChannelOffset;
                else
                    pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_NONE;

                pTDLS->ChSwitchTime = PeerChSwitchTime;
                pAd->StaCfg.TdlsGlobalSwitchTime = PeerChSwitchTime;
                pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut;
                pAd->StaCfg.TdlsGlobalSwitchTimeOut = PeerChSwitchTimeOut;

                RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                //Cancel the timer since the received packet to me.
#ifdef TDLS_HWTIMER_SUPPORT
                TDLS_SetChannelSwitchTimer(pAd,  (PeerChSwitchTimeOut / 1000));
#else
                RTMPCancelTimer(&pTDLS->ChannelSwitchTimeoutTimer, &TimerCancelled);
                NdisGetSystemUpTime(&pTDLS->ChannelSwitchTimerStartTime);
                RTMPSetTimer(&pTDLS->ChannelSwitchTimeoutTimer, (PeerChSwitchTimeOut / 1000));
#endif // TDLS_HWTIMER_SUPPORT //
                RTMPCancelTimer(&pAd->StaCfg.TdlsDisableChannelSwitchTimer, &TimerCancelled);
                pAd->StaCfg.bTdlsCurrentDoingChannelSwitchWaitSuccess = TRUE;
                pAd->StaCfg.bDoingPeriodChannelSwitch = TRUE;

                if (RTDebugLevel < RT_DEBUG_ERROR)
                    RTMPusecDelay(300);
                else
                    DBGPRINT(RT_DEBUG_ERROR, ("1041. %ld !!!\n", (jiffies * 1000) / OS_HZ));
                TDLS_InitChannelRelatedValue(pAd, pAd->StaCfg.TdlsCurrentChannel, pAd->StaCfg.TdlsCurrentChannelBW);
            }
            else
            {
                pTDLS->bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE;
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;

                RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                RTMPusecDelay(300);

                if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
                else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
                else
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
                TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
                RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);

                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
            }
        }
    }

    DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_PeerChannelSwitchReqAction() \n"));

    return;
}