linux/drivers/staging/otus/80211core/cpsmgr.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2007-2008 Atheros Communications Inc.
   3 *
   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.
   7 *
   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.
  15 */
  16
  17/**
  18  *  The power saving manager is to save the power as much as possible.
  19  *  Generally speaking, it controls:
  20  *
  21  *         - when to sleep
  22  *         -
  23  *
  24  */
  25#include "cprecomp.h"
  26
  27void zfPowerSavingMgrInit(zdev_t* dev)
  28{
  29    zmw_get_wlan_dev(dev);
  30
  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;
  37}
  38
  39static u16_t zfPowerSavingMgrHandlePsNone(zdev_t* dev, u8_t *isWakeUpRequired)
  40{
  41    u16_t ret = 0;
  42    zmw_get_wlan_dev(dev);
  43
  44    switch(wd->sta.psMgr.state)
  45    {
  46        case ZM_PS_MSG_STATE_ACTIVE:
  47            *isWakeUpRequired = 0;
  48            break;
  49
  50        case ZM_PS_MSG_STATE_T1:
  51        case ZM_PS_MSG_STATE_T2:
  52        case ZM_PS_MSG_STATE_SLEEP:
  53        default:
  54            *isWakeUpRequired = 1;
  55zm_debug_msg0("zfPowerSavingMgrHandlePsNone: Wake up now\n");
  56            if ( zfStaIsConnected(dev) )
  57            {
  58                zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
  59                //zfSendNullData(dev, 0);
  60                ret = 1;
  61            }
  62
  63            wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
  64            break;
  65    }
  66    return ret;
  67}
  68
  69static void zfPowerSavingMgrHandlePs(zdev_t* dev)
  70{
  71    zmw_get_wlan_dev(dev);
  72
  73    switch(wd->sta.psMgr.state)
  74    {
  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;
  78            break;
  79
  80        case ZM_PS_MSG_STATE_T1:
  81        case ZM_PS_MSG_STATE_T2:
  82        case ZM_PS_MSG_STATE_SLEEP:
  83        default:
  84            break;
  85    }
  86}
  87
  88void zfPowerSavingMgrSetMode(zdev_t* dev, u8_t mode)
  89{
  90    u16_t sendNull = 0;
  91    u8_t isWakeUpRequired = 0;
  92
  93    zmw_get_wlan_dev(dev);
  94    zmw_declare_for_critical_section();
  95
  96    zm_debug_msg1("mode = ", mode);
  97
  98    if (mode > ZM_STA_PS_LIGHT)
  99    {
 100        zm_debug_msg0("return - wrong power save mode");
 101        return;
 102    }
 103
 104    zmw_enter_critical_section(dev);
 105
 106    #if 1
 107    switch(mode)
 108    {
 109        case ZM_STA_PS_NONE:
 110            sendNull = zfPowerSavingMgrHandlePsNone(dev, &isWakeUpRequired);
 111            break;
 112
 113        case ZM_STA_PS_FAST:
 114        case ZM_STA_PS_LIGHT:
 115            wd->sta.psMgr.maxSleepPeriods = 1;
 116            zfPowerSavingMgrHandlePs(dev);
 117            break;
 118
 119        case ZM_STA_PS_MAX:
 120            wd->sta.psMgr.maxSleepPeriods = ZM_PS_MAX_SLEEP_PERIODS;
 121            zfPowerSavingMgrHandlePs(dev);
 122            break;
 123    }
 124    #else
 125    switch(wd->sta.psMgr.state)
 126    {
 127        case ZM_PS_MSG_STATE_ACTIVE:
 128            if ( mode != ZM_STA_PS_NONE )
 129            {
 130zm_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;
 133            }
 134            break;
 135
 136        case ZM_PS_MSG_STATE_SLEEP:
 137            break;
 138    }
 139    #endif
 140
 141    wd->sta.powerSaveMode = mode;
 142    zmw_leave_critical_section(dev);
 143
 144    if ( isWakeUpRequired )
 145    {
 146        zfHpPowerSaveSetState(dev, 0);
 147        wd->sta.psMgr.tempWakeUp = 0;
 148    }
 149
 150    if ( zfStaIsConnected(dev)
 151         && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
 152    {
 153        switch(mode)
 154        {
 155            case ZM_STA_PS_NONE:
 156                zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
 157                break;
 158
 159            case ZM_STA_PS_FAST:
 160            case ZM_STA_PS_MAX:
 161            case ZM_STA_PS_LIGHT:
 162                zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
 163                break;
 164
 165            default:
 166                zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
 167                break;
 168        }
 169    }
 170
 171    if (sendNull == 1)
 172    {
 173        zfSendNullData(dev, 0);
 174    }
 175
 176    return;
 177}
 178
 179static void zfPowerSavingMgrNotifyPSToAP(zdev_t *dev)
 180{
 181    zmw_get_wlan_dev(dev);
 182    zmw_declare_for_critical_section();
 183
 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) )
 188    {
 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);
 194
 195        zfSendNullData(dev, 1);
 196    }
 197}
 198
 199static void zfPowerSavingMgrOnHandleT1(zdev_t* dev)
 200{
 201    zmw_get_wlan_dev(dev);
 202    zmw_declare_for_critical_section();
 203
 204    // If the tx Q is not empty...return
 205    if ( zfIsVtxqEmpty(dev) == FALSE )
 206    {
 207        return;
 208    }
 209
 210zm_debug_msg0("VtxQ is empty now...Check if HAL TXQ is empty\n");
 211
 212    // The the HAL TX Q is not empty...return
 213    if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
 214    {
 215        return;
 216    }
 217
 218zm_debug_msg0("HAL TXQ is empty now...Could go to sleep...\n");
 219
 220    zmw_enter_critical_section(dev);
 221
 222    if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
 223    {
 224        if (wd->sta.ReceivedPktRatePerSecond > 200)
 225        {
 226            zmw_leave_critical_section(dev);
 227            return;
 228        }
 229
 230        if ( zfStaIsConnected(dev)
 231             && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
 232        {
 233            if (wd->sta.psMgr.sleepAllowedtick) {
 234                wd->sta.psMgr.sleepAllowedtick--;
 235                zmw_leave_critical_section(dev);
 236                return;
 237            }
 238        }
 239    }
 240
 241    wd->sta.psMgr.state = ZM_PS_MSG_STATE_T2;
 242
 243    zmw_leave_critical_section(dev);
 244
 245    // Send the Null pkt to AP to notify that I'm going to sleep
 246    if ( zfStaIsConnected(dev) )
 247    {
 248zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
 249        zfPowerSavingMgrNotifyPSToAP(dev);
 250    }
 251
 252    // Stall the TX now
 253    // zfTxEngineStop(dev);
 254}
 255
 256static void zfPowerSavingMgrOnHandleT2(zdev_t* dev)
 257{
 258    zmw_get_wlan_dev(dev);
 259    zmw_declare_for_critical_section();
 260
 261    // Wait until the Null pkt is transmitted
 262    if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
 263    {
 264        return;
 265    }
 266
 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);
 273
 274    // Let CHIP sleep now
 275zm_debug_msg0("zfPowerSavingMgrOnHandleT2 zzzz....\n");
 276    zfHpPowerSaveSetState(dev, 1);
 277    wd->sta.psMgr.tempWakeUp = 0;
 278}
 279
 280u8_t zfPowerSavingMgrIsSleeping(zdev_t *dev)
 281{
 282    u8_t isSleeping = FALSE;
 283    zmw_get_wlan_dev(dev);
 284    zmw_declare_for_critical_section();
 285
 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)
 289    {
 290        isSleeping = TRUE;
 291    }
 292    zmw_leave_critical_section(dev);
 293    return isSleeping;
 294}
 295
 296static u8_t zfPowerSavingMgrIsIdle(zdev_t *dev)
 297{
 298    u8_t isIdle = 0;
 299
 300    zmw_get_wlan_dev(dev);
 301    zmw_declare_for_critical_section();
 302
 303    zmw_enter_critical_section(dev);
 304
 305    if ( zfStaIsConnected(dev) && wd->sta.psMgr.isSleepAllowed == 0 )
 306    {
 307        goto done;
 308    }
 309
 310    if ( wd->sta.bChannelScan )
 311    {
 312        goto done;
 313    }
 314
 315    if ( zfStaIsConnecting(dev) )
 316    {
 317        goto done;
 318    }
 319
 320    if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
 321    {
 322        if (wd->sta.ReceivedPktRatePerSecond > 200)
 323        {
 324            goto done;
 325        }
 326
 327        if ( zfStaIsConnected(dev)
 328             && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
 329        {
 330            if (wd->sta.psMgr.sleepAllowedtick) {
 331                wd->sta.psMgr.sleepAllowedtick--;
 332                goto done;
 333            }
 334        }
 335    }
 336
 337    isIdle = 1;
 338
 339done:
 340    zmw_leave_critical_section(dev);
 341
 342    if ( zfIsVtxqEmpty(dev) == FALSE )
 343    {
 344        isIdle = 0;
 345    }
 346
 347    return isIdle;
 348}
 349
 350static void zfPowerSavingMgrSleepIfIdle(zdev_t *dev)
 351{
 352    u8_t isIdle;
 353
 354    zmw_get_wlan_dev(dev);
 355    zmw_declare_for_critical_section();
 356
 357    isIdle = zfPowerSavingMgrIsIdle(dev);
 358
 359    if ( isIdle == 0 )
 360    {
 361        return;
 362    }
 363
 364    zmw_enter_critical_section(dev);
 365
 366    switch(wd->sta.powerSaveMode)
 367    {
 368        case ZM_STA_PS_NONE:
 369            break;
 370
 371        case ZM_STA_PS_MAX:
 372        case ZM_STA_PS_FAST:
 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;
 376            break;
 377    }
 378
 379    zmw_leave_critical_section(dev);
 380}
 381
 382static void zfPowerSavingMgrDisconnectMain(zdev_t* dev)
 383{
 384    zmw_get_wlan_dev(dev);
 385
 386#ifdef ZM_ENABLE_DISCONNECT_PS
 387    switch(wd->sta.psMgr.state)
 388    {
 389        case ZM_PS_MSG_STATE_ACTIVE:
 390            zfPowerSavingMgrSleepIfIdle(dev);
 391            break;
 392
 393        case ZM_PS_MSG_STATE_SLEEP:
 394            break;
 395
 396        case ZM_PS_MSG_STATE_T1:
 397            zfPowerSavingMgrOnHandleT1(dev);
 398            break;
 399
 400        case ZM_PS_MSG_STATE_T2:
 401            zfPowerSavingMgrOnHandleT2(dev);
 402            break;
 403    }
 404#else
 405    zfPowerSavingMgrWakeup(dev);
 406#endif
 407}
 408
 409static void zfPowerSavingMgrInfraMain(zdev_t* dev)
 410{
 411    zmw_get_wlan_dev(dev);
 412
 413    switch(wd->sta.psMgr.state)
 414    {
 415        case ZM_PS_MSG_STATE_ACTIVE:
 416            zfPowerSavingMgrSleepIfIdle(dev);
 417            break;
 418
 419        case ZM_PS_MSG_STATE_SLEEP:
 420            break;
 421
 422        case ZM_PS_MSG_STATE_T1:
 423            zfPowerSavingMgrOnHandleT1(dev);
 424            break;
 425
 426        case ZM_PS_MSG_STATE_T2:
 427            zfPowerSavingMgrOnHandleT2(dev);
 428            break;
 429    }
 430}
 431
 432void zfPowerSavingMgrAtimWinExpired(zdev_t* dev)
 433{
 434    zmw_get_wlan_dev(dev);
 435
 436//printk("zfPowerSavingMgrAtimWinExpired #1\n");
 437    if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
 438    {
 439        return;
 440    }
 441
 442//printk("zfPowerSavingMgrAtimWinExpired #2\n");
 443    // if we received any ATIM window from the others to indicate we have buffered data
 444    // at the other station, we can't go to sleep
 445    if ( wd->sta.recvAtim )
 446    {
 447        wd->sta.recvAtim = 0;
 448        zm_debug_msg0("Can't sleep due to receving ATIM window!");
 449        return;
 450    }
 451
 452    // if we are the one to tx beacon during last beacon interval. we can't go to sleep
 453    // since we need to be alive to respond the probe request!
 454    if ( wd->sta.txBeaconInd )
 455    {
 456        zm_debug_msg0("Can't sleep due to just transmit a beacon!");
 457        return;
 458    }
 459
 460    // If we buffer any data for the other stations. we could not go to sleep
 461    if ( wd->sta.ibssPrevPSDataCount != 0 )
 462    {
 463        zm_debug_msg0("Can't sleep due to buffering data for the others!");
 464        return;
 465    }
 466
 467    // before sleeping, we still need to notify the others by transmitting null
 468    // pkt with power mgmt bit turned on.
 469    zfPowerSavingMgrOnHandleT1(dev);
 470}
 471
 472static void zfPowerSavingMgrIBSSMain(zdev_t* dev)
 473{
 474    // wait for the end of
 475    // if need to wait to know if we are the one to transmit the beacon
 476    // during the beacon interval. If it's me, we can't go to sleep.
 477
 478    zmw_get_wlan_dev(dev);
 479
 480    switch(wd->sta.psMgr.state)
 481    {
 482        case ZM_PS_MSG_STATE_ACTIVE:
 483        case ZM_PS_MSG_STATE_SLEEP:
 484        case ZM_PS_MSG_STATE_T1:
 485            break;
 486
 487        case ZM_PS_MSG_STATE_T2:
 488            zfPowerSavingMgrOnHandleT2(dev);
 489            break;
 490    }
 491
 492    return;
 493}
 494
 495#if 1
 496void zfPowerSavingMgrMain(zdev_t* dev)
 497{
 498    zmw_get_wlan_dev(dev);
 499
 500    switch (wd->sta.adapterState)
 501    {
 502    case ZM_STA_STATE_DISCONNECT:
 503        zfPowerSavingMgrDisconnectMain(dev);
 504        break;
 505    case ZM_STA_STATE_CONNECTED:
 506        {
 507            if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) {
 508                zfPowerSavingMgrInfraMain(dev);
 509            } else if (wd->wlanMode == ZM_MODE_IBSS) {
 510                zfPowerSavingMgrIBSSMain(dev);
 511            }
 512        }
 513        break;
 514    case ZM_STA_STATE_CONNECTING:
 515    default:
 516        break;
 517    }
 518}
 519#else
 520void zfPowerSavingMgrMain(zdev_t* dev)
 521{
 522    zmw_get_wlan_dev(dev);
 523
 524    if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE )
 525    {
 526        return;
 527    }
 528
 529    switch(wd->sta.psMgr.state)
 530    {
 531        case ZM_PS_MSG_STATE_ACTIVE:
 532            goto check_sleep;
 533            break;
 534
 535        case ZM_PS_MSG_STATE_SLEEP:
 536            goto sleeping;
 537            break;
 538
 539        case ZM_PS_MSG_STATE_T1:
 540            zfPowerSavingMgrOnHandleT1(dev);
 541            break;
 542
 543        case ZM_PS_MSG_STATE_T2:
 544            zfPowerSavingMgrOnHandleT2(dev);
 545            break;
 546    }
 547
 548    return;
 549
 550sleeping:
 551    return;
 552
 553check_sleep:
 554    zfPowerSavingMgrSleepIfIdle(dev);
 555    return;
 556}
 557#endif
 558
 559#ifdef ZM_ENABLE_POWER_SAVE
 560void zfPowerSavingMgrWakeup(zdev_t* dev)
 561{
 562    zmw_get_wlan_dev(dev);
 563    zmw_declare_for_critical_section();
 564
 565//zm_debug_msg0("zfPowerSavingMgrWakeup");
 566
 567    //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE && ( zfPowerSavingMgrIsIdle(dev) == 0 ))
 568    if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE )
 569    {
 570        zmw_enter_critical_section(dev);
 571
 572        wd->sta.psMgr.isSleepAllowed = 0;
 573        wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
 574
 575        if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
 576            wd->sta.psMgr.tempWakeUp = 1;
 577
 578        zmw_leave_critical_section(dev);
 579
 580        // Wake up the CHIP now!!
 581        zfHpPowerSaveSetState(dev, 0);
 582    }
 583}
 584#else
 585void zfPowerSavingMgrWakeup(zdev_t* dev)
 586{
 587}
 588#endif
 589
 590void zfPowerSavingMgrProcessBeacon(zdev_t* dev, zbuf_t* buf)
 591{
 592    u8_t   length, bitmap;
 593    u16_t  offset, n1, n2, q, r;
 594    zbuf_t* psBuf;
 595
 596    zmw_get_wlan_dev(dev);
 597    zmw_declare_for_critical_section();
 598
 599    if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE  )
 600    //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_SLEEP )
 601    {
 602        return;
 603    }
 604
 605    wd->sta.psMgr.isSleepAllowed = 1;
 606
 607    if ( (offset=zfFindElement(dev, buf, ZM_WLAN_EID_TIM)) != 0xffff )
 608    {
 609        length = zmw_rx_buf_readb(dev, buf, offset+1);
 610
 611        if ( length > 3 )
 612        {
 613            n1 = zmw_rx_buf_readb(dev, buf, offset+4) & (~ZM_BIT_0);
 614            n2 = length + n1 - 4;
 615            q = wd->sta.aid >> 3;
 616            r = wd->sta.aid & 7;
 617
 618            if ((q >= n1) && (q <= n2))
 619            {
 620                bitmap = zmw_rx_buf_readb(dev, buf, offset+5+q-n1);
 621
 622                if ( (bitmap >> r) &  ZM_BIT_0 )
 623                {
 624                    //if ( wd->sta.powerSaveMode == ZM_STA_PS_FAST )
 625                    if ( 0 )
 626                    {
 627                        wd->sta.psMgr.state = ZM_PS_MSG_STATE_S1;
 628                        //zfSendPSPoll(dev);
 629                        zfSendNullData(dev, 0);
 630                    }
 631                    else
 632                    {
 633                        if ((wd->sta.qosInfo&0xf) != 0xf)
 634                        {
 635                            /* send ps-poll */
 636                            //printk("zfSendPSPoll #1\n");
 637
 638                            wd->sta.psMgr.isSleepAllowed = 0;
 639
 640                            switch (wd->sta.powerSaveMode)
 641                            {
 642                            case ZM_STA_PS_MAX:
 643                            case ZM_STA_PS_FAST:
 644                                //zm_debug_msg0("wake up and send PS-Poll\n");
 645                                zfSendPSPoll(dev);
 646                                break;
 647                            case ZM_STA_PS_LIGHT:
 648                                zm_debug_msg0("wake up and send null data\n");
 649
 650                                zmw_enter_critical_section(dev);
 651                                wd->sta.psMgr.sleepAllowedtick = 400;
 652                                zmw_leave_critical_section(dev);
 653
 654                                zfSendNullData(dev, 0);
 655                                break;
 656                            }
 657
 658                            wd->sta.psMgr.tempWakeUp = 0;
 659                        }
 660                    }
 661                }
 662            }
 663        }
 664    }
 665
 666    while ((psBuf = zfQueueGet(dev, wd->sta.uapsdQ)) != NULL)
 667    {
 668        zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
 669    }
 670
 671    //printk("zfPowerSavingMgrProcessBeacon #1\n");
 672    zfPowerSavingMgrMain(dev);
 673}
 674
 675void zfPowerSavingMgrConnectNotify(zdev_t *dev)
 676{
 677    zmw_get_wlan_dev(dev);
 678
 679    if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
 680    {
 681        switch(wd->sta.powerSaveMode)
 682        {
 683            case ZM_STA_PS_NONE:
 684                zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
 685                break;
 686
 687            case ZM_STA_PS_FAST:
 688            case ZM_STA_PS_MAX:
 689            case ZM_STA_PS_LIGHT:
 690                zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
 691                break;
 692
 693            default:
 694                zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
 695                break;
 696        }
 697    }
 698}
 699
 700void zfPowerSavingMgrPreTBTTInterrupt(zdev_t *dev)
 701{
 702    zmw_get_wlan_dev(dev);
 703    zmw_declare_for_critical_section();
 704
 705    /* disable TBTT interrupt when change from connection to disconnect */
 706    if (zfStaIsDisconnect(dev)) {
 707        zfHpPowerSaveSetMode(dev, 0, 0, 0);
 708        zfPowerSavingMgrWakeup(dev);
 709        return;
 710    }
 711
 712    zmw_enter_critical_section(dev);
 713    wd->sta.psMgr.ticks++;
 714
 715    if ( wd->sta.psMgr.ticks < wd->sta.psMgr.maxSleepPeriods )
 716    {
 717        zmw_leave_critical_section(dev);
 718        return;
 719    }
 720    else
 721    {
 722        wd->sta.psMgr.ticks = 0;
 723    }
 724
 725    zmw_leave_critical_section(dev);
 726
 727    zfPowerSavingMgrWakeup(dev);
 728}
 729
 730/* Leave an empty line below to remove warning message on some compiler */
 731
 732