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 "tmacro.h"
  37#include "mac.h"
  38#include "80211mgr.h"
  39#include "bssdb.h"
  40#include "datarate.h"
  41#include "card.h"
  42#include "baseband.h"
  43#include "rf.h"
  44
  45/* static int msglevel = MSG_LEVEL_DEBUG; */
  46static int msglevel = MSG_LEVEL_INFO;
  47static const u8 acbyIERate[MAX_RATE] = {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18,
  48        0x24, 0x30, 0x48, 0x60, 0x6C};
  49
  50#define AUTORATE_TXOK_CNT       0x0400
  51#define AUTORATE_TXFAIL_CNT     0x0064
  52#define AUTORATE_TIMEOUT        10
  53
  54void s_vResetCounter(PKnownNodeDB psNodeDBTable);
  55
  56void s_vResetCounter(PKnownNodeDB psNodeDBTable)
  57{
  58        u8 ii;
  59
  60        /* clear statistics counter for auto_rate */
  61        for (ii = 0; ii <= MAX_RATE; ii++) {
  62                psNodeDBTable->uTxOk[ii] = 0;
  63                psNodeDBTable->uTxFail[ii] = 0;
  64        }
  65}
  66
  67/*+
  68 *
  69 * Routine Description:
  70 *      Rate fallback Algorithm Implementaion
  71 *
  72 * Parameters:
  73 *  In:
  74 *      pDevice         - Pointer to the adapter
  75 *      psNodeDBTable   - Pointer to Node Data Base
  76 *  Out:
  77 *      none
  78 *
  79 * Return Value: none
  80 *
  81-*/
  82#define AUTORATE_TXCNT_THRESHOLD        20
  83#define AUTORATE_INC_THRESHOLD          30
  84
  85/*+
  86 *
  87 * Description:
  88 *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
  89 *
  90 * Parameters:
  91 *  In:
  92 *      u8    - Rate value in SuppRates IE or ExtSuppRates IE
  93 *  Out:
  94 *      none
  95 *
  96 * Return Value: RateIdx
  97 *
  98-*/
  99u16 RATEwGetRateIdx(u8 byRate)
 100{
 101        u16 ii;
 102
 103        /* erase BasicRate flag */
 104        byRate = byRate & 0x7F;
 105
 106        for (ii = 0; ii < MAX_RATE; ii++) {
 107                if (acbyIERate[ii] == byRate)
 108                        return ii;
 109        }
 110        return 0;
 111}
 112
 113/*+
 114 *
 115 * Description:
 116 *      Parsing the highest basic & support rate in rate field of frame.
 117 *
 118 * Parameters:
 119 *  In:
 120 *      pDevice         - Pointer to the adapter
 121 *      pItemRates      - Pointer to Rate field defined in 802.11 spec.
 122 *      pItemExtRates      - Pointer to Extended Rate field defined in 802.11 spec.
 123 *  Out:
 124 *      pwMaxBasicRate  - Maximum Basic Rate
 125 *      pwMaxSuppRate   - Maximum Supported Rate
 126 *      pbyTopCCKRate   - Maximum Basic Rate in CCK mode
 127 *      pbyTopOFDMRate  - Maximum Basic Rate in OFDM mode
 128 *
 129 * Return Value: none
 130 *
 131-*/
 132
 133void RATEvParseMaxRate(struct vnt_private *pDevice,
 134        PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pItemExtRates,
 135        int bUpdateBasicRate, u16 *pwMaxBasicRate, u16 *pwMaxSuppRate,
 136        u16 *pwSuppRate, u8 *pbyTopCCKRate, u8 *pbyTopOFDMRate)
 137{
 138        int ii;
 139        u8 byHighSuppRate = 0, byRate = 0;
 140        u16 wOldBasicRate = pDevice->wBasicRate;
 141        u32 uRateLen;
 142
 143        if (pItemRates == NULL)
 144                return;
 145
 146        *pwSuppRate = 0;
 147        uRateLen = pItemRates->len;
 148
 149        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen);
 150        if (pDevice->byBBType != BB_TYPE_11B) {
 151                if (uRateLen > WLAN_RATES_MAXLEN)
 152                        uRateLen = WLAN_RATES_MAXLEN;
 153        } else {
 154                if (uRateLen > WLAN_RATES_MAXLEN_11B)
 155                        uRateLen = WLAN_RATES_MAXLEN_11B;
 156        }
 157
 158        for (ii = 0; ii < uRateLen; ii++) {
 159                byRate = (u8)(pItemRates->abyRates[ii]);
 160                if (WLAN_MGMT_IS_BASICRATE(byRate) &&
 161                                (bUpdateBasicRate == true)) {
 162                        /*
 163                         * add to basic rate set, update pDevice->byTopCCKBasicRate and
 164                         * pDevice->byTopOFDMBasicRate
 165                         */
 166                        CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
 167                        DBG_PRT(MSG_LEVEL_DEBUG,
 168                                KERN_INFO"ParseMaxRate AddBasicRate: %d\n",
 169                                RATEwGetRateIdx(byRate));
 170                }
 171                byRate = (u8)(pItemRates->abyRates[ii]&0x7F);
 172                if (byHighSuppRate == 0)
 173                        byHighSuppRate = byRate;
 174                if (byRate > byHighSuppRate)
 175                        byHighSuppRate = byRate;
 176                *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
 177        }
 178        if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
 179                        (pDevice->byBBType != BB_TYPE_11B)) {
 180
 181                unsigned int uExtRateLen = pItemExtRates->len;
 182
 183                if (uExtRateLen > WLAN_RATES_MAXLEN)
 184                        uExtRateLen = WLAN_RATES_MAXLEN;
 185
 186                for (ii = 0; ii < uExtRateLen; ii++) {
 187                        byRate = (u8)(pItemExtRates->abyRates[ii]);
 188                        /* select highest basic rate */
 189                        if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
 190                                /*
 191                                 * add to basic rate set, update pDevice->byTopCCKBasicRate and
 192                                 * pDevice->byTopOFDMBasicRate
 193                                 */
 194                                CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
 195                                DBG_PRT(MSG_LEVEL_DEBUG,
 196                                                KERN_INFO"ParseMaxRate AddBasicRate: %d\n",
 197                                                RATEwGetRateIdx(byRate));
 198                        }
 199                        byRate = (u8)(pItemExtRates->abyRates[ii]&0x7F);
 200                        if (byHighSuppRate == 0)
 201                                byHighSuppRate = byRate;
 202                        if (byRate > byHighSuppRate)
 203                                byHighSuppRate = byRate;
 204                        *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
 205
 206                        /* DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n",
 207                         * RATEwGetRateIdx(byRate), byRate));
 208                         */
 209                }
 210        }
 211
 212        if ((pDevice->byPacketType == PK_TYPE_11GB)
 213                        && CARDbIsOFDMinBasicRate((void *)pDevice)) {
 214                pDevice->byPacketType = PK_TYPE_11GA;
 215        }
 216
 217        *pbyTopCCKRate = pDevice->byTopCCKBasicRate;
 218        *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
 219        *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate);
 220        if ((pDevice->byPacketType == PK_TYPE_11B) || (pDevice->byPacketType == PK_TYPE_11GB))
 221                *pwMaxBasicRate = pDevice->byTopCCKBasicRate;
 222        else
 223                *pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
 224        if (wOldBasicRate != pDevice->wBasicRate)
 225                CARDvSetRSPINF((void *)pDevice, pDevice->byBBType);
 226
 227        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
 228}
 229
 230/*+
 231 *
 232 * Routine Description:
 233 *      Rate fallback Algorithm Implementaion
 234 *
 235 * Parameters:
 236 *  In:
 237 *      pDevice         - Pointer to the adapter
 238 *      psNodeDBTable   - Pointer to Node Data Base
 239 *  Out:
 240 *      none
 241 *
 242 * Return Value: none
 243 *
 244-*/
 245#define AUTORATE_TXCNT_THRESHOLD        20
 246#define AUTORATE_INC_THRESHOLD          30
 247
 248void RATEvTxRateFallBack(struct vnt_private *pDevice,
 249        PKnownNodeDB psNodeDBTable)
 250{
 251        struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 252        u16 wIdxDownRate = 0;
 253        int ii;
 254        int bAutoRate[MAX_RATE] = {true, true, true, true, false, false, true,
 255                                         true, true, true, true, true};
 256        u32 dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180,
 257                240, 360, 480, 540};
 258        u32 dwThroughput = 0;
 259        u16 wIdxUpRate = 0;
 260        u32 dwTxDiff = 0;
 261
 262        if (pMgmt->eScanState != WMAC_NO_SCANNING)
 263                return; /* Don't do Fallback when scanning Channel */
 264
 265        psNodeDBTable->uTimeCount++;
 266
 267        if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
 268                dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
 269
 270        if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
 271                        (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
 272                        (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
 273                return;
 274        }
 275
 276        if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT)
 277                psNodeDBTable->uTimeCount = 0;
 278
 279        for (ii = 0; ii < MAX_RATE; ii++) {
 280                if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
 281                        if (bAutoRate[ii] == true)
 282                                wIdxUpRate = (u16) ii;
 283                } else {
 284                        bAutoRate[ii] = false;
 285                }
 286        }
 287
 288        for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) {
 289                if ((psNodeDBTable->uTxOk[ii] != 0) ||
 290                                (psNodeDBTable->uTxFail[ii] != 0)) {
 291                        dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
 292                        if (ii < RATE_11M)
 293                                psNodeDBTable->uTxFail[ii] *= 4;
 294                        dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
 295                }
 296                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
 297                                ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]);
 298        }
 299        dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
 300
 301        wIdxDownRate = psNodeDBTable->wTxDataRate;
 302        for (ii = psNodeDBTable->wTxDataRate; ii > 0;) {
 303                ii--;
 304                if ((dwThroughputTbl[ii] > dwThroughput) &&
 305                                (bAutoRate[ii] == true)) {
 306                        dwThroughput = dwThroughputTbl[ii];
 307                        wIdxDownRate = (u16) ii;
 308                }
 309        }
 310        psNodeDBTable->wTxDataRate = wIdxDownRate;
 311        if (psNodeDBTable->uTxOk[MAX_RATE]) {
 312                if (psNodeDBTable->uTxOk[MAX_RATE] >
 313                                (psNodeDBTable->uTxFail[MAX_RATE] * 4)) {
 314                        psNodeDBTable->wTxDataRate = wIdxUpRate;
 315                }
 316        } else { /* adhoc, if uTxOk(total) == 0 & uTxFail(total) == 0 */
 317                if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
 318                        psNodeDBTable->wTxDataRate = wIdxUpRate;
 319        }
 320
 321        if (pDevice->byBBType == BB_TYPE_11A) {
 322                if (psNodeDBTable->wTxDataRate <= RATE_11M)
 323                        psNodeDBTable->wTxDataRate = RATE_6M;
 324        }
 325        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]);
 326        s_vResetCounter(psNodeDBTable);
 327        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate);
 328        return;
 329}
 330
 331/*+
 332 *
 333 * Description:
 334 *    This routine is used to assemble available Rate IE.
 335 *
 336 * Parameters:
 337 *  In:
 338 *    pDevice
 339 *  Out:
 340 *
 341 * Return Value: None
 342 *
 343-*/
 344u8 RATEuSetIE(PWLAN_IE_SUPP_RATES pSrcRates, PWLAN_IE_SUPP_RATES pDstRates,
 345                unsigned int uRateLen)
 346{
 347        unsigned int ii, uu, uRateCnt = 0;
 348
 349        if ((pSrcRates == NULL) || (pDstRates == NULL))
 350                return 0;
 351
 352        if (pSrcRates->len == 0)
 353                return 0;
 354
 355        for (ii = 0; ii < uRateLen; ii++) {
 356                for (uu = 0; uu < pSrcRates->len; uu++) {
 357                        if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
 358                                pDstRates->abyRates[uRateCnt++] = pSrcRates->abyRates[uu];
 359                                break;
 360                        }
 361                }
 362        }
 363        return (u8)uRateCnt;
 364}
 365