2 * Copyright (c) 2007-2008 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * The power saving manager is to save the power as much as possible.
19 * Generally speaking, it controls:
27 void zfPowerSavingMgrInit(zdev_t
* dev
)
29 zmw_get_wlan_dev(dev
);
31 wd
->sta
.powerSaveMode
= ZM_STA_PS_NONE
;
32 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_ACTIVE
;
33 wd
->sta
.psMgr
.isSleepAllowed
= 0;
34 wd
->sta
.psMgr
.maxSleepPeriods
= 1;
35 wd
->sta
.psMgr
.ticks
= 0;
36 wd
->sta
.psMgr
.sleepAllowedtick
= 0;
39 static u16_t
zfPowerSavingMgrHandlePsNone(zdev_t
* dev
, u8_t
*isWakeUpRequired
)
42 zmw_get_wlan_dev(dev
);
44 switch(wd
->sta
.psMgr
.state
)
46 case ZM_PS_MSG_STATE_ACTIVE
:
47 *isWakeUpRequired
= 0;
50 case ZM_PS_MSG_STATE_T1
:
51 case ZM_PS_MSG_STATE_T2
:
52 case ZM_PS_MSG_STATE_SLEEP
:
54 *isWakeUpRequired
= 1;
55 zm_debug_msg0("zfPowerSavingMgrHandlePsNone: Wake up now\n");
56 if ( zfStaIsConnected(dev
) )
58 zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
59 //zfSendNullData(dev, 0);
63 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_ACTIVE
;
69 static void zfPowerSavingMgrHandlePs(zdev_t
* dev
)
71 zmw_get_wlan_dev(dev
);
73 switch(wd
->sta
.psMgr
.state
)
75 case ZM_PS_MSG_STATE_ACTIVE
:
76 //zm_debug_msg0("zfPowerSavingMgrHandlePs: Prepare to sleep...\n");
77 //wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
80 case ZM_PS_MSG_STATE_T1
:
81 case ZM_PS_MSG_STATE_T2
:
82 case ZM_PS_MSG_STATE_SLEEP
:
88 void zfPowerSavingMgrSetMode(zdev_t
* dev
, u8_t mode
)
91 u8_t isWakeUpRequired
= 0;
93 zmw_get_wlan_dev(dev
);
94 zmw_declare_for_critical_section();
96 zm_debug_msg1("mode = ", mode
);
98 if (mode
> ZM_STA_PS_LIGHT
)
100 zm_debug_msg0("return - wrong power save mode");
104 zmw_enter_critical_section(dev
);
109 sendNull
= zfPowerSavingMgrHandlePsNone(dev
, &isWakeUpRequired
);
113 case ZM_STA_PS_LIGHT
:
114 wd
->sta
.psMgr
.maxSleepPeriods
= 1;
115 zfPowerSavingMgrHandlePs(dev
);
119 wd
->sta
.psMgr
.maxSleepPeriods
= ZM_PS_MAX_SLEEP_PERIODS
;
120 zfPowerSavingMgrHandlePs(dev
);
124 wd
->sta
.powerSaveMode
= mode
;
125 zmw_leave_critical_section(dev
);
127 if ( isWakeUpRequired
)
129 zfHpPowerSaveSetState(dev
, 0);
130 wd
->sta
.psMgr
.tempWakeUp
= 0;
133 if ( zfStaIsConnected(dev
)
134 && (wd
->wlanMode
== ZM_MODE_INFRASTRUCTURE
) )
139 zfHpPowerSaveSetMode(dev
, 0, 0, wd
->beaconInterval
);
144 case ZM_STA_PS_LIGHT
:
145 zfHpPowerSaveSetMode(dev
, 0, 1, wd
->beaconInterval
);
149 zfHpPowerSaveSetMode(dev
, 0, 0, wd
->beaconInterval
);
156 zfSendNullData(dev
, 0);
162 static void zfPowerSavingMgrNotifyPSToAP(zdev_t
*dev
)
164 zmw_get_wlan_dev(dev
);
165 zmw_declare_for_critical_section();
167 if ( (wd
->sta
.psMgr
.tempWakeUp
!= 1)&&
168 (wd
->sta
.psMgr
.lastTxUnicastFrm
!= wd
->commTally
.txUnicastFrm
||
169 wd
->sta
.psMgr
.lastTxBroadcastFrm
!= wd
->commTally
.txBroadcastFrm
||
170 wd
->sta
.psMgr
.lastTxMulticastFrm
!= wd
->commTally
.txMulticastFrm
) )
172 zmw_enter_critical_section(dev
);
173 wd
->sta
.psMgr
.lastTxUnicastFrm
= wd
->commTally
.txUnicastFrm
;
174 wd
->sta
.psMgr
.lastTxBroadcastFrm
= wd
->commTally
.txBroadcastFrm
;
175 wd
->sta
.psMgr
.lastTxMulticastFrm
= wd
->commTally
.txMulticastFrm
;
176 zmw_leave_critical_section(dev
);
178 zfSendNullData(dev
, 1);
182 static void zfPowerSavingMgrOnHandleT1(zdev_t
* dev
)
184 zmw_get_wlan_dev(dev
);
185 zmw_declare_for_critical_section();
187 // If the tx Q is not empty...return
188 if ( zfIsVtxqEmpty(dev
) == FALSE
)
193 zm_debug_msg0("VtxQ is empty now...Check if HAL TXQ is empty\n");
195 // The the HAL TX Q is not empty...return
196 if ( zfHpGetFreeTxdCount(dev
) != zfHpGetMaxTxdCount(dev
) )
201 zm_debug_msg0("HAL TXQ is empty now...Could go to sleep...\n");
203 zmw_enter_critical_section(dev
);
205 if (wd
->sta
.powerSaveMode
== ZM_STA_PS_LIGHT
)
207 if (wd
->sta
.ReceivedPktRatePerSecond
> 200)
209 zmw_leave_critical_section(dev
);
213 if ( zfStaIsConnected(dev
)
214 && (wd
->wlanMode
== ZM_MODE_INFRASTRUCTURE
) )
216 if (wd
->sta
.psMgr
.sleepAllowedtick
) {
217 wd
->sta
.psMgr
.sleepAllowedtick
--;
218 zmw_leave_critical_section(dev
);
224 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_T2
;
226 zmw_leave_critical_section(dev
);
228 // Send the Null pkt to AP to notify that I'm going to sleep
229 if ( zfStaIsConnected(dev
) )
231 zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
232 zfPowerSavingMgrNotifyPSToAP(dev
);
236 // zfTxEngineStop(dev);
239 static void zfPowerSavingMgrOnHandleT2(zdev_t
* dev
)
241 zmw_get_wlan_dev(dev
);
242 zmw_declare_for_critical_section();
244 // Wait until the Null pkt is transmitted
245 if ( zfHpGetFreeTxdCount(dev
) != zfHpGetMaxTxdCount(dev
) )
250 zmw_enter_critical_section(dev
);
251 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_SLEEP
;
252 wd
->sta
.psMgr
.lastTxUnicastFrm
= wd
->commTally
.txUnicastFrm
;
253 wd
->sta
.psMgr
.lastTxBroadcastFrm
= wd
->commTally
.txBroadcastFrm
;
254 wd
->sta
.psMgr
.lastTxMulticastFrm
= wd
->commTally
.txMulticastFrm
;
255 zmw_leave_critical_section(dev
);
257 // Let CHIP sleep now
258 zm_debug_msg0("zfPowerSavingMgrOnHandleT2 zzzz....\n");
259 zfHpPowerSaveSetState(dev
, 1);
260 wd
->sta
.psMgr
.tempWakeUp
= 0;
263 u8_t
zfPowerSavingMgrIsSleeping(zdev_t
*dev
)
265 u8_t isSleeping
= FALSE
;
266 zmw_get_wlan_dev(dev
);
267 zmw_declare_for_critical_section();
269 zmw_enter_critical_section(dev
);
270 if ( wd
->sta
.psMgr
.state
== ZM_PS_MSG_STATE_SLEEP
||
271 wd
->sta
.psMgr
.state
== ZM_PS_MSG_STATE_T2
)
275 zmw_leave_critical_section(dev
);
279 static u8_t
zfPowerSavingMgrIsIdle(zdev_t
*dev
)
283 zmw_get_wlan_dev(dev
);
284 zmw_declare_for_critical_section();
286 zmw_enter_critical_section(dev
);
288 if ( zfStaIsConnected(dev
) && wd
->sta
.psMgr
.isSleepAllowed
== 0 )
293 if ( wd
->sta
.bChannelScan
)
298 if ( zfStaIsConnecting(dev
) )
303 if (wd
->sta
.powerSaveMode
== ZM_STA_PS_LIGHT
)
305 if (wd
->sta
.ReceivedPktRatePerSecond
> 200)
310 if ( zfStaIsConnected(dev
)
311 && (wd
->wlanMode
== ZM_MODE_INFRASTRUCTURE
) )
313 if (wd
->sta
.psMgr
.sleepAllowedtick
) {
314 wd
->sta
.psMgr
.sleepAllowedtick
--;
323 zmw_leave_critical_section(dev
);
325 if ( zfIsVtxqEmpty(dev
) == FALSE
)
333 static void zfPowerSavingMgrSleepIfIdle(zdev_t
*dev
)
337 zmw_get_wlan_dev(dev
);
338 zmw_declare_for_critical_section();
340 isIdle
= zfPowerSavingMgrIsIdle(dev
);
347 zmw_enter_critical_section(dev
);
349 switch(wd
->sta
.powerSaveMode
)
356 case ZM_STA_PS_LIGHT
:
357 zm_debug_msg0("zfPowerSavingMgrSleepIfIdle: IDLE so slep now...\n");
358 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_T1
;
362 zmw_leave_critical_section(dev
);
365 static void zfPowerSavingMgrDisconnectMain(zdev_t
* dev
)
367 #ifdef ZM_ENABLE_DISCONNECT_PS
368 switch(wd
->sta
.psMgr
.state
)
370 case ZM_PS_MSG_STATE_ACTIVE
:
371 zfPowerSavingMgrSleepIfIdle(dev
);
374 case ZM_PS_MSG_STATE_SLEEP
:
377 case ZM_PS_MSG_STATE_T1
:
378 zfPowerSavingMgrOnHandleT1(dev
);
381 case ZM_PS_MSG_STATE_T2
:
382 zfPowerSavingMgrOnHandleT2(dev
);
386 zfPowerSavingMgrWakeup(dev
);
390 static void zfPowerSavingMgrInfraMain(zdev_t
* dev
)
392 zmw_get_wlan_dev(dev
);
394 switch(wd
->sta
.psMgr
.state
)
396 case ZM_PS_MSG_STATE_ACTIVE
:
397 zfPowerSavingMgrSleepIfIdle(dev
);
400 case ZM_PS_MSG_STATE_SLEEP
:
403 case ZM_PS_MSG_STATE_T1
:
404 zfPowerSavingMgrOnHandleT1(dev
);
407 case ZM_PS_MSG_STATE_T2
:
408 zfPowerSavingMgrOnHandleT2(dev
);
413 void zfPowerSavingMgrAtimWinExpired(zdev_t
* dev
)
415 zmw_get_wlan_dev(dev
);
417 //printk("zfPowerSavingMgrAtimWinExpired #1\n");
418 if ( wd
->sta
.powerSaveMode
== ZM_STA_PS_NONE
)
423 //printk("zfPowerSavingMgrAtimWinExpired #2\n");
424 // if we received any ATIM window from the others to indicate we have buffered data
425 // at the other station, we can't go to sleep
426 if ( wd
->sta
.recvAtim
)
428 wd
->sta
.recvAtim
= 0;
429 zm_debug_msg0("Can't sleep due to receving ATIM window!");
433 // if we are the one to tx beacon during last beacon interval. we can't go to sleep
434 // since we need to be alive to respond the probe request!
435 if ( wd
->sta
.txBeaconInd
)
437 zm_debug_msg0("Can't sleep due to just transmit a beacon!");
441 // If we buffer any data for the other stations. we could not go to sleep
442 if ( wd
->sta
.ibssPrevPSDataCount
!= 0 )
444 zm_debug_msg0("Can't sleep due to buffering data for the others!");
448 // before sleeping, we still need to notify the others by transmitting null
449 // pkt with power mgmt bit turned on.
450 zfPowerSavingMgrOnHandleT1(dev
);
453 static void zfPowerSavingMgrIBSSMain(zdev_t
* dev
)
455 // wait for the end of
456 // if need to wait to know if we are the one to transmit the beacon
457 // during the beacon interval. If it's me, we can't go to sleep.
459 zmw_get_wlan_dev(dev
);
461 switch(wd
->sta
.psMgr
.state
)
463 case ZM_PS_MSG_STATE_ACTIVE
:
464 case ZM_PS_MSG_STATE_SLEEP
:
465 case ZM_PS_MSG_STATE_T1
:
468 case ZM_PS_MSG_STATE_T2
:
469 zfPowerSavingMgrOnHandleT2(dev
);
476 void zfPowerSavingMgrMain(zdev_t
* dev
)
478 zmw_get_wlan_dev(dev
);
480 switch (wd
->sta
.adapterState
)
482 case ZM_STA_STATE_DISCONNECT
:
483 zfPowerSavingMgrDisconnectMain(dev
);
485 case ZM_STA_STATE_CONNECTED
:
487 if (wd
->wlanMode
== ZM_MODE_INFRASTRUCTURE
) {
488 zfPowerSavingMgrInfraMain(dev
);
489 } else if (wd
->wlanMode
== ZM_MODE_IBSS
) {
490 zfPowerSavingMgrIBSSMain(dev
);
494 case ZM_STA_STATE_CONNECTING
:
500 #ifdef ZM_ENABLE_POWER_SAVE
501 void zfPowerSavingMgrWakeup(zdev_t
* dev
)
503 zmw_get_wlan_dev(dev
);
504 zmw_declare_for_critical_section();
506 //zm_debug_msg0("zfPowerSavingMgrWakeup");
508 //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE && ( zfPowerSavingMgrIsIdle(dev) == 0 ))
509 if ( wd
->sta
.psMgr
.state
!= ZM_PS_MSG_STATE_ACTIVE
)
511 zmw_enter_critical_section(dev
);
513 wd
->sta
.psMgr
.isSleepAllowed
= 0;
514 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_ACTIVE
;
516 if ( wd
->sta
.powerSaveMode
> ZM_STA_PS_NONE
)
517 wd
->sta
.psMgr
.tempWakeUp
= 1;
519 zmw_leave_critical_section(dev
);
521 // Wake up the CHIP now!!
522 zfHpPowerSaveSetState(dev
, 0);
526 void zfPowerSavingMgrWakeup(zdev_t
* dev
)
531 void zfPowerSavingMgrProcessBeacon(zdev_t
* dev
, zbuf_t
* buf
)
534 u16_t offset
, n1
, n2
, q
, r
;
537 zmw_get_wlan_dev(dev
);
538 zmw_declare_for_critical_section();
540 if ( wd
->sta
.powerSaveMode
== ZM_STA_PS_NONE
)
541 //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_SLEEP )
546 wd
->sta
.psMgr
.isSleepAllowed
= 1;
548 offset
= zfFindElement(dev
, buf
, ZM_WLAN_EID_TIM
);
549 if (offset
!= 0xffff)
551 length
= zmw_rx_buf_readb(dev
, buf
, offset
+1);
555 n1
= zmw_rx_buf_readb(dev
, buf
, offset
+4) & (~ZM_BIT_0
);
556 n2
= length
+ n1
- 4;
557 q
= wd
->sta
.aid
>> 3;
560 if ((q
>= n1
) && (q
<= n2
))
562 bitmap
= zmw_rx_buf_readb(dev
, buf
, offset
+5+q
-n1
);
564 if ( (bitmap
>> r
) & ZM_BIT_0
)
566 //if ( wd->sta.powerSaveMode == ZM_STA_PS_FAST )
569 wd
->sta
.psMgr
.state
= ZM_PS_MSG_STATE_S1
;
571 zfSendNullData(dev
, 0);
575 if ((wd
->sta
.qosInfo
&0xf) != 0xf)
578 //printk("zfSendPSPoll #1\n");
580 wd
->sta
.psMgr
.isSleepAllowed
= 0;
582 switch (wd
->sta
.powerSaveMode
)
586 //zm_debug_msg0("wake up and send PS-Poll\n");
589 case ZM_STA_PS_LIGHT
:
590 zm_debug_msg0("wake up and send null data\n");
592 zmw_enter_critical_section(dev
);
593 wd
->sta
.psMgr
.sleepAllowedtick
= 400;
594 zmw_leave_critical_section(dev
);
596 zfSendNullData(dev
, 0);
600 wd
->sta
.psMgr
.tempWakeUp
= 0;
608 while ((psBuf
= zfQueueGet(dev
, wd
->sta
.uapsdQ
)) != NULL
)
610 zfTxSendEth(dev
, psBuf
, 0, ZM_EXTERNAL_ALLOC_BUF
, 0);
613 //printk("zfPowerSavingMgrProcessBeacon #1\n");
614 zfPowerSavingMgrMain(dev
);
617 void zfPowerSavingMgrConnectNotify(zdev_t
*dev
)
619 zmw_get_wlan_dev(dev
);
621 if ( wd
->wlanMode
== ZM_MODE_INFRASTRUCTURE
)
623 switch(wd
->sta
.powerSaveMode
)
626 zfHpPowerSaveSetMode(dev
, 0, 0, wd
->beaconInterval
);
631 case ZM_STA_PS_LIGHT
:
632 zfHpPowerSaveSetMode(dev
, 0, 1, wd
->beaconInterval
);
636 zfHpPowerSaveSetMode(dev
, 0, 0, wd
->beaconInterval
);
642 void zfPowerSavingMgrPreTBTTInterrupt(zdev_t
*dev
)
644 zmw_get_wlan_dev(dev
);
645 zmw_declare_for_critical_section();
647 /* disable TBTT interrupt when change from connection to disconnect */
648 if (zfStaIsDisconnect(dev
)) {
649 zfHpPowerSaveSetMode(dev
, 0, 0, 0);
650 zfPowerSavingMgrWakeup(dev
);
654 zmw_enter_critical_section(dev
);
655 wd
->sta
.psMgr
.ticks
++;
657 if ( wd
->sta
.psMgr
.ticks
< wd
->sta
.psMgr
.maxSleepPeriods
)
659 zmw_leave_critical_section(dev
);
664 wd
->sta
.psMgr
.ticks
= 0;
667 zmw_leave_critical_section(dev
);
669 zfPowerSavingMgrWakeup(dev
);
672 /* Leave an empty line below to remove warning message on some compiler */