Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/common/ral_ps.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

226 lines
6.8 KiB
C

/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2010, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
All related POWER SAVE function body.
***************************************************************************/
#include "rt_config.h"
/*
========================================================================
Description:
This routine frees all packets in PSQ that's destined to a specific DA.
BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL
is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF
========================================================================
*/
VOID RalHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive)
{
QUEUE_ENTRY *pQEntry;
MAC_TABLE_ENTRY *pMacEntry;
unsigned long IrqFlags;
STA_TR_ENTRY *tr_entry;
/*
DBGPRINT(RT_DEBUG_TRACE, ("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n",
Aid, PRINT_MAC(pAddr)));
*/
pMacEntry = &pAd->MacTab.Content[wcid];
tr_entry = &pAd->MacTab.tr_entry[wcid];
{
/*NdisAcquireSpinLock(&pAd->MacTabLock); */
/*NdisAcquireSpinLock(&pAd->TxSwQueueLock); */
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
if (isActive == FALSE)
{
if (tr_entry->ps_queue.Head)
{
#ifdef UAPSD_SUPPORT
UINT32 NumOfOldPsPkt;
NumOfOldPsPkt = pAd->TxSwQueue[QID_AC_BE].Number;
#endif /* UAPSD_SUPPORT */
pQEntry = RemoveHeadQueue(&tr_entry->ps_queue);
if (tr_entry->ps_queue.Number >= 1)
{
RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pQEntry), TRUE);
RTMP_SET_PACKET_TXTYPE(RTPKT_TO_OSPKT(pQEntry), TX_LEGACY_FRAME);
}
InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry);
#ifdef UAPSD_SUPPORT
/* we need to call RTMPDeQueuePacket() immediately as below */
if (NumOfOldPsPkt != pAd->TxSwQueue[QID_AC_BE].Number)
{
if (RTMP_GET_PACKET_DHCP(RTPKT_TO_OSPKT(pQEntry)) ||
RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pQEntry)) ||
RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pQEntry)))
{
/*
These packets will use 1M/6M rate to send.
If you use 1M(2.4G)/6M(5G) to send, no statistics
count in NICUpdateFifoStaCounters().
So we can not count it for UAPSD; Or the SP will
not closed until timeout.
*/
}
else
UAPSD_MR_MIX_PS_POLL_RCV(pAd, pMacEntry);
}
#endif /* UAPSD_SUPPORT */
}
else
{
/*
or transmit a (QoS) Null Frame;
In addtion, in Station Keep Alive mechanism, we need to
send a QoS Null frame to detect the station live status.
*/
BOOLEAN bQosNull = FALSE;
if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
bQosNull = TRUE;
RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, tr_entry->CurrTxRate,
pMacEntry->Aid, pMacEntry->func_tb_idx,
bQosNull, TRUE, 0);
}
}
else
{
#ifdef UAPSD_SUPPORT
/* deliver all queued UAPSD packets */
UAPSD_AllPacketDeliver(pAd, pMacEntry);
/* end the SP if exists */
UAPSD_MR_ENTRY_RESET(pAd, pMacEntry);
#endif /* UAPSD_SUPPORT */
while(tr_entry->ps_queue.Head)
{
pQEntry = RemoveHeadQueue(&tr_entry->ps_queue);
InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry);
}
}
/*NdisReleaseSpinLock(&pAd->TxSwQueueLock); */
/*NdisReleaseSpinLock(&pAd->MacTabLock); */
if ((pMacEntry->Aid > 0) && (pMacEntry->Aid < MAX_LEN_OF_MAC_TABLE) &&
(tr_entry->ps_queue.Number == 0))
{
/* clear corresponding TIM bit because no any PS packet */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->func_tb_idx, pMacEntry->Aid);
}
#endif /* CONFIG_AP_SUPPORT */
tr_entry->PsQIdleCount = 0;
}
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
/*
Dequeue outgoing frames from TxSwQueue0..3 queue and process it
TODO: 2004-12-27 it's not a good idea to handle "More Data" bit here.
because the RTMPDeQueue process doesn't guarantee to de-queue the
desired MSDU from the corresponding TxSwQueue/PsQueue when QOS
in-used. We should consider "HardTransmt" this MPDU using MGMT
queue or things like that.
*/
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, wcid, MAX_TX_PROCESS);
}
}
/*
==========================================================================
Description:
Update the station current power save mode. Calling this routine also
prove the specified client is still alive. Otherwise AP will age-out
this client once IdleCount exceeds a threshold.
==========================================================================
*/
BOOLEAN RalPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm)
{
MAC_TABLE_ENTRY *pEntry;
UCHAR old_psmode;
STA_TR_ENTRY *tr_entry;
tr_entry = &pAd->MacTab.tr_entry[wcid];
if (wcid >= MAX_LEN_OF_MAC_TABLE)
return PWR_ACTIVE;
pEntry = &pAd->MacTab.Content[wcid];
old_psmode = pEntry->PsMode;
/* if (pEntry) */
{
/*
Change power save mode first because we will call
RTMPDeQueuePacket() in RtmpHandleRxPsPoll().
Or when Psm = PWR_ACTIVE, we will not do Aggregation in
RTMPDeQueuePacket().
*/
pEntry->NoDataIdleCount = 0;
pEntry->PsMode = Psm;
// TODO: shiang-usw, we need to rmove upper setting and migrate to tr_entry->PsMode
pAd->MacTab.tr_entry[wcid].PsMode = Psm;
if (old_psmode != Psm) {
DBGPRINT(RT_DEBUG_INFO, ("%s():%02x:%02x:%02x:%02x:%02x:%02x %s!\n",
__FUNCTION__, PRINT_MAC(pAddr),
(Psm == PWR_SAVE ? "Sleep" : "wakes up, act like rx PS-POLL")));
}
if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE))
{
#ifdef RTMP_MAC_PCI
#ifdef DOT11_N_SUPPORT
/*
When sta wake up, we send BAR to refresh the BA sequence.
TODO:
For RT2870, how to handle BA when STA in PS mode?
*/
SendRefreshBAR(pAd, pEntry);
#endif /* DOT11_N_SUPPORT */
#endif /* RTMP_MAC_PCI */
/* sleep station awakes, move all pending frames from PSQ to TXQ if any */
RtmpHandleRxPsPoll(pAd, pAddr, pEntry->wcid, TRUE);
}
}
#ifdef RELEASE_EXCLUDE
/*
else
{
// not in table, try to learn it ???? why bother?
DBGPRINT(RT_DEBUG_INFO, ("%s():[%ldth] not match %02x:%02x:%02x:%02x:%02x:%02x \n",
__FUNCTION__, wcid, PRINT_MAC(pAddr)));
}
*/
#endif /* RELEASE_EXCLUDE */
return old_psmode;
}