linux/drivers/staging/vt6655/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
  46/*---------------------  Static Definitions -------------------------*/
  47
  48/*---------------------  Static Classes  ----------------------------*/
  49
  50extern unsigned short TxRate_iwconfig; //2008-5-8 <add> by chester
  51/*---------------------  Static Variables  --------------------------*/
  52//static int          msglevel                =MSG_LEVEL_DEBUG;
  53static int msglevel = MSG_LEVEL_INFO;
  54const unsigned char acbyIERate[MAX_RATE] =
  55{0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
  56
  57#define AUTORATE_TXOK_CNT       0x0400
  58#define AUTORATE_TXFAIL_CNT     0x0064
  59#define AUTORATE_TIMEOUT        10
  60
  61/*---------------------  Static Functions  --------------------------*/
  62
  63void s_vResetCounter(
  64        PKnownNodeDB psNodeDBTable
  65);
  66
  67void
  68s_vResetCounter(
  69        PKnownNodeDB psNodeDBTable
  70)
  71{
  72        unsigned char 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/*---------------------  Export Functions  --------------------------*/
  84
  85/*+
  86 *
  87 * Description:
  88 *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
  89 *
  90 * Parameters:
  91 *  In:
  92 *      unsigned char - Rate value in SuppRates IE or ExtSuppRates IE
  93 *  Out:
  94 *      none
  95 *
  96 * Return Value: RateIdx
  97 *
  98 -*/
  99unsigned char
 100DATARATEbyGetRateIdx(
 101        unsigned char byRate
 102)
 103{
 104        unsigned char ii;
 105
 106        //Erase basicRate flag.
 107        byRate = byRate & 0x7F;//0111 1111
 108
 109        for (ii = 0; ii < MAX_RATE; ii++) {
 110                if (acbyIERate[ii] == byRate)
 111                        return ii;
 112        }
 113        return 0;
 114}
 115
 116/*+
 117 *
 118 * Routine Description:
 119 *      Rate fallback Algorithm Implementation
 120 *
 121 * Parameters:
 122 *  In:
 123 *      pDevice         - Pointer to the adapter
 124 *      psNodeDBTable   - Pointer to Node Data Base
 125 *  Out:
 126 *      none
 127 *
 128 * Return Value: none
 129 *
 130 -*/
 131#define AUTORATE_TXCNT_THRESHOLD        20
 132#define AUTORATE_INC_THRESHOLD          30
 133
 134/*+
 135 *
 136 * Description:
 137 *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
 138 *
 139 * Parameters:
 140 *  In:
 141 *      unsigned char - Rate value in SuppRates IE or ExtSuppRates IE
 142 *  Out:
 143 *      none
 144 *
 145 * Return Value: RateIdx
 146 *
 147 -*/
 148unsigned short
 149wGetRateIdx(
 150        unsigned char byRate
 151)
 152{
 153        unsigned short ii;
 154
 155        //Erase basicRate flag.
 156        byRate = byRate & 0x7F;//0111 1111
 157
 158        for (ii = 0; ii < MAX_RATE; ii++) {
 159                if (acbyIERate[ii] == byRate)
 160                        return ii;
 161        }
 162        return 0;
 163}
 164
 165/*+
 166 *
 167 * Description:
 168 *      Parsing the highest basic & support rate in rate field of frame.
 169 *
 170 * Parameters:
 171 *  In:
 172 *      pDevice         - Pointer to the adapter
 173 *      pItemRates      - Pointer to Rate field defined in 802.11 spec.
 174 *      pItemExtRates      - Pointer to Extended Rate field defined in 802.11 spec.
 175 *  Out:
 176 *      pwMaxBasicRate  - Maximum Basic Rate
 177 *      pwMaxSuppRate   - Maximum Supported Rate
 178 *      pbyTopCCKRate   - Maximum Basic Rate in CCK mode
 179 *      pbyTopOFDMRate  - Maximum Basic Rate in OFDM mode
 180 *
 181 * Return Value: none
 182 *
 183 -*/
 184void
 185RATEvParseMaxRate(
 186        void *pDeviceHandler,
 187        PWLAN_IE_SUPP_RATES pItemRates,
 188        PWLAN_IE_SUPP_RATES pItemExtRates,
 189        bool bUpdateBasicRate,
 190        unsigned short *pwMaxBasicRate,
 191        unsigned short *pwMaxSuppRate,
 192        unsigned short *pwSuppRate,
 193        unsigned char *pbyTopCCKRate,
 194        unsigned char *pbyTopOFDMRate
 195)
 196{
 197        PSDevice  pDevice = (PSDevice) pDeviceHandler;
 198        unsigned int ii;
 199        unsigned char byHighSuppRate = 0;
 200        unsigned char byRate = 0;
 201        unsigned short wOldBasicRate = pDevice->wBasicRate;
 202        unsigned int uRateLen;
 203
 204        if (pItemRates == NULL)
 205                return;
 206
 207        *pwSuppRate = 0;
 208        uRateLen = pItemRates->len;
 209
 210        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate Len: %d\n", uRateLen);
 211        if (pDevice->eCurrentPHYType != PHY_TYPE_11B) {
 212                if (uRateLen > WLAN_RATES_MAXLEN)
 213                        uRateLen = WLAN_RATES_MAXLEN;
 214        } else {
 215                if (uRateLen > WLAN_RATES_MAXLEN_11B)
 216                        uRateLen = WLAN_RATES_MAXLEN_11B;
 217        }
 218
 219        for (ii = 0; ii < uRateLen; ii++) {
 220                byRate = (unsigned char)(pItemRates->abyRates[ii]);
 221                if (WLAN_MGMT_IS_BASICRATE(byRate) && bUpdateBasicRate)  {
 222                        // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
 223                        CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate));
 224                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate));
 225                }
 226                byRate = (unsigned char)(pItemRates->abyRates[ii]&0x7F);
 227                if (byHighSuppRate == 0)
 228                        byHighSuppRate = byRate;
 229                if (byRate > byHighSuppRate)
 230                        byHighSuppRate = byRate;
 231                *pwSuppRate |= (1<<wGetRateIdx(byRate));
 232        }
 233        if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
 234            (pDevice->eCurrentPHYType != PHY_TYPE_11B)) {
 235                unsigned int uExtRateLen = pItemExtRates->len;
 236
 237                if (uExtRateLen > WLAN_RATES_MAXLEN)
 238                        uExtRateLen = WLAN_RATES_MAXLEN;
 239
 240                for (ii = 0; ii < uExtRateLen; ii++) {
 241                        byRate = (unsigned char)(pItemExtRates->abyRates[ii]);
 242                        // select highest basic rate
 243                        if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
 244                                // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
 245                                CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate));
 246                                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate));
 247                        }
 248                        byRate = (unsigned char)(pItemExtRates->abyRates[ii]&0x7F);
 249                        if (byHighSuppRate == 0)
 250                                byHighSuppRate = byRate;
 251                        if (byRate > byHighSuppRate)
 252                                byHighSuppRate = byRate;
 253                        *pwSuppRate |= (1<<wGetRateIdx(byRate));
 254                        //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", wGetRateIdx(byRate), byRate));
 255                }
 256        } //if (pItemExtRates != NULL)
 257
 258        if ((pDevice->byPacketType == PK_TYPE_11GB) && CARDbIsOFDMinBasicRate((void *)pDevice)) {
 259                pDevice->byPacketType = PK_TYPE_11GA;
 260        }
 261
 262        *pbyTopCCKRate = pDevice->byTopCCKBasicRate;
 263        *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
 264        *pwMaxSuppRate = wGetRateIdx(byHighSuppRate);
 265        if ((pDevice->byPacketType == PK_TYPE_11B) || (pDevice->byPacketType == PK_TYPE_11GB))
 266                *pwMaxBasicRate = pDevice->byTopCCKBasicRate;
 267        else
 268                *pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
 269        if (wOldBasicRate != pDevice->wBasicRate)
 270                CARDvSetRSPINF((void *)pDevice, pDevice->eCurrentPHYType);
 271
 272        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Exit ParseMaxRate\n");
 273}
 274
 275/*+
 276 *
 277 * Routine Description:
 278 *      Rate fallback Algorithm Implementaion
 279 *
 280 * Parameters:
 281 *  In:
 282 *      pDevice         - Pointer to the adapter
 283 *      psNodeDBTable   - Pointer to Node Data Base
 284 *  Out:
 285 *      none
 286 *
 287 * Return Value: none
 288 *
 289 -*/
 290#define AUTORATE_TXCNT_THRESHOLD        20
 291#define AUTORATE_INC_THRESHOLD          30
 292
 293void
 294RATEvTxRateFallBack(
 295        void *pDeviceHandler,
 296        PKnownNodeDB psNodeDBTable
 297)
 298{
 299        PSDevice        pDevice = (PSDevice) pDeviceHandler;
 300        unsigned short wIdxDownRate = 0;
 301        unsigned int ii;
 302//unsigned long dwRateTable[MAX_RATE]  = {1,   2,   5,   11,  6,    9,    12,   18,  24,  36,  48,  54};
 303        bool bAutoRate[MAX_RATE]    = {true, true, true, true, false, false, true, true, true, true, true, true};
 304        unsigned long dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
 305        unsigned long dwThroughput = 0;
 306        unsigned short wIdxUpRate = 0;
 307        unsigned long dwTxDiff = 0;
 308
 309        if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) {
 310                // Don't do Fallback when scanning Channel
 311                return;
 312        }
 313
 314        psNodeDBTable->uTimeCount++;
 315
 316        if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
 317                dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
 318
 319        if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
 320            (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
 321            (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
 322                return;
 323        }
 324
 325        if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) {
 326                psNodeDBTable->uTimeCount = 0;
 327        }
 328
 329        for (ii = 0; ii < MAX_RATE; ii++) {
 330                if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
 331                        if (bAutoRate[ii]) {
 332                                wIdxUpRate = (unsigned short) ii;
 333                        }
 334                } else {
 335                        bAutoRate[ii] = false;
 336                }
 337        }
 338
 339        for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) {
 340                if ((psNodeDBTable->uTxOk[ii] != 0) ||
 341                    (psNodeDBTable->uTxFail[ii] != 0)) {
 342                        dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
 343                        if (ii < RATE_11M) {
 344                                psNodeDBTable->uTxFail[ii] *= 4;
 345                        }
 346                        dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
 347                }
 348//        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
 349//                       ii, psNodeDBTable->uTxOk[ii], psNodeDBTable->uTxFail[ii], dwThroughputTbl[ii]);
 350        }
 351        dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
 352
 353        wIdxDownRate = psNodeDBTable->wTxDataRate;
 354        for (ii = psNodeDBTable->wTxDataRate; ii > 0;) {
 355                ii--;
 356                if ((dwThroughputTbl[ii] > dwThroughput) && bAutoRate[ii]) {
 357                        dwThroughput = dwThroughputTbl[ii];
 358                        wIdxDownRate = (unsigned short) ii;
 359                }
 360        }
 361        psNodeDBTable->wTxDataRate = wIdxDownRate;
 362        if (psNodeDBTable->uTxOk[MAX_RATE]) {
 363                if (psNodeDBTable->uTxOk[MAX_RATE] >
 364                    (psNodeDBTable->uTxFail[MAX_RATE] * 4)) {
 365                        psNodeDBTable->wTxDataRate = wIdxUpRate;
 366                }
 367        } else { // adhoc, if uTxOk =0 & uTxFail = 0
 368                if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
 369                        psNodeDBTable->wTxDataRate = wIdxUpRate;
 370        }
 371//2008-5-8 <add> by chester
 372        TxRate_iwconfig = psNodeDBTable->wTxDataRate;
 373        s_vResetCounter(psNodeDBTable);
 374//    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Rate: %d, U:%d, D:%d\n", psNodeDBTable->wTxDataRate, wIdxUpRate, wIdxDownRate);
 375
 376        return;
 377}
 378
 379/*+
 380 *
 381 * Description:
 382 *    This routine is used to assemble available Rate IE.
 383 *
 384 * Parameters:
 385 *  In:
 386 *    pDevice
 387 *  Out:
 388 *
 389 * Return Value: None
 390 *
 391 -*/
 392unsigned char
 393RATEuSetIE(
 394        PWLAN_IE_SUPP_RATES pSrcRates,
 395        PWLAN_IE_SUPP_RATES pDstRates,
 396        unsigned int uRateLen
 397)
 398{
 399        unsigned int ii, uu, uRateCnt = 0;
 400
 401        if ((pSrcRates == NULL) || (pDstRates == NULL))
 402                return 0;
 403
 404        if (pSrcRates->len == 0)
 405                return 0;
 406
 407        for (ii = 0; ii < uRateLen; ii++) {
 408                for (uu = 0; uu < pSrcRates->len; uu++) {
 409                        if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
 410                                pDstRates->abyRates[uRateCnt++] = pSrcRates->abyRates[uu];
 411                                break;
 412                        }
 413                }
 414        }
 415        return (unsigned char)uRateCnt;
 416}
 417