linux/drivers/staging/vt6656/datarate.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
   3 * All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along
  16 * with this program; if not, write to the Free Software Foundation, Inc.,
  17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18 *
  19 * File: datarate.c
  20 *
  21 * Purpose: Handles the auto fallback & data rates functions
  22 *
  23 * Author: Lyndon Chen
  24 *
  25 * Date: July 17, 2002
  26 *
  27 * Functions:
  28 *      RATEvParseMaxRate - Parsing the highest basic & support rate in rate field of frame
  29 *      RATEvTxRateFallBack - Rate fallback Algorithm Implementaion
  30 *      RATEuSetIE- Set rate IE field.
  31 *
  32 * Revision History:
  33 *
  34 */
  35
  36#include "ttype.h"
  37#include "tmacro.h"
  38#include "mac.h"
  39#include "80211mgr.h"
  40#include "bssdb.h"
  41#include "datarate.h"
  42#include "card.h"
  43#include "baseband.h"
  44#include "srom.h"
  45#include "rf.h"
  46
  47/*---------------------  Static Definitions -------------------------*/
  48
  49
  50
  51
  52/*---------------------  Static Classes  ----------------------------*/
  53
  54
  55
  56/*---------------------  Static Variables  --------------------------*/
  57//static int          msglevel                =MSG_LEVEL_DEBUG;
  58static int          msglevel                =MSG_LEVEL_INFO;
  59const BYTE acbyIERate[MAX_RATE] =
  60{0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
  61
  62#define AUTORATE_TXOK_CNT       0x0400
  63#define AUTORATE_TXFAIL_CNT     0x0064
  64#define AUTORATE_TIMEOUT        10
  65
  66/*---------------------  Static Functions  --------------------------*/
  67
  68void s_vResetCounter(PKnownNodeDB psNodeDBTable);
  69
  70void s_vResetCounter(PKnownNodeDB psNodeDBTable)
  71{
  72    BYTE            ii;
  73
  74    // clear statistic counter for auto_rate
  75    for(ii=0;ii<=MAX_RATE;ii++) {
  76        psNodeDBTable->uTxOk[ii] = 0;
  77        psNodeDBTable->uTxFail[ii] = 0;
  78    }
  79}
  80
  81/*---------------------  Export Variables  --------------------------*/
  82
  83
  84/*---------------------  Export Functions  --------------------------*/
  85
  86
  87/*+
  88 *
  89 * Description:
  90 *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
  91 *
  92 * Parameters:
  93 *  In:
  94 *      BYTE    - Rate value in SuppRates IE or ExtSuppRates IE
  95 *  Out:
  96 *      none
  97 *
  98 * Return Value: RateIdx
  99 *
 100-*/
 101BYTE
 102DATARATEbyGetRateIdx (
 103     BYTE byRate
 104    )
 105{
 106    BYTE    ii;
 107
 108    //Erase basicRate flag.
 109    byRate = byRate & 0x7F;//0111 1111
 110
 111    for (ii = 0; ii < MAX_RATE; ii ++) {
 112        if (acbyIERate[ii] == byRate)
 113            return ii;
 114    }
 115    return 0;
 116}
 117
 118
 119
 120/*+
 121 *
 122 * Routine Description:
 123 *      Rate fallback Algorithm Implementaion
 124 *
 125 * Parameters:
 126 *  In:
 127 *      pDevice         - Pointer to the adapter
 128 *      psNodeDBTable   - Pointer to Node Data Base
 129 *  Out:
 130 *      none
 131 *
 132 * Return Value: none
 133 *
 134-*/
 135#define AUTORATE_TXCNT_THRESHOLD        20
 136#define AUTORATE_INC_THRESHOLD          30
 137
 138
 139
 140
 141/*+
 142 *
 143 * Description:
 144 *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
 145 *
 146 * Parameters:
 147 *  In:
 148 *      BYTE    - Rate value in SuppRates IE or ExtSuppRates IE
 149 *  Out:
 150 *      none
 151 *
 152 * Return Value: RateIdx
 153 *
 154-*/
 155WORD
 156RATEwGetRateIdx(
 157     BYTE byRate
 158    )
 159{
 160    WORD    ii;
 161
 162    //Erase basicRate flag.
 163    byRate = byRate & 0x7F;//0111 1111
 164
 165    for (ii = 0; ii < MAX_RATE; ii ++) {
 166        if (acbyIERate[ii] == byRate)
 167            return ii;
 168    }
 169    return 0;
 170}
 171
 172/*+
 173 *
 174 * Description:
 175 *      Parsing the highest basic & support rate in rate field of frame.
 176 *
 177 * Parameters:
 178 *  In:
 179 *      pDevice         - Pointer to the adapter
 180 *      pItemRates      - Pointer to Rate field defined in 802.11 spec.
 181 *      pItemExtRates      - Pointer to Extended Rate field defined in 802.11 spec.
 182 *  Out:
 183 *      pwMaxBasicRate  - Maximum Basic Rate
 184 *      pwMaxSuppRate   - Maximum Supported Rate
 185 *      pbyTopCCKRate   - Maximum Basic Rate in CCK mode
 186 *      pbyTopOFDMRate  - Maximum Basic Rate in OFDM mode
 187 *
 188 * Return Value: none
 189 *
 190-*/
 191void RATEvParseMaxRate(
 192     void *pDeviceHandler,
 193     PWLAN_IE_SUPP_RATES pItemRates,
 194     PWLAN_IE_SUPP_RATES pItemExtRates,
 195     BOOL bUpdateBasicRate,
 196     PWORD pwMaxBasicRate,
 197     PWORD pwMaxSuppRate,
 198     PWORD pwSuppRate,
 199     PBYTE pbyTopCCKRate,
 200     PBYTE pbyTopOFDMRate
 201    )
 202{
 203PSDevice  pDevice = (PSDevice) pDeviceHandler;
 204unsigned int  ii;
 205BYTE  byHighSuppRate = 0;
 206BYTE  byRate = 0;
 207WORD  wOldBasicRate = pDevice->wBasicRate;
 208unsigned int  uRateLen;
 209
 210
 211    if (pItemRates == NULL)
 212        return;
 213
 214    *pwSuppRate = 0;
 215    uRateLen = pItemRates->len;
 216
 217    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen);
 218    if (pDevice->byBBType != BB_TYPE_11B) {
 219        if (uRateLen > WLAN_RATES_MAXLEN)
 220            uRateLen = WLAN_RATES_MAXLEN;
 221    } else {
 222        if (uRateLen > WLAN_RATES_MAXLEN_11B)
 223            uRateLen = WLAN_RATES_MAXLEN_11B;
 224    }
 225
 226    for (ii = 0; ii < uRateLen; ii++) {
 227        byRate = (BYTE)(pItemRates->abyRates[ii]);
 228        if (WLAN_MGMT_IS_BASICRATE(byRate) &&
 229            (bUpdateBasicRate == TRUE))  {
 230            // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
 231                CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
 232            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
 233        }
 234        byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F);
 235        if (byHighSuppRate == 0)
 236            byHighSuppRate = byRate;
 237        if (byRate > byHighSuppRate)
 238            byHighSuppRate = byRate;
 239        *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
 240    }
 241    if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
 242        (pDevice->byBBType != BB_TYPE_11B)) {
 243
 244        unsigned int uExtRateLen = pItemExtRates->len;
 245
 246        if (uExtRateLen > WLAN_RATES_MAXLEN)
 247            uExtRateLen = WLAN_RATES_MAXLEN;
 248
 249        for (ii = 0; ii < uExtRateLen ; ii++) {
 250            byRate = (BYTE)(pItemExtRates->abyRates[ii]);
 251            // select highest basic rate
 252            if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
 253                // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
 254                    CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
 255                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
 256            }
 257            byRate = (BYTE)(pItemExtRates->abyRates[ii]&0x7F);
 258            if (byHighSuppRate == 0)
 259                byHighSuppRate = byRate;
 260            if (byRate > byHighSuppRate)
 261                byHighSuppRate = byRate;
 262            *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
 263            //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", RATEwGetRateIdx(byRate), byRate));
 264        }
 265    } //if(pItemExtRates != NULL)
 266
 267    if ((pDevice->byPacketType == PK_TYPE_11GB)
 268        && CARDbIsOFDMinBasicRate((void *)pDevice)) {
 269        pDevice->byPacketType = PK_TYPE_11GA;
 270    }
 271
 272    *pbyTopCCKRate = pDevice->byTopCCKBasicRate;
 273    *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
 274    *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate);
 275    if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB))
 276       *pwMaxBasicRate = pDevice->byTopCCKBasicRate;
 277    else
 278       *pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
 279    if (wOldBasicRate != pDevice->wBasicRate)
 280        CARDvSetRSPINF((void *)pDevice, pDevice->byBBType);
 281
 282     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
 283}
 284
 285
 286/*+
 287 *
 288 * Routine Description:
 289 *      Rate fallback Algorithm Implementaion
 290 *
 291 * Parameters:
 292 *  In:
 293 *      pDevice         - Pointer to the adapter
 294 *      psNodeDBTable   - Pointer to Node Data Base
 295 *  Out:
 296 *      none
 297 *
 298 * Return Value: none
 299 *
 300-*/
 301#define AUTORATE_TXCNT_THRESHOLD        20
 302#define AUTORATE_INC_THRESHOLD          30
 303
 304void
 305RATEvTxRateFallBack(
 306     void *pDeviceHandler,
 307     PKnownNodeDB psNodeDBTable
 308    )
 309{
 310PSDevice        pDevice = (PSDevice) pDeviceHandler;
 311PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
 312#if 1  //mike fixed old: use packet lose ratio algorithm to control rate
 313WORD            wIdxDownRate = 0;
 314unsigned int            ii;
 315BOOL            bAutoRate[MAX_RATE]    = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE};
 316DWORD           dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
 317DWORD           dwThroughput = 0;
 318WORD            wIdxUpRate = 0;
 319DWORD           dwTxDiff = 0;
 320
 321    if (pMgmt->eScanState != WMAC_NO_SCANNING) {
 322        // Don't do Fallback when scanning Channel
 323        return;
 324    }
 325    psNodeDBTable->uTimeCount ++;
 326
 327    if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
 328        dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
 329
 330    if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
 331        (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
 332        (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
 333        return;
 334    }
 335
 336    if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) {
 337        psNodeDBTable->uTimeCount = 0;
 338    }
 339
 340    for(ii=0;ii<MAX_RATE;ii++) {
 341        if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
 342            if (bAutoRate[ii] == TRUE) {
 343                wIdxUpRate = (WORD) ii;
 344            }
 345        } else {
 346            bAutoRate[ii] = FALSE;
 347        }
 348    }
 349
 350    for(ii=0;ii<=psNodeDBTable->wTxDataRate;ii++) {
 351        if ( (psNodeDBTable->uTxOk[ii] != 0) ||
 352             (psNodeDBTable->uTxFail[ii] != 0) ) {
 353            dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
 354            if (ii < RATE_11M) {
 355                psNodeDBTable->uTxFail[ii] *= 4;
 356            }
 357            dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
 358        }
 359        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
 360                       ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]);
 361    }
 362    dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
 363
 364    wIdxDownRate = psNodeDBTable->wTxDataRate;
 365    for(ii = psNodeDBTable->wTxDataRate; ii > 0;) {
 366        ii--;
 367        if ( (dwThroughputTbl[ii] > dwThroughput) &&
 368             (bAutoRate[ii]==TRUE) ) {
 369            dwThroughput = dwThroughputTbl[ii];
 370            wIdxDownRate = (WORD) ii;
 371        }
 372    }
 373    psNodeDBTable->wTxDataRate = wIdxDownRate;
 374    if (psNodeDBTable->uTxOk[MAX_RATE]) {
 375        if (psNodeDBTable->uTxOk[MAX_RATE] >
 376           (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) {
 377            psNodeDBTable->wTxDataRate = wIdxUpRate;
 378        }
 379    }else { // adhoc, if uTxOk(total) =0 & uTxFail(total) = 0
 380        if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
 381            psNodeDBTable->wTxDataRate = wIdxUpRate;
 382    }
 383
 384    if (pDevice->byBBType == BB_TYPE_11A) {
 385        if (psNodeDBTable->wTxDataRate <= RATE_11M)
 386            psNodeDBTable->wTxDataRate = RATE_6M;
 387    }
 388    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uTxOk[MAX_RATE] %d, uTxFail[MAX_RATE]:%d\n",(int)psNodeDBTable->uTxOk[MAX_RATE], (int)psNodeDBTable->uTxFail[MAX_RATE]);
 389    s_vResetCounter(psNodeDBTable);
 390    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate);
 391    return;
 392#else  //mike fixed new: use differ-signal strength to control rate
 393WORD            wIdxUpRate = 0;
 394BOOL            bAutoRate[MAX_RATE]    = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE};
 395unsigned int            ii;
 396long  ldBm;
 397
 398    if (pMgmt->eScanState != WMAC_NO_SCANNING) {
 399        // Don't do Fallback when scanning Channel
 400        return;
 401    }
 402
 403    for(ii=0;ii<MAX_RATE;ii++) {
 404        if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
 405            if (bAutoRate[ii] == TRUE) {
 406                wIdxUpRate = (WORD) ii;
 407            }
 408        } else {
 409            bAutoRate[ii] = FALSE;
 410        }
 411    }
 412
 413         RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
 414
 415        if (ldBm > -55) {
 416                if ( psNodeDBTable->wSuppRate & (0x0001<<RATE_54M) )  //11a/g
 417                {
 418                        psNodeDBTable->wTxDataRate = RATE_54M;
 419                }
 420                else{ //11b
 421                        psNodeDBTable->wTxDataRate = RATE_11M;
 422                }
 423        }
 424
 425if (wIdxUpRate == RATE_54M ) {     //11a/g
 426                if (ldBm > -56 )
 427                        psNodeDBTable->wTxDataRate = RATE_54M;
 428                else if (ldBm > -61 )
 429                        psNodeDBTable->wTxDataRate = RATE_48M;
 430                else if (ldBm > -66 )
 431                        psNodeDBTable->wTxDataRate = RATE_36M;
 432                else if (ldBm > -72 )
 433                        psNodeDBTable->wTxDataRate = RATE_24M;
 434                else if (ldBm > -80 )
 435                        psNodeDBTable->wTxDataRate = RATE_5M;
 436                else {
 437                        psNodeDBTable->wTxDataRate = RATE_1M;
 438                        //increasingVGA = TRUE;
 439                }
 440        }
 441        else {  //11b
 442                if (ldBm > -65 )
 443                        psNodeDBTable->wTxDataRate = RATE_11M;
 444                else if (ldBm > -75 )
 445                        psNodeDBTable->wTxDataRate = RATE_5M;
 446                else
 447                        psNodeDBTable->wTxDataRate = RATE_1M;
 448        }
 449
 450   return;
 451#endif
 452}
 453
 454/*+
 455 *
 456 * Description:
 457 *    This routine is used to assemble available Rate IE.
 458 *
 459 * Parameters:
 460 *  In:
 461 *    pDevice
 462 *  Out:
 463 *
 464 * Return Value: None
 465 *
 466-*/
 467BYTE
 468RATEuSetIE (
 469     PWLAN_IE_SUPP_RATES pSrcRates,
 470     PWLAN_IE_SUPP_RATES pDstRates,
 471     unsigned int                uRateLen
 472    )
 473{
 474    unsigned int ii, uu, uRateCnt = 0;
 475
 476    if ((pSrcRates == NULL) || (pDstRates == NULL))
 477        return 0;
 478
 479    if (pSrcRates->len == 0)
 480        return 0;
 481
 482    for (ii = 0; ii < uRateLen; ii++) {
 483        for (uu = 0; uu < pSrcRates->len; uu++) {
 484            if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
 485                pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu];
 486                break;
 487            }
 488        }
 489    }
 490    return (BYTE)uRateCnt;
 491}
 492
 493
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.