linux/drivers/staging/otus/80211core/ratectrl.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#include "cprecomp.h"
  18#include "ratectrl.h"
  19
  20const u32_t zcRateToPhyCtrl[] =
  21    {
  22        /* 1M,        2M,         5M,        11M ,  0  1  2  3*/
  23        0x00000,    0x10000,    0x20000,    0x30000,
  24        /* 6M         9M          12M        18M ,  4  5  6  7*/
  25        0xb0001,    0xf0001,    0xa0001,    0xe0001,
  26        /* 24M         36M        48M        54M ,  8  9  10 11*/
  27        0x90001,    0xd0001,    0x80001,    0xc0001,
  28        /* MCS0      MCS1        MCS2        MCS3,  12 13 14 15*/
  29        0x00002,    0x10002,    0x20002,    0x30002,
  30        /* MCS4      MCS5        MCS6        MCS7,  16 17 18 19*/
  31        0x40002,    0x50002,    0x60002,    0x70002,
  32        /* MCS8      MCS9        MCS10       MCS11, 20 21 22 23*/
  33        0x80002,    0x90002,    0xa0002,    0xb0002,
  34        /* MCS12     MCS13       MCS14       MCS15, 24 25 26 27*/
  35        0xc0002,    0xd0002,    0xe0002,    0xf0002,
  36        /* MCS14SG,  MCS15SG     MCS7SG           , 28 29, 30*/
  37        0x800e0002, 0x800f0002, 0x80070002
  38    };
  39
  40
  41const u8_t zcHtRateTable[15][4] =
  42    { /*[5G 20MHz]  [5G 40MHz] [2.4G 20MHz]  [2.4G 40MHz]*/
  43        {  4,          4,          0,          0},   /*OFDM6M OFDM6M  CCK1M  CCK1M  */
  44        {  5,          5,          1,          1},   /*OFDM9M OFDM9M  CCK2M  CCK2M  */
  45        {  13,         12,         2,          2},   /*MCS1   MCS0    CCK5M  CCK5M  */
  46        {  14,         13,         3,          3},   /*MCS2   MCS1    CCK11M CCK11M */
  47        {  15,         14,         13,         12},  /*MCS3   MCS2    MCS1   MCS0   */
  48        {  16,         15,         14,         13},  /*MCS4   MCS3    MCS2   MCS1   */
  49        {  23,         16,         15,         14},  /*MCS11  MCS4    MCS3   MCS2   */
  50        {  24,         23,         16,         15},  /*MCS12  MCS11   MCS4   MCS3   */
  51        {  25,         24,         23,         16},  /*MCS13  MCS12   MCS11  MCS4   */
  52        {  26,         25,         24,         23},  /*MCS14  MCS13   MCS12  MCS11  */
  53        {  27,         26,         25,         24},  /*MCS15  MCS14   MCS13  MCS12  */
  54        {  0,          27,         26,         25},  /*0      MCS15   MCS14  MCS13  */
  55        {  0,          29,         27,         26},  /*0      MCS15SG MCS15  MCS14  */
  56        {  0,          0,          0,          28},  /*0      0       0      MCS14SG*/
  57        {  0,          0,          0,          29}   /*0      0       0      MCS15SG*/
  58    };
  59
  60const u8_t zcHtOneTxStreamRateTable[15][4] =
  61    { /*[5G 20MHz]  [5G 40MHz] [2.4G 20MHz]  [2.4G 40MHz]*/
  62        {  4,          4,          0,          0},   /*OFDM6M OFDM6M  CCK1M  CCK1M  */
  63        {  5,          5,          1,          1},   /*OFDM9M OFDM9M  CCK2M  CCK2M  */
  64        {  13,         12,         2,          2},   /*MCS1   MCS0    CCK5M  CCK5M  */
  65        {  14,         13,         3,          3},   /*MCS2   MCS1    CCK11M CCK11M */
  66        {  15,         14,         13,         12},  /*MCS3   MCS2    MCS1   MCS0   */
  67        {  16,         15,         14,         13},  /*MCS4   MCS3    MCS2   MCS1   */
  68        {  17,         16,         15,         14},  /*MCS5   MCS4    MCS3   MCS2   */
  69        {  18,         17,         16,         15},  /*MCS6   MCS5    MCS4   MCS3   */
  70        {  19,         18,         17,         16},  /*MCS7   MCS6    MCS5   MCS4   */
  71        {  0,          19,         18,         17},  /*0      MCS7    MCS6   MCS5   */
  72        {  0,          30,         19,         18},  /*0      MCS7SG  MCS7   MCS6   */
  73        {  0,          0,          0,          19},  /*0      0       0      MCS7   */
  74        {  0,          0,          0,          30},  /*0      0       0      MCS7SG */
  75        {  0,          0,          0,          0 },  /*0      0       0      0      */
  76        {  0,          0,          0,          0 }   /*0      0       0      0      */
  77    };
  78
  79const u16_t zcRate[] =
  80    {
  81        1, 2, 5, 11,                  /* 1M, 2M, 5M, 11M          ,  0  1  2  3*/
  82        6, 9, 12, 18,                 /* 6M  9M  12M  18M         ,  4  5  6  7*/
  83        24, 36, 48, 54,               /* 24M  36M  48M  54M       ,  8  9 10 11*/
  84        13, 27, 40, 54,               /* MCS0 MCS1 MCS2 MCS3      , 12 13 14 15*/
  85        81, 108, 121, 135,            /* MCS4 MCS5 MCS6 MCS7      , 16 17 18 19*/
  86        27, 54, 81, 108,              /* MCS8 MCS9 MCS10 MCS11    , 20 21 22 23*/
  87        162, 216, 243, 270,           /* MCS12 MCS13 MCS14 MCS15  , 24 25 26 27*/
  88        270, 300, 150                 /* MCS14SG, MCS15SG, MCS7SG , 28 29 30*/
  89    };
  90
  91const u16_t PERThreshold[] =
  92    {
  93        100, 50, 50, 50,    /* 1M, 2M, 5M, 11M          ,  0  1  2  3*/
  94        50, 50, 30, 30,     /* 6M  9M  12M  18M         ,  4  5  6  7*/
  95        25, 25, 25, 20,     /* 24M  36M  48M  54M       ,  8  9 10 11*/
  96        50, 50, 50, 40,    /* MCS0 MCS1 MCS2 MCS3      , 12 13 14 15*/
  97        30, 30, 30, 30,    /* MCS4 MCS5 MCS6 MCS7      , 16 17 18 19*/
  98        30, 30, 25, 25,    /* MCS8 MCS9 MCS10 MCS11    , 20 21 22 23*/
  99        25, 25, 15, 15,     /* MCS12 MCS13 MCS14 MCS15  , 24 25 26 27*/
 100        15, 15, 10          /* MCS14SG, MCS15SG         , 28 29*/
 101    };
 102
 103const u16_t FailDiff[] =
 104    {
 105        40, 46, 40, 0,          /* 1M, 2M, 5M, 11M          ,  0  1  2  3*/
 106        24, 17, 22, 16,         /* 6M  9M  12M  18M         ,  4  5  6  7*/
 107        19, 13, 5, 0,           /* 24M  36M  48M  54M       ,  8  9 10 11*/
 108        36, 22, 15, 19,         /* MCS0 MCS1 MCS2 MCS3      , 12 13 14 15*/
 109        12, 5, 4, 7,            /* MCS4 MCS5 MCS6 MCS7      , 16 17 18 19*/
 110        0, 0, 0, 0,             /* MCS8 MCS9 MCS10 MCS11    , 20 21 22 23*/
 111        9, 4, 3, 3,             /* MCS12 MCS13 MCS14 MCS15  , 24 25 26 27*/
 112        3, 0, 0                 /* MCS14SG, MCS15SG         , 28 29*/
 113    };
 114
 115
 116#ifdef ZM_ENABLE_BA_RATECTRL
 117u32_t TxMPDU[29];
 118u32_t BAFail[29];
 119u32_t BAPER[29];
 120const u16_t BADiff[] =
 121    {
 122        0, 0, 0, 0,
 123        0, 0, 0, 0,
 124        0, 0, 0, 0,
 125        361, 220, 151, 187,
 126        122, 48, 41, 65,
 127        0, 0, 0, 0,
 128        88, 33, 27, 25,
 129        0
 130    };
 131#endif
 132
 133/************************************************************************/
 134/*                                                                      */
 135/*    FUNCTION DESCRIPTION                  zfRateCtrlInitCell          */
 136/*      Initialize rate control cell.                                   */
 137/*                                                                      */
 138/*    INPUTS                                                            */
 139/*      dev : device pointer                                            */
 140/*      type : 0=>11b, 1=>11a/g, 2=>11n, 3=>11n one Tx stream           */
 141/*      gBand : 1=>2.4G, 0=>5G                                          */
 142/*                                                                      */
 143/*    OUTPUTS                                                           */
 144/*      None                                                            */
 145/*                                                                      */
 146/*    AUTHOR                                                            */
 147/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 148/*                                                                      */
 149/************************************************************************/
 150void zfRateCtrlInitCell(zdev_t* dev, struct zsRcCell* rcCell, u8_t type,
 151        u8_t gBand, u8_t SG40)
 152{
 153    u8_t i;
 154    u8_t maxrate;
 155    zmw_get_wlan_dev(dev);
 156
 157    if (SG40) SG40 = 1;
 158
 159    if (gBand != 0)
 160    {
 161        if (type == 1) //11g
 162        {
 163            for (i=0; i<4; i++) //1M 2M 5M 11M
 164            {
 165                rcCell->operationRateSet[i] = (u8_t)i;
 166            }
 167            for (i=4; i<10; i++) //12M 18M 24M 36M 48M 54M
 168            {
 169                rcCell->operationRateSet[i] = 2+i;
 170            }
 171            rcCell->operationRateCount = 10;
 172            rcCell->currentRateIndex = 5; //18M
 173        }
 174        else if (type == 2) //11ng
 175        {
 176            if (wd->wlanMode == ZM_MODE_AP) //AP 11ng 40M
 177            {
 178                for (i=0; i<15; i++)
 179                {
 180                    rcCell->operationRateSet[i] = zcHtRateTable[i][3];
 181                }
 182                if(!SG40) rcCell->operationRateSet[13] = 27;
 183                rcCell->operationRateCount = 14+SG40;
 184                rcCell->currentRateIndex = 10;
 185            }
 186            else //STA
 187            {
 188                if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M
 189                {
 190                    for (i=0; i<15; i++)
 191                    {
 192                        rcCell->operationRateSet[i] = zcHtRateTable[i][3];
 193                    }
 194                    if(!SG40) rcCell->operationRateSet[13] = 27;
 195                    rcCell->operationRateCount = 14+SG40;
 196                    rcCell->currentRateIndex = 10;
 197                }
 198                else    //11ng 20M
 199                {
 200                    for (i=0; i<13; i++)
 201                    {
 202                        rcCell->operationRateSet[i] = zcHtRateTable[i][2];
 203                    }
 204                    rcCell->operationRateCount = 13;
 205                    rcCell->currentRateIndex = 9;
 206                }
 207            }
 208        }
 209        else if (type == 3) //11ng one Tx stream
 210        {
 211                if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M one Tx stream
 212                {
 213                    if(SG40 != 0)
 214                    {
 215                        maxrate = 13;
 216                    }
 217                    else
 218                    {
 219                        maxrate = 12;
 220                    }
 221                    for (i=0; i<maxrate; i++)
 222                    {
 223                        rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][3];
 224                    }
 225                    rcCell->operationRateCount = i;
 226                    rcCell->currentRateIndex = ((i+1)*3)/4;
 227                }
 228                else    //11ng 20M
 229                {
 230                    for (i=0; i<11; i++)
 231                    {
 232                        rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][2];
 233                    }
 234                    rcCell->operationRateCount = i;
 235                    rcCell->currentRateIndex = ((i+1)*3)/4;
 236                }
 237        }
 238        else //if (type == 0) //11b
 239        {
 240            for (i=0; i<4; i++)
 241            {
 242                rcCell->operationRateSet[i] = (u8_t)i;
 243            }
 244            rcCell->operationRateCount = 4;
 245            rcCell->currentRateIndex = rcCell->operationRateCount-1;
 246        }
 247    }
 248    else
 249    {
 250        if (type == 2) //11na
 251        {
 252            if (wd->wlanMode == ZM_MODE_AP) //AP 11na 40M
 253            {
 254                for (i=0; i<(12+SG40); i++)
 255                {
 256                    rcCell->operationRateSet[i] = zcHtRateTable[i][1];
 257                }
 258                rcCell->operationRateCount = 12+SG40;
 259                rcCell->currentRateIndex = 8;
 260            }
 261            else //STA
 262            {
 263                if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M
 264                {
 265                    for (i=0; i<(12+SG40); i++)
 266                    {
 267                        rcCell->operationRateSet[i] = zcHtRateTable[i][1];
 268                    }
 269                    rcCell->operationRateCount = 12+SG40;
 270                    rcCell->currentRateIndex = 8;
 271                }
 272                else    //11na 20M
 273                {
 274                    for (i=0; i<11; i++)
 275                    {
 276                        rcCell->operationRateSet[i] = zcHtRateTable[i][0];
 277                    }
 278                    rcCell->operationRateCount = 11;
 279                    rcCell->currentRateIndex = 7;
 280                }
 281            }
 282        }
 283        else if (type == 3) //11na one Tx stream
 284        {
 285                if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M one Tx stream
 286                {
 287                    if(SG40 != 0)
 288                    {
 289                        maxrate = 11;
 290                    }
 291                    else
 292                    {
 293                        maxrate = 10;
 294                    }
 295                    for (i=0; i<maxrate; i++)
 296                    {
 297                        rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][1];
 298                    }
 299                    rcCell->operationRateCount = i;
 300                    rcCell->currentRateIndex = ((i+1)*3)/4;
 301                }
 302                else    //11ng 20M
 303                {
 304                    for (i=0; i<9; i++)
 305                    {
 306                        rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][0];
 307                    }
 308                    rcCell->operationRateCount = i;
 309                    rcCell->currentRateIndex = ((i+1)*3)/4;
 310                }
 311        }
 312        else //if (type == 1) //11a
 313        {
 314            for (i=0; i<8; i++) //6M 9M 12M 18M 24M 36M 48M 54M
 315            {
 316                rcCell->operationRateSet[i] = i+4;
 317            }
 318            rcCell->operationRateCount = 8;
 319            rcCell->currentRateIndex = 4;  //24M
 320        }
 321    }
 322
 323    rcCell->flag = 0;
 324    rcCell->txCount = 0;
 325    rcCell->failCount = 0;
 326    rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
 327    rcCell->lasttxCount = 0;
 328    rcCell->lastTime    = wd->tick;
 329    rcCell->probingTime = wd->tick;
 330    for (i=0; i<ZM_RATE_TABLE_SIZE; i++) {
 331        wd->PER[i] = 0;
 332        wd->txMPDU[i] = wd->txFail[i] = 0;
 333    }
 334    wd->probeCount = 0;
 335    wd->probeInterval = 0;
 336#ifdef ZM_ENABLE_BA_RATECTRL
 337    for (i=0; i<29; i++) {
 338        TxMPDU[i]=0;
 339        BAFail[i]=0;
 340        BAPER[i]=0;
 341    }
 342#endif
 343    return;
 344}
 345
 346
 347/************************************************************************/
 348/*                                                                      */
 349/*    FUNCTION DESCRIPTION                  zfRateCtrlGetHigherRate     */
 350/*      Get a higher rate.                                              */
 351/*                                                                      */
 352/*    INPUTS                                                            */
 353/*      rcCell : rate control cell                                      */
 354/*                                                                      */
 355/*    OUTPUTS                                                           */
 356/*      rate                                                            */
 357/*                                                                      */
 358/*    AUTHOR                                                            */
 359/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 360/*                                                                      */
 361/************************************************************************/
 362u8_t zfRateCtrlGetHigherRate(struct zsRcCell* rcCell)
 363{
 364    u8_t rateIndex;
 365
 366    rateIndex = rcCell->currentRateIndex
 367            + (((rcCell->currentRateIndex+1) < rcCell->operationRateCount)?1:0);
 368    return rcCell->operationRateSet[rateIndex];
 369}
 370
 371
 372/************************************************************************/
 373/*                                                                      */
 374/*    FUNCTION DESCRIPTION                  zfRateCtrlNextLowerRate     */
 375/*      Get a lower rate.                                               */
 376/*                                                                      */
 377/*    INPUTS                                                            */
 378/*      rcCell : rate control cell                                      */
 379/*                                                                      */
 380/*    OUTPUTS                                                           */
 381/*      rate                                                            */
 382/*                                                                      */
 383/*    AUTHOR                                                            */
 384/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 385/*                                                                      */
 386/************************************************************************/
 387u8_t zfRateCtrlNextLowerRate(zdev_t* dev, struct zsRcCell* rcCell)
 388{
 389    zmw_get_wlan_dev(dev);
 390    if (rcCell->currentRateIndex > 0)
 391    {
 392        rcCell->currentRateIndex--;
 393        rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
 394    }
 395    zm_msg1_tx(ZM_LV_0, "Lower Tx Rate=", rcCell->currentRate);
 396    //DbgPrint("Lower Tx Rate=%d", rcCell->currentRate);
 397    rcCell->failCount = rcCell->txCount = 0;
 398    rcCell->lasttxCount = 0;
 399    rcCell->lastTime  = wd->tick;
 400    return rcCell->currentRate;
 401}
 402
 403
 404/************************************************************************/
 405/*                                                                      */
 406/*    FUNCTION DESCRIPTION                  zfRateCtrlRateDiff          */
 407/*      Rate difference.                                                */
 408/*                                                                      */
 409/*    INPUTS                                                            */
 410/*      rcCell : rate control cell                                      */
 411/*      retryRate : retry rate                                          */
 412/*                                                                      */
 413/*    OUTPUTS                                                           */
 414/*      rate difference                                                 */
 415/*                                                                      */
 416/*    AUTHOR                                                            */
 417/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 418/*                                                                      */
 419/************************************************************************/
 420u8_t zfRateCtrlRateDiff(struct zsRcCell* rcCell, u8_t retryRate)
 421{
 422    u16_t i;
 423
 424    /* Find retryRate in operationRateSet[] */
 425    for (i=0; i<rcCell->operationRateCount; i++)
 426    {
 427        if (retryRate == rcCell->operationRateSet[i])
 428        {
 429            if (i < rcCell->currentRateIndex)
 430            {
 431                return ((rcCell->currentRateIndex - i)+1)>>1;
 432            }
 433            else if (i == rcCell->currentRateIndex == 0)
 434            {
 435                return 1;
 436            }
 437            else
 438            {
 439                return 0;
 440            }
 441        }
 442    }
 443    /* TODO : retry rate not in operation rate set */
 444    zm_msg1_tx(ZM_LV_0, "Not in operation rate set:", retryRate);
 445    return 1;
 446
 447}
 448
 449u32_t zfRateCtrlUDPTP(zdev_t* dev, u16_t Rate, u32_t PER) {
 450    if ((PER < 100) && (Rate > 0) && PER)
 451        return 1168000/(((12304/Rate)+197)*(100+100*PER/(100-PER)));
 452    else
 453        return 0;
 454}
 455
 456u8_t zfRateCtrlFindMaxUDPTP(zdev_t* dev, struct zsRcCell* rcCell) {
 457    u8_t i, maxIndex=0, rateIndex;
 458    u32_t max=0, UDPThroughput;
 459
 460    zmw_get_wlan_dev(dev);
 461
 462    rateIndex = zm_agg_min(rcCell->currentRateIndex+3, rcCell->operationRateCount-1);
 463    for (i=rcCell->currentRateIndex; i < rateIndex; i++) {
 464        UDPThroughput = zfRateCtrlUDPTP(dev, zcRate[rcCell->operationRateSet[i]],
 465            wd->PER[rcCell->operationRateSet[i]]);
 466        if (max < UDPThroughput) {
 467            max = UDPThroughput;
 468            maxIndex = i;
 469        }
 470    }
 471
 472    return rcCell->operationRateSet[maxIndex];
 473}
 474/************************************************************************/
 475/*                                                                      */
 476/*    FUNCTION DESCRIPTION                  zfRateCtrlGetTxRate         */
 477/*      Get transmission rate.                                          */
 478/*                                                                      */
 479/*    INPUTS                                                            */
 480/*      dev : device pointer                                            */
 481/*      rcCell : rate control cell                                      */
 482/*      probing : rate probing flag                                     */
 483/*                                                                      */
 484/*    OUTPUTS                                                           */
 485/*      Tx rate                                                         */
 486/*                                                                      */
 487/*    AUTHOR                                                            */
 488/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 489/*                                                                      */
 490/************************************************************************/
 491u16_t zfRateCtrlGetTxRate(zdev_t* dev, struct zsRcCell* rcCell, u16_t* probing)
 492{
 493    u8_t newRate, highRate;
 494    zmw_get_wlan_dev(dev);
 495
 496    zm_msg1_tx(ZM_LV_3, "txCount=", rcCell->txCount);
 497    zm_msg1_tx(ZM_LV_3, "probingTime=", rcCell->probingTime);
 498    zm_msg1_tx(ZM_LV_3, "tick=", wd->tick);
 499    *probing = 0;
 500    newRate = rcCell->currentRate;
 501
 502    if (wd->probeCount && (wd->probeCount < wd->success_probing))
 503    {
 504        if (wd->probeInterval < 50)
 505        {
 506            wd->probeInterval++;
 507        }
 508        else
 509        {
 510            wd->probeInterval++;
 511            if (wd->probeInterval > 52) //probe 51, 52, 53 three packets every 50 packets
 512            {
 513                wd->probeInterval = 0;
 514            }
 515            newRate=zfRateCtrlGetHigherRate(rcCell);
 516            *probing = 1;
 517            wd->probeCount++;
 518            rcCell->probingTime = wd->tick;
 519        }
 520    }
 521    /* Accumulate at least 1000ms and 8 packets or Accumulate over 1K packets */
 522    else if ((((wd->tick - rcCell->probingTime) > (ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK))
 523                && (rcCell->txCount >= ZM_RATE_CTRL_MIN_PROBING_PACKET))
 524        || (rcCell->txCount >= 1000))
 525    {
 526#ifndef ZM_DISABLE_RATE_CTRL
 527        /* PER = fail/total */
 528        wd->probeCount = 0;
 529        wd->probeSuccessCount = 0;
 530        if (wd->txMPDU[rcCell->currentRate] != 0) {
 531            wd->PER[rcCell->currentRate] = zm_agg_min(100,
 532                (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
 533            if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
 534        }
 535
 536        /* if PER < threshold, do rate probing, return probing rate */
 537        if ((wd->PER[rcCell->currentRate] <= (ZM_RATE_PROBING_THRESHOLD+15)) ||
 538            ((rcCell->currentRate <= 16) &&
 539            ((wd->PER[rcCell->currentRate]/2) <= ZM_RATE_PROBING_THRESHOLD)))
 540        {
 541            if ((newRate=zfRateCtrlGetHigherRate(rcCell)) != rcCell->currentRate)
 542            {
 543                *probing = 1;
 544                wd->probeCount++;
 545                wd->probeInterval = 0;
 546                wd->success_probing =
 547                    (rcCell->currentRate <= 16)? (ZM_RATE_SUCCESS_PROBING/2) : ZM_RATE_SUCCESS_PROBING;
 548                //DbgPrint("Start Probing");
 549                zm_msg1_tx(ZM_LV_0, "Probing Rate=", newRate);
 550            }
 551        }
 552#endif
 553
 554        zm_msg0_tx(ZM_LV_1, "Diminish counter");
 555        rcCell->failCount = rcCell->failCount>>1;
 556        rcCell->txCount = rcCell->txCount>>1;
 557        wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
 558        wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
 559
 560
 561        if (rcCell->currentRate > 15) {
 562            highRate = zfRateCtrlGetHigherRate(rcCell);
 563            if ((highRate != rcCell->currentRate) && wd->PER[highRate] &&
 564                ((wd->PER[rcCell->currentRate] + FailDiff[rcCell->currentRate]) >
 565                wd->PER[highRate])) {
 566                //DbgPrint("PER compare force raise rate to %d", highRate);
 567                wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
 568                zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
 569            }
 570        }
 571        else {
 572            highRate = zfRateCtrlFindMaxUDPTP(dev, rcCell);
 573            if (rcCell->currentRate < highRate) {
 574                //DbgPrint("UDP Throughput compare force raise rate to %d", highRate);
 575                wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
 576                zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
 577            }
 578        }
 579        rcCell->probingTime = wd->tick;
 580    }
 581
 582    if( (wd->tick > 1000)
 583        && ((wd->tick - rcCell->lastTime) > 3840) )
 584    {
 585        if (rcCell->lasttxCount < 70)
 586        {
 587            rcCell->failCount = rcCell->failCount>>1;
 588            rcCell->txCount = rcCell->txCount>>1;
 589            wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
 590            wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
 591
 592            rcCell->failCount = (rcCell->failCount < rcCell->txCount)?
 593                                rcCell->failCount : rcCell->txCount;
 594            wd->txFail[rcCell->currentRate] = (wd->txFail[rcCell->currentRate] < wd->txMPDU[rcCell->currentRate])?
 595                                              wd->txFail[rcCell->currentRate] : wd->txMPDU[rcCell->currentRate];
 596        }
 597
 598        rcCell->lastTime    = wd->tick;
 599        rcCell->lasttxCount = 0;
 600    }
 601
 602    rcCell->txCount++;
 603    rcCell->lasttxCount++;
 604    wd->txMPDU[rcCell->currentRate]++;
 605    zm_msg1_tx(ZM_LV_1, "Get Tx Rate=", newRate);
 606    return newRate;
 607}
 608
 609
 610/************************************************************************/
 611/*                                                                      */
 612/*    FUNCTION DESCRIPTION                  zfRateCtrlTxFailEvent       */
 613/*      Tx fail event. Calculate PER and lower Tx rate if under         */
 614/*      PER under threshold.                                            */
 615/*                                                                      */
 616/*    INPUTS                                                            */
 617/*      rcCell : rate control cell                                      */
 618/*      retryRate : retry rate                                          */
 619/*                                                                      */
 620/*    OUTPUTS                                                           */
 621/*      None                                                            */
 622/*                                                                      */
 623/*    AUTHOR                                                            */
 624/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 625/*                                                                      */
 626/************************************************************************/
 627void zfRateCtrlTxFailEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t aggRate, u32_t retryRate)
 628{
 629    zmw_get_wlan_dev(dev);
 630
 631    zmw_declare_for_critical_section();
 632
 633#ifndef ZM_DISABLE_RATE_CTRL
 634    //DbgPrint("aggRate=%d, retryRate=%d", aggRate, retryRate);
 635    if (aggRate && (aggRate != rcCell->currentRate)) {
 636        wd->txFail[aggRate] += retryRate;
 637        return;
 638    }
 639
 640    if (!aggRate) {
 641        retryRate = (zfRateCtrlRateDiff(rcCell, (u8_t)retryRate)+1)>>1;
 642        if (rcCell->currentRate <12) //legacy rate
 643        {
 644            retryRate*=2;
 645        }
 646    }
 647    rcCell->failCount += retryRate;
 648    wd->txFail[rcCell->currentRate] += retryRate;
 649
 650    //DbgPrint("failCount=%d", rcCell->failCount);
 651    if (rcCell->failCount > ZM_MIN_RATE_FAIL_COUNT)
 652    {
 653        if (wd->txMPDU[rcCell->currentRate] != 0) {
 654            wd->PER[rcCell->currentRate] = zm_agg_min(100,
 655                (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
 656            if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
 657        }
 658        //zm_msg1_tx(ZM_LV_1, "PER=", per);
 659        //DbgPrint("PER=%d, txFail=%d, txMPDU=%d", wd->PER[rcCell->currentRate], wd->txFail[rcCell->currentRate], wd->txMPDU[rcCell->currentRate]);
 660        if (wd->PER[rcCell->currentRate] > PERThreshold[rcCell->currentRate])
 661        {
 662            /* Lower Tx Rate if PER < THRESHOLD */
 663            zfRateCtrlNextLowerRate(dev, rcCell);
 664            rcCell->flag |= ZM_RC_TRAINED_BIT;
 665
 666            // Resolve compatibility problem with Marvell
 667            if(rcCell->currentRate == 15)
 668            {
 669                zmw_leave_critical_section(dev);
 670                zfHpSetAggPktNum(dev, 8);
 671                zmw_enter_critical_section(dev);
 672            }
 673
 674            wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
 675            wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
 676
 677            wd->probeCount = wd->probeSuccessCount = 0;
 678        }
 679    }
 680
 681#endif
 682    return;
 683}
 684
 685
 686/************************************************************************/
 687/*                                                                      */
 688/*    FUNCTION DESCRIPTION                  zfRateCtrlTxSuccessEvent    */
 689/*      Tx success event. Raise Tx rate because rate probing success.   */
 690/*                                                                      */
 691/*    INPUTS                                                            */
 692/*      rcCell : rate control cell                                      */
 693/*      successRate : success rate                                      */
 694/*                                                                      */
 695/*    OUTPUTS                                                           */
 696/*      None                                                            */
 697/*                                                                      */
 698/*    AUTHOR                                                            */
 699/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 700/*                                                                      */
 701/************************************************************************/
 702void zfRateCtrlTxSuccessEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t successRate)
 703{
 704    /* Raise Tx Rate */
 705    u16_t i, PERProbe;
 706    u16_t pcount;
 707    zmw_get_wlan_dev(dev);
 708
 709    zmw_declare_for_critical_section();
 710
 711    //DbgPrint("Probing successRate=%d", successRate);
 712    /* Find successRate in operationRateSet[] */
 713    wd->probeSuccessCount++;
 714    if (wd->probeCount < wd->success_probing)
 715    {
 716        return;
 717    }
 718
 719    pcount = wd->probeCount;
 720    if (pcount != 0)
 721    {
 722        PERProbe = wd->probeSuccessCount * 100 / pcount;
 723    }
 724    else
 725    {
 726        PERProbe = 1;
 727    }
 728
 729    if (PERProbe < ((rcCell->currentRate < 16)? 80:100))
 730    {
 731        return;
 732    }
 733    //DbgPrint("wd->probeCount=%d, wd->probeSuccessCount=%d", wd->probeCount, wd->probeSuccessCount);
 734    wd->probeCount = wd->probeSuccessCount = 0;
 735    for (i=0; i<rcCell->operationRateCount; i++)
 736    {
 737        if (successRate == rcCell->operationRateSet[i])
 738        {
 739            if (i > rcCell->currentRateIndex)
 740            {
 741                /* Raise current Tx rate */
 742                zm_msg1_tx(ZM_LV_0, "Raise Tx Rate=", successRate);
 743                //DbgPrint("Raise Tx Rate=%d", successRate);
 744
 745                // Resolve compatibility problem with Marvell
 746                if((rcCell->currentRate <= 15) && (successRate > 15))
 747                {
 748                    zmw_leave_critical_section(dev);
 749                    zfHpSetAggPktNum(dev, 16);
 750                    zmw_enter_critical_section(dev);
 751                }
 752
 753                rcCell->currentRate = successRate;
 754                rcCell->currentRateIndex = (u8_t)i;
 755                rcCell->failCount = rcCell->txCount = 0;
 756                rcCell->lasttxCount = 0;
 757                rcCell->lastTime  = wd->tick;
 758                wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
 759                wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
 760            }
 761        }
 762    }
 763
 764    return;
 765}
 766
 767
 768/************************************************************************/
 769/*                                                                      */
 770/*    FUNCTION DESCRIPTION                  zfRateCtrlRxRssiEvent       */
 771/*      Rx RSSI event. Calculate RSSI moving average, accelarate        */
 772/*      rate probing if RSSI variation over threshold.                  */
 773/*                                                                      */
 774/*    INPUTS                                                            */
 775/*      rcCell : rate control cell                                      */
 776/*      successRate : success rate                                      */
 777/*                                                                      */
 778/*    OUTPUTS                                                           */
 779/*      None                                                            */
 780/*                                                                      */
 781/*    AUTHOR                                                            */
 782/*      Stephen Chen        Atheros Communications, INC.    2007.2      */
 783/*                                                                      */
 784/************************************************************************/
 785void zfRateCtrlRxRssiEvent(struct zsRcCell* rcCell, u16_t rxRssi)
 786{
 787    /* if delta(rcCell->rxRssi, rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION */
 788    if ((rcCell->rxRssi - rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION)
 789    {
 790        /* Accelerate rate probing via decreaing rcCell->probingTime */
 791        rcCell->probingTime -= ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK;
 792    }
 793
 794    /* Update RSSI moving average */
 795    rcCell->rxRssi = (((rcCell->rxRssi*7) + rxRssi)+4) >> 3;
 796    return;
 797}
 798
 799
 800#ifdef ZM_ENABLE_BA_RATECTRL
 801u8_t HigherRate(u8_t Rate) {
 802    if (Rate < 28) Rate++; //28=MCS15SG, 27=MCS15, 26=MCS14, 25=MCS13
 803    if (Rate > 28) Rate = 28;
 804    while ((Rate >= 20) && (Rate <= 23)) {
 805        Rate ++;
 806    }
 807    return Rate;
 808}
 809
 810u8_t LowerRate(u8_t Rate) {
 811    if (Rate > 1) Rate--;
 812    while ((Rate >= 20) && (Rate <= 23)) {
 813        Rate --;
 814    }
 815    return Rate;
 816}
 817
 818u8_t RateMapToRateIndex(u8_t Rate, struct zsRcCell* rcCell) {
 819    u8_t i;
 820    for (i=0; i<rcCell->operationRateCount; i++) {
 821        if (Rate == rcCell->operationRateSet[i]) {
 822            return i;
 823        }
 824    }
 825    return 0;
 826}
 827
 828void zfRateCtrlAggrSta(zdev_t* dev) {
 829    u8_t RateIndex, Rate;
 830    u8_t HRate;
 831    u8_t LRate;
 832    u32_t RateCtrlTxMPDU, RateCtrlBAFail;
 833    zmw_get_wlan_dev(dev);
 834
 835    RateIndex = wd->sta.oppositeInfo[0].rcCell.currentRateIndex;
 836    Rate = wd->sta.oppositeInfo[0].rcCell.operationRateSet[RateIndex];
 837
 838    TxMPDU[Rate] = (TxMPDU[Rate] / 5) + (wd->commTally.RateCtrlTxMPDU * 4 / 5);
 839    BAFail[Rate] = (BAFail[Rate] / 5) + (wd->commTally.RateCtrlBAFail * 4 / 5);
 840    RateCtrlTxMPDU = wd->commTally.RateCtrlTxMPDU;
 841    RateCtrlBAFail = wd->commTally.RateCtrlBAFail;
 842    wd->commTally.RateCtrlTxMPDU = 0;
 843    wd->commTally.RateCtrlBAFail = 0;
 844    if (TxMPDU[Rate] > 0) {
 845        BAPER[Rate] = BAFail[Rate] * 1000 / TxMPDU[Rate]; //PER*1000
 846        BAPER[Rate] = (BAPER[Rate]>0)? BAPER[Rate]:1;
 847    }
 848    else {
 849        return;
 850    }
 851
 852    HRate = HigherRate(Rate);
 853    LRate = LowerRate(Rate);
 854    if (BAPER[Rate]>200) {
 855        if ((RateCtrlTxMPDU > 100) && (BAPER[Rate]<300) && (HRate != Rate) && BAPER[HRate] &&
 856            (BAPER[HRate] < BAPER[Rate] + BADiff[Rate])) {
 857            Rate = HRate;
 858            //DbgPrint("Rate improved to %d", Rate);
 859        }
 860        else {
 861            Rate = LRate;
 862            //DbgPrint("Rate decreased to %d", Rate);
 863        }
 864    }
 865    else if (BAPER[Rate] && BAPER[Rate]<100) {
 866        if (RateCtrlTxMPDU > 100) {
 867            Rate = HRate;
 868            //DbgPrint("Rate improved to %d", Rate);
 869        }
 870    }
 871    wd->sta.oppositeInfo[0].rcCell.currentRate = Rate;
 872    wd->sta.oppositeInfo[0].rcCell.currentRateIndex = RateMapToRateIndex(Rate, &wd->sta.oppositeInfo[0].rcCell);
 873}
 874#endif
 875