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);
110 sendNull = zfPowerSavingMgrHandlePsNone(dev, &isWakeUpRequired);
114 case ZM_STA_PS_LIGHT:
115 wd->sta.psMgr.maxSleepPeriods = 1;
116 zfPowerSavingMgrHandlePs(dev);
120 wd->sta.psMgr.maxSleepPeriods = ZM_PS_MAX_SLEEP_PERIODS;
121 zfPowerSavingMgrHandlePs(dev);
125 switch(wd->sta.psMgr.state)
127 case ZM_PS_MSG_STATE_ACTIVE:
128 if ( mode != ZM_STA_PS_NONE )
130 zm_debug_msg0("zfPowerSavingMgrSetMode: switch from ZM_PS_MSG_STATE_ACTIVE to ZM_PS_MSG_STATE_T1\n");
131 // Stall the TX & start to wait the pending TX to be completed
132 wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
136 case ZM_PS_MSG_STATE_SLEEP:
141 wd->sta.powerSaveMode = mode;
142 zmw_leave_critical_section(dev);
144 if ( isWakeUpRequired )
146 zfHpPowerSaveSetState(dev, 0);
147 wd->sta.psMgr.tempWakeUp = 0;
150 if ( zfStaIsConnected(dev)
151 && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
156 zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
161 case ZM_STA_PS_LIGHT:
162 zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
166 zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
173 zfSendNullData(dev, 0);
179 static void zfPowerSavingMgrNotifyPSToAP(zdev_t *dev)
181 zmw_get_wlan_dev(dev);
182 zmw_declare_for_critical_section();
184 if ( (wd->sta.psMgr.tempWakeUp != 1)&&
185 (wd->sta.psMgr.lastTxUnicastFrm != wd->commTally.txUnicastFrm ||
186 wd->sta.psMgr.lastTxBroadcastFrm != wd->commTally.txBroadcastFrm ||
187 wd->sta.psMgr.lastTxMulticastFrm != wd->commTally.txMulticastFrm) )
189 zmw_enter_critical_section(dev);
190 wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm;
191 wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm;
192 wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm;
193 zmw_leave_critical_section(dev);
195 zfSendNullData(dev, 1);
199 static void zfPowerSavingMgrOnHandleT1(zdev_t* dev)
201 zmw_get_wlan_dev(dev);
202 zmw_declare_for_critical_section();
204 // If the tx Q is not empty...return
205 if ( zfIsVtxqEmpty(dev) == FALSE )
210 zm_debug_msg0("VtxQ is empty now...Check if HAL TXQ is empty\n");
212 // The the HAL TX Q is not empty...return
213 if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
218 zm_debug_msg0("HAL TXQ is empty now...Could go to sleep...\n");
220 zmw_enter_critical_section(dev);
222 if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
224 if (wd->sta.ReceivedPktRatePerSecond > 200)
226 zmw_leave_critical_section(dev);
230 if ( zfStaIsConnected(dev)
231 && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
233 if (wd->sta.psMgr.sleepAllowedtick) {
234 wd->sta.psMgr.sleepAllowedtick--;
235 zmw_leave_critical_section(dev);
241 wd->sta.psMgr.state = ZM_PS_MSG_STATE_T2;
243 zmw_leave_critical_section(dev);
245 // Send the Null pkt to AP to notify that I'm going to sleep
246 if ( zfStaIsConnected(dev) )
248 zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
249 zfPowerSavingMgrNotifyPSToAP(dev);
253 // zfTxEngineStop(dev);
256 static void zfPowerSavingMgrOnHandleT2(zdev_t* dev)
258 zmw_get_wlan_dev(dev);
259 zmw_declare_for_critical_section();
261 // Wait until the Null pkt is transmitted
262 if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
267 zmw_enter_critical_section(dev);
268 wd->sta.psMgr.state = ZM_PS_MSG_STATE_SLEEP;
269 wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm;
270 wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm;
271 wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm;
272 zmw_leave_critical_section(dev);
274 // Let CHIP sleep now
275 zm_debug_msg0("zfPowerSavingMgrOnHandleT2 zzzz....\n");
276 zfHpPowerSaveSetState(dev, 1);
277 wd->sta.psMgr.tempWakeUp = 0;
280 u8_t zfPowerSavingMgrIsSleeping(zdev_t *dev)
282 u8_t isSleeping = FALSE;
283 zmw_get_wlan_dev(dev);
284 zmw_declare_for_critical_section();
286 zmw_enter_critical_section(dev);
287 if ( wd->sta.psMgr.state == ZM_PS_MSG_STATE_SLEEP ||
288 wd->sta.psMgr.state == ZM_PS_MSG_STATE_T2)
292 zmw_leave_critical_section(dev);
296 static u8_t zfPowerSavingMgrIsIdle(zdev_t *dev)
300 zmw_get_wlan_dev(dev);
301 zmw_declare_for_critical_section();
303 zmw_enter_critical_section(dev);
305 if ( zfStaIsConnected(dev) && wd->sta.psMgr.isSleepAllowed == 0 )
310 if ( wd->sta.bChannelScan )
315 if ( zfStaIsConnecting(dev) )
320 if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
322 if (wd->sta.ReceivedPktRatePerSecond > 200)
327 if ( zfStaIsConnected(dev)
328 && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
330 if (wd->sta.psMgr.sleepAllowedtick) {
331 wd->sta.psMgr.sleepAllowedtick--;
340 zmw_leave_critical_section(dev);
342 if ( zfIsVtxqEmpty(dev) == FALSE )
350 static void zfPowerSavingMgrSleepIfIdle(zdev_t *dev)
354 zmw_get_wlan_dev(dev);
355 zmw_declare_for_critical_section();
357 isIdle = zfPowerSavingMgrIsIdle(dev);
364 zmw_enter_critical_section(dev);
366 switch(wd->sta.powerSaveMode)
373 case ZM_STA_PS_LIGHT:
374 zm_debug_msg0("zfPowerSavingMgrSleepIfIdle: IDLE so slep now...\n");
375 wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
379 zmw_leave_critical_section(dev);
382 static void zfPowerSavingMgrDisconnectMain(zdev_t* dev)
384 #ifdef ZM_ENABLE_DISCONNECT_PS
385 switch(wd->sta.psMgr.state)
387 case ZM_PS_MSG_STATE_ACTIVE:
388 zfPowerSavingMgrSleepIfIdle(dev);
391 case ZM_PS_MSG_STATE_SLEEP:
394 case ZM_PS_MSG_STATE_T1:
395 zfPowerSavingMgrOnHandleT1(dev);
398 case ZM_PS_MSG_STATE_T2:
399 zfPowerSavingMgrOnHandleT2(dev);
403 zfPowerSavingMgrWakeup(dev);
407 static void zfPowerSavingMgrInfraMain(zdev_t* dev)
409 zmw_get_wlan_dev(dev);
411 switch(wd->sta.psMgr.state)
413 case ZM_PS_MSG_STATE_ACTIVE:
414 zfPowerSavingMgrSleepIfIdle(dev);
417 case ZM_PS_MSG_STATE_SLEEP:
420 case ZM_PS_MSG_STATE_T1:
421 zfPowerSavingMgrOnHandleT1(dev);
424 case ZM_PS_MSG_STATE_T2:
425 zfPowerSavingMgrOnHandleT2(dev);
430 void zfPowerSavingMgrAtimWinExpired(zdev_t* dev)
432 zmw_get_wlan_dev(dev);
434 //printk("zfPowerSavingMgrAtimWinExpired #1\n");
435 if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
440 //printk("zfPowerSavingMgrAtimWinExpired #2\n");
441 // if we received any ATIM window from the others to indicate we have buffered data
442 // at the other station, we can't go to sleep
443 if ( wd->sta.recvAtim )
445 wd->sta.recvAtim = 0;
446 zm_debug_msg0("Can't sleep due to receving ATIM window!");
450 // if we are the one to tx beacon during last beacon interval. we can't go to sleep
451 // since we need to be alive to respond the probe request!
452 if ( wd->sta.txBeaconInd )
454 zm_debug_msg0("Can't sleep due to just transmit a beacon!");
458 // If we buffer any data for the other stations. we could not go to sleep
459 if ( wd->sta.ibssPrevPSDataCount != 0 )
461 zm_debug_msg0("Can't sleep due to buffering data for the others!");
465 // before sleeping, we still need to notify the others by transmitting null
466 // pkt with power mgmt bit turned on.
467 zfPowerSavingMgrOnHandleT1(dev);
470 static void zfPowerSavingMgrIBSSMain(zdev_t* dev)
472 // wait for the end of
473 // if need to wait to know if we are the one to transmit the beacon
474 // during the beacon interval. If it's me, we can't go to sleep.
476 zmw_get_wlan_dev(dev);
478 switch(wd->sta.psMgr.state)
480 case ZM_PS_MSG_STATE_ACTIVE:
481 case ZM_PS_MSG_STATE_SLEEP:
482 case ZM_PS_MSG_STATE_T1:
485 case ZM_PS_MSG_STATE_T2:
486 zfPowerSavingMgrOnHandleT2(dev);
494 void zfPowerSavingMgrMain(zdev_t* dev)
496 zmw_get_wlan_dev(dev);
498 switch (wd->sta.adapterState)
500 case ZM_STA_STATE_DISCONNECT:
501 zfPowerSavingMgrDisconnectMain(dev);
503 case ZM_STA_STATE_CONNECTED:
505 if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) {
506 zfPowerSavingMgrInfraMain(dev);
507 } else if (wd->wlanMode == ZM_MODE_IBSS) {
508 zfPowerSavingMgrIBSSMain(dev);
512 case ZM_STA_STATE_CONNECTING:
518 void zfPowerSavingMgrMain(zdev_t* dev)
520 zmw_get_wlan_dev(dev);
522 if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE )
527 switch(wd->sta.psMgr.state)
529 case ZM_PS_MSG_STATE_ACTIVE:
533 case ZM_PS_MSG_STATE_SLEEP:
537 case ZM_PS_MSG_STATE_T1:
538 zfPowerSavingMgrOnHandleT1(dev);
541 case ZM_PS_MSG_STATE_T2:
542 zfPowerSavingMgrOnHandleT2(dev);
552 zfPowerSavingMgrSleepIfIdle(dev);
557 #ifdef ZM_ENABLE_POWER_SAVE
558 void zfPowerSavingMgrWakeup(zdev_t* dev)
560 zmw_get_wlan_dev(dev);
561 zmw_declare_for_critical_section();
563 //zm_debug_msg0("zfPowerSavingMgrWakeup");
565 //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE && ( zfPowerSavingMgrIsIdle(dev) == 0 ))
566 if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE )
568 zmw_enter_critical_section(dev);
570 wd->sta.psMgr.isSleepAllowed = 0;
571 wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
573 if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
574 wd->sta.psMgr.tempWakeUp = 1;
576 zmw_leave_critical_section(dev);
578 // Wake up the CHIP now!!
579 zfHpPowerSaveSetState(dev, 0);
583 void zfPowerSavingMgrWakeup(zdev_t* dev)
588 void zfPowerSavingMgrProcessBeacon(zdev_t* dev, zbuf_t* buf)
591 u16_t offset, n1, n2, q, r;
594 zmw_get_wlan_dev(dev);
595 zmw_declare_for_critical_section();
597 if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
598 //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_SLEEP )
603 wd->sta.psMgr.isSleepAllowed = 1;
605 offset = zfFindElement(dev, buf, ZM_WLAN_EID_TIM);
606 if (offset != 0xffff)
608 length = zmw_rx_buf_readb(dev, buf, offset+1);
612 n1 = zmw_rx_buf_readb(dev, buf, offset+4) & (~ZM_BIT_0);
613 n2 = length + n1 - 4;
614 q = wd->sta.aid >> 3;
617 if ((q >= n1) && (q <= n2))
619 bitmap = zmw_rx_buf_readb(dev, buf, offset+5+q-n1);
621 if ( (bitmap >> r) & ZM_BIT_0 )
623 //if ( wd->sta.powerSaveMode == ZM_STA_PS_FAST )
626 wd->sta.psMgr.state = ZM_PS_MSG_STATE_S1;
628 zfSendNullData(dev, 0);
632 if ((wd->sta.qosInfo&0xf) != 0xf)
635 //printk("zfSendPSPoll #1\n");
637 wd->sta.psMgr.isSleepAllowed = 0;
639 switch (wd->sta.powerSaveMode)
643 //zm_debug_msg0("wake up and send PS-Poll\n");
646 case ZM_STA_PS_LIGHT:
647 zm_debug_msg0("wake up and send null data\n");
649 zmw_enter_critical_section(dev);
650 wd->sta.psMgr.sleepAllowedtick = 400;
651 zmw_leave_critical_section(dev);
653 zfSendNullData(dev, 0);
657 wd->sta.psMgr.tempWakeUp = 0;
665 while ((psBuf = zfQueueGet(dev, wd->sta.uapsdQ)) != NULL)
667 zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
670 //printk("zfPowerSavingMgrProcessBeacon #1\n");
671 zfPowerSavingMgrMain(dev);
674 void zfPowerSavingMgrConnectNotify(zdev_t *dev)
676 zmw_get_wlan_dev(dev);
678 if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
680 switch(wd->sta.powerSaveMode)
683 zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
688 case ZM_STA_PS_LIGHT:
689 zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
693 zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
699 void zfPowerSavingMgrPreTBTTInterrupt(zdev_t *dev)
701 zmw_get_wlan_dev(dev);
702 zmw_declare_for_critical_section();
704 /* disable TBTT interrupt when change from connection to disconnect */
705 if (zfStaIsDisconnect(dev)) {
706 zfHpPowerSaveSetMode(dev, 0, 0, 0);
707 zfPowerSavingMgrWakeup(dev);
711 zmw_enter_critical_section(dev);
712 wd->sta.psMgr.ticks++;
714 if ( wd->sta.psMgr.ticks < wd->sta.psMgr.maxSleepPeriods )
716 zmw_leave_critical_section(dev);
721 wd->sta.psMgr.ticks = 0;
724 zmw_leave_critical_section(dev);
726 zfPowerSavingMgrWakeup(dev);
729 /* Leave an empty line below to remove warning message on some compiler */