4bd43f507c
Initial dump of the otus USB wireless network driver. It builds properly, but a lot of work needs to be done cleaning it up before it can be merged into the wireless driver tree. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
732 lines
18 KiB
C
732 lines
18 KiB
C
/*
|
|
* Copyright (c) 2007-2008 Atheros Communications Inc.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/**
|
|
* The power saving manager is to save the power as much as possible.
|
|
* Generally speaking, it controls:
|
|
*
|
|
* - when to sleep
|
|
* -
|
|
*
|
|
*/
|
|
#include "cprecomp.h"
|
|
|
|
void zfPowerSavingMgrInit(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
wd->sta.powerSaveMode = ZM_STA_PS_NONE;
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
|
|
wd->sta.psMgr.isSleepAllowed = 0;
|
|
wd->sta.psMgr.maxSleepPeriods = 1;
|
|
wd->sta.psMgr.ticks = 0;
|
|
wd->sta.psMgr.sleepAllowedtick = 0;
|
|
}
|
|
|
|
static u16_t zfPowerSavingMgrHandlePsNone(zdev_t* dev, u8_t *isWakeUpRequired)
|
|
{
|
|
u16_t ret = 0;
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
*isWakeUpRequired = 0;
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T1:
|
|
case ZM_PS_MSG_STATE_T2:
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
default:
|
|
*isWakeUpRequired = 1;
|
|
zm_debug_msg0("zfPowerSavingMgrHandlePsNone: Wake up now\n");
|
|
if ( zfStaIsConnected(dev) )
|
|
{
|
|
zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
|
|
//zfSendNullData(dev, 0);
|
|
ret = 1;
|
|
}
|
|
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void zfPowerSavingMgrHandlePs(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
//zm_debug_msg0("zfPowerSavingMgrHandlePs: Prepare to sleep...\n");
|
|
//wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T1:
|
|
case ZM_PS_MSG_STATE_T2:
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void zfPowerSavingMgrSetMode(zdev_t* dev, u8_t mode)
|
|
{
|
|
u16_t sendNull = 0;
|
|
u8_t isWakeUpRequired = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
zm_debug_msg1("mode = ", mode);
|
|
|
|
if (mode > ZM_STA_PS_LIGHT)
|
|
{
|
|
zm_debug_msg0("return - wrong power save mode");
|
|
return;
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
#if 1
|
|
switch(mode)
|
|
{
|
|
case ZM_STA_PS_NONE:
|
|
sendNull = zfPowerSavingMgrHandlePsNone(dev, &isWakeUpRequired);
|
|
break;
|
|
|
|
case ZM_STA_PS_FAST:
|
|
case ZM_STA_PS_LIGHT:
|
|
wd->sta.psMgr.maxSleepPeriods = 1;
|
|
zfPowerSavingMgrHandlePs(dev);
|
|
break;
|
|
|
|
case ZM_STA_PS_MAX:
|
|
wd->sta.psMgr.maxSleepPeriods = ZM_PS_MAX_SLEEP_PERIODS;
|
|
zfPowerSavingMgrHandlePs(dev);
|
|
break;
|
|
}
|
|
#else
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
if ( mode != ZM_STA_PS_NONE )
|
|
{
|
|
zm_debug_msg0("zfPowerSavingMgrSetMode: switch from ZM_PS_MSG_STATE_ACTIVE to ZM_PS_MSG_STATE_T1\n");
|
|
// Stall the TX & start to wait the pending TX to be completed
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
|
|
}
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
wd->sta.powerSaveMode = mode;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
if ( isWakeUpRequired )
|
|
{
|
|
zfHpPowerSaveSetState(dev, 0);
|
|
wd->sta.psMgr.tempWakeUp = 0;
|
|
}
|
|
|
|
if ( zfStaIsConnected(dev)
|
|
&& (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
|
|
{
|
|
switch(mode)
|
|
{
|
|
case ZM_STA_PS_NONE:
|
|
zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
|
|
break;
|
|
|
|
case ZM_STA_PS_FAST:
|
|
case ZM_STA_PS_MAX:
|
|
case ZM_STA_PS_LIGHT:
|
|
zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
|
|
break;
|
|
|
|
default:
|
|
zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sendNull == 1)
|
|
{
|
|
zfSendNullData(dev, 0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void zfPowerSavingMgrNotifyPSToAP(zdev_t *dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
if ( (wd->sta.psMgr.tempWakeUp != 1)&&
|
|
(wd->sta.psMgr.lastTxUnicastFrm != wd->commTally.txUnicastFrm ||
|
|
wd->sta.psMgr.lastTxBroadcastFrm != wd->commTally.txBroadcastFrm ||
|
|
wd->sta.psMgr.lastTxMulticastFrm != wd->commTally.txMulticastFrm) )
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm;
|
|
wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm;
|
|
wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
zfSendNullData(dev, 1);
|
|
}
|
|
}
|
|
|
|
static void zfPowerSavingMgrOnHandleT1(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
// If the tx Q is not empty...return
|
|
if ( zfIsVtxqEmpty(dev) == FALSE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
zm_debug_msg0("VtxQ is empty now...Check if HAL TXQ is empty\n");
|
|
|
|
// The the HAL TX Q is not empty...return
|
|
if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
zm_debug_msg0("HAL TXQ is empty now...Could go to sleep...\n");
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
|
|
{
|
|
if (wd->sta.ReceivedPktRatePerSecond > 200)
|
|
{
|
|
zmw_leave_critical_section(dev);
|
|
return;
|
|
}
|
|
|
|
if ( zfStaIsConnected(dev)
|
|
&& (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
|
|
{
|
|
if (wd->sta.psMgr.sleepAllowedtick) {
|
|
wd->sta.psMgr.sleepAllowedtick--;
|
|
zmw_leave_critical_section(dev);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_T2;
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
// Send the Null pkt to AP to notify that I'm going to sleep
|
|
if ( zfStaIsConnected(dev) )
|
|
{
|
|
zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
|
|
zfPowerSavingMgrNotifyPSToAP(dev);
|
|
}
|
|
|
|
// Stall the TX now
|
|
// zfTxEngineStop(dev);
|
|
}
|
|
|
|
static void zfPowerSavingMgrOnHandleT2(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
// Wait until the Null pkt is transmitted
|
|
if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_SLEEP;
|
|
wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm;
|
|
wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm;
|
|
wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
// Let CHIP sleep now
|
|
zm_debug_msg0("zfPowerSavingMgrOnHandleT2 zzzz....\n");
|
|
zfHpPowerSaveSetState(dev, 1);
|
|
wd->sta.psMgr.tempWakeUp = 0;
|
|
}
|
|
|
|
u8_t zfPowerSavingMgrIsSleeping(zdev_t *dev)
|
|
{
|
|
u8_t isSleeping = FALSE;
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
if ( wd->sta.psMgr.state == ZM_PS_MSG_STATE_SLEEP ||
|
|
wd->sta.psMgr.state == ZM_PS_MSG_STATE_T2)
|
|
{
|
|
isSleeping = TRUE;
|
|
}
|
|
zmw_leave_critical_section(dev);
|
|
return isSleeping;
|
|
}
|
|
|
|
static u8_t zfPowerSavingMgrIsIdle(zdev_t *dev)
|
|
{
|
|
u8_t isIdle = 0;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
if ( zfStaIsConnected(dev) && wd->sta.psMgr.isSleepAllowed == 0 )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if ( wd->sta.bChannelScan )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if ( zfStaIsConnecting(dev) )
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
|
|
{
|
|
if (wd->sta.ReceivedPktRatePerSecond > 200)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if ( zfStaIsConnected(dev)
|
|
&& (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
|
|
{
|
|
if (wd->sta.psMgr.sleepAllowedtick) {
|
|
wd->sta.psMgr.sleepAllowedtick--;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
isIdle = 1;
|
|
|
|
done:
|
|
zmw_leave_critical_section(dev);
|
|
|
|
if ( zfIsVtxqEmpty(dev) == FALSE )
|
|
{
|
|
isIdle = 0;
|
|
}
|
|
|
|
return isIdle;
|
|
}
|
|
|
|
static void zfPowerSavingMgrSleepIfIdle(zdev_t *dev)
|
|
{
|
|
u8_t isIdle;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
isIdle = zfPowerSavingMgrIsIdle(dev);
|
|
|
|
if ( isIdle == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
|
|
switch(wd->sta.powerSaveMode)
|
|
{
|
|
case ZM_STA_PS_NONE:
|
|
break;
|
|
|
|
case ZM_STA_PS_MAX:
|
|
case ZM_STA_PS_FAST:
|
|
case ZM_STA_PS_LIGHT:
|
|
zm_debug_msg0("zfPowerSavingMgrSleepIfIdle: IDLE so slep now...\n");
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
|
|
break;
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
}
|
|
|
|
static void zfPowerSavingMgrDisconnectMain(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
#ifdef ZM_ENABLE_DISCONNECT_PS
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
zfPowerSavingMgrSleepIfIdle(dev);
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T1:
|
|
zfPowerSavingMgrOnHandleT1(dev);
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T2:
|
|
zfPowerSavingMgrOnHandleT2(dev);
|
|
break;
|
|
}
|
|
#else
|
|
zfPowerSavingMgrWakeup(dev);
|
|
#endif
|
|
}
|
|
|
|
static void zfPowerSavingMgrInfraMain(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
zfPowerSavingMgrSleepIfIdle(dev);
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T1:
|
|
zfPowerSavingMgrOnHandleT1(dev);
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T2:
|
|
zfPowerSavingMgrOnHandleT2(dev);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void zfPowerSavingMgrAtimWinExpired(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
//printk("zfPowerSavingMgrAtimWinExpired #1\n");
|
|
if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//printk("zfPowerSavingMgrAtimWinExpired #2\n");
|
|
// if we received any ATIM window from the others to indicate we have buffered data
|
|
// at the other station, we can't go to sleep
|
|
if ( wd->sta.recvAtim )
|
|
{
|
|
wd->sta.recvAtim = 0;
|
|
zm_debug_msg0("Can't sleep due to receving ATIM window!");
|
|
return;
|
|
}
|
|
|
|
// if we are the one to tx beacon during last beacon interval. we can't go to sleep
|
|
// since we need to be alive to respond the probe request!
|
|
if ( wd->sta.txBeaconInd )
|
|
{
|
|
zm_debug_msg0("Can't sleep due to just transmit a beacon!");
|
|
return;
|
|
}
|
|
|
|
// If we buffer any data for the other stations. we could not go to sleep
|
|
if ( wd->sta.ibssPrevPSDataCount != 0 )
|
|
{
|
|
zm_debug_msg0("Can't sleep due to buffering data for the others!");
|
|
return;
|
|
}
|
|
|
|
// before sleeping, we still need to notify the others by transmitting null
|
|
// pkt with power mgmt bit turned on.
|
|
zfPowerSavingMgrOnHandleT1(dev);
|
|
}
|
|
|
|
static void zfPowerSavingMgrIBSSMain(zdev_t* dev)
|
|
{
|
|
// wait for the end of
|
|
// if need to wait to know if we are the one to transmit the beacon
|
|
// during the beacon interval. If it's me, we can't go to sleep.
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
case ZM_PS_MSG_STATE_T1:
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T2:
|
|
zfPowerSavingMgrOnHandleT2(dev);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#if 1
|
|
void zfPowerSavingMgrMain(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
switch (wd->sta.adapterState)
|
|
{
|
|
case ZM_STA_STATE_DISCONNECT:
|
|
zfPowerSavingMgrDisconnectMain(dev);
|
|
break;
|
|
case ZM_STA_STATE_CONNECTED:
|
|
{
|
|
if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) {
|
|
zfPowerSavingMgrInfraMain(dev);
|
|
} else if (wd->wlanMode == ZM_MODE_IBSS) {
|
|
zfPowerSavingMgrIBSSMain(dev);
|
|
}
|
|
}
|
|
break;
|
|
case ZM_STA_STATE_CONNECTING:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
void zfPowerSavingMgrMain(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch(wd->sta.psMgr.state)
|
|
{
|
|
case ZM_PS_MSG_STATE_ACTIVE:
|
|
goto check_sleep;
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_SLEEP:
|
|
goto sleeping;
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T1:
|
|
zfPowerSavingMgrOnHandleT1(dev);
|
|
break;
|
|
|
|
case ZM_PS_MSG_STATE_T2:
|
|
zfPowerSavingMgrOnHandleT2(dev);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
|
|
sleeping:
|
|
return;
|
|
|
|
check_sleep:
|
|
zfPowerSavingMgrSleepIfIdle(dev);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifdef ZM_ENABLE_POWER_SAVE
|
|
void zfPowerSavingMgrWakeup(zdev_t* dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
//zm_debug_msg0("zfPowerSavingMgrWakeup");
|
|
|
|
//if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE && ( zfPowerSavingMgrIsIdle(dev) == 0 ))
|
|
if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE )
|
|
{
|
|
zmw_enter_critical_section(dev);
|
|
|
|
wd->sta.psMgr.isSleepAllowed = 0;
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
|
|
|
|
if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
|
|
wd->sta.psMgr.tempWakeUp = 1;
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
// Wake up the CHIP now!!
|
|
zfHpPowerSaveSetState(dev, 0);
|
|
}
|
|
}
|
|
#else
|
|
void zfPowerSavingMgrWakeup(zdev_t* dev)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void zfPowerSavingMgrProcessBeacon(zdev_t* dev, zbuf_t* buf)
|
|
{
|
|
u8_t length, bitmap;
|
|
u16_t offset, n1, n2, q, r;
|
|
zbuf_t* psBuf;
|
|
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
|
|
//if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_SLEEP )
|
|
{
|
|
return;
|
|
}
|
|
|
|
wd->sta.psMgr.isSleepAllowed = 1;
|
|
|
|
if ( (offset=zfFindElement(dev, buf, ZM_WLAN_EID_TIM)) != 0xffff )
|
|
{
|
|
length = zmw_rx_buf_readb(dev, buf, offset+1);
|
|
|
|
if ( length > 3 )
|
|
{
|
|
n1 = zmw_rx_buf_readb(dev, buf, offset+4) & (~ZM_BIT_0);
|
|
n2 = length + n1 - 4;
|
|
q = wd->sta.aid >> 3;
|
|
r = wd->sta.aid & 7;
|
|
|
|
if ((q >= n1) && (q <= n2))
|
|
{
|
|
bitmap = zmw_rx_buf_readb(dev, buf, offset+5+q-n1);
|
|
|
|
if ( (bitmap >> r) & ZM_BIT_0 )
|
|
{
|
|
//if ( wd->sta.powerSaveMode == ZM_STA_PS_FAST )
|
|
if ( 0 )
|
|
{
|
|
wd->sta.psMgr.state = ZM_PS_MSG_STATE_S1;
|
|
//zfSendPSPoll(dev);
|
|
zfSendNullData(dev, 0);
|
|
}
|
|
else
|
|
{
|
|
if ((wd->sta.qosInfo&0xf) != 0xf)
|
|
{
|
|
/* send ps-poll */
|
|
//printk("zfSendPSPoll #1\n");
|
|
|
|
wd->sta.psMgr.isSleepAllowed = 0;
|
|
|
|
switch (wd->sta.powerSaveMode)
|
|
{
|
|
case ZM_STA_PS_MAX:
|
|
case ZM_STA_PS_FAST:
|
|
//zm_debug_msg0("wake up and send PS-Poll\n");
|
|
zfSendPSPoll(dev);
|
|
break;
|
|
case ZM_STA_PS_LIGHT:
|
|
zm_debug_msg0("wake up and send null data\n");
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.psMgr.sleepAllowedtick = 400;
|
|
zmw_leave_critical_section(dev);
|
|
|
|
zfSendNullData(dev, 0);
|
|
break;
|
|
}
|
|
|
|
wd->sta.psMgr.tempWakeUp = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
while ((psBuf = zfQueueGet(dev, wd->sta.uapsdQ)) != NULL)
|
|
{
|
|
zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
|
|
}
|
|
|
|
//printk("zfPowerSavingMgrProcessBeacon #1\n");
|
|
zfPowerSavingMgrMain(dev);
|
|
}
|
|
|
|
void zfPowerSavingMgrConnectNotify(zdev_t *dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
|
|
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
|
|
{
|
|
switch(wd->sta.powerSaveMode)
|
|
{
|
|
case ZM_STA_PS_NONE:
|
|
zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
|
|
break;
|
|
|
|
case ZM_STA_PS_FAST:
|
|
case ZM_STA_PS_MAX:
|
|
case ZM_STA_PS_LIGHT:
|
|
zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
|
|
break;
|
|
|
|
default:
|
|
zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void zfPowerSavingMgrPreTBTTInterrupt(zdev_t *dev)
|
|
{
|
|
zmw_get_wlan_dev(dev);
|
|
zmw_declare_for_critical_section();
|
|
|
|
/* disable TBTT interrupt when change from connection to disconnect */
|
|
if (zfStaIsDisconnect(dev)) {
|
|
zfHpPowerSaveSetMode(dev, 0, 0, 0);
|
|
zfPowerSavingMgrWakeup(dev);
|
|
return;
|
|
}
|
|
|
|
zmw_enter_critical_section(dev);
|
|
wd->sta.psMgr.ticks++;
|
|
|
|
if ( wd->sta.psMgr.ticks < wd->sta.psMgr.maxSleepPeriods )
|
|
{
|
|
zmw_leave_critical_section(dev);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
wd->sta.psMgr.ticks = 0;
|
|
}
|
|
|
|
zmw_leave_critical_section(dev);
|
|
|
|
zfPowerSavingMgrWakeup(dev);
|
|
}
|
|
|
|
/* Leave an empty line below to remove warning message on some compiler */
|
|
|