linux/drivers/staging/rtl8187se/r8180_dm.c
<<
>>
Prefs
   1//#include "r8180.h"
   2#include "r8180_dm.h"
   3#include "r8180_hw.h"
   4#include "r8180_93cx6.h"
   5//{by amy 080312
   6
   7//
   8//      Description:
   9//              Return TRUE if we shall perform High Power Mecahnism, FALSE otherwise.
  10//
  11//+by amy 080312
  12#define RATE_ADAPTIVE_TIMER_PERIOD      300
  13
  14bool CheckHighPower(struct net_device *dev)
  15{
  16        struct r8180_priv *priv = ieee80211_priv(dev);
  17        struct ieee80211_device *ieee = priv->ieee80211;
  18
  19        if(!priv->bRegHighPowerMechanism)
  20        {
  21                return false;
  22        }
  23
  24        if(ieee->state == IEEE80211_LINKED_SCANNING)
  25        {
  26                return false;
  27        }
  28
  29        return true;
  30}
  31
  32//
  33//      Description:
  34//              Update Tx power level if necessary.
  35//              See also DoRxHighPower() and SetTxPowerLevel8185() for reference.
  36//
  37//      Note:
  38//              The reason why we udpate Tx power level here instead of DoRxHighPower()
  39//              is the number of IO to change Tx power is much more than channel TR switch
  40//              and they are related to OFDM and MAC registers.
  41//              So, we don't want to update it so frequently in per-Rx packet base.
  42//
  43void
  44DoTxHighPower(
  45        struct net_device *dev
  46        )
  47{
  48        struct r8180_priv *priv = ieee80211_priv(dev);
  49        u16                     HiPwrUpperTh = 0;
  50        u16                     HiPwrLowerTh = 0;
  51        u8                      RSSIHiPwrUpperTh;
  52        u8                      RSSIHiPwrLowerTh;
  53        u8                      u1bTmp;
  54        char                    OfdmTxPwrIdx, CckTxPwrIdx;
  55
  56        //printk("----> DoTxHighPower()\n");
  57
  58        HiPwrUpperTh = priv->RegHiPwrUpperTh;
  59        HiPwrLowerTh = priv->RegHiPwrLowerTh;
  60
  61        HiPwrUpperTh = HiPwrUpperTh * 10;
  62        HiPwrLowerTh = HiPwrLowerTh * 10;
  63        RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh;
  64        RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh;
  65
  66        //lzm add 080826
  67        OfdmTxPwrIdx  = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
  68        CckTxPwrIdx  = priv->chtxpwr[priv->ieee80211->current_network.channel];
  69
  70        //      printk("DoTxHighPower() - UndecoratedSmoothedSS:%d, CurCCKRSSI = %d , bCurCCKPkt= %d \n", priv->UndecoratedSmoothedSS, priv->CurCCKRSSI, priv->bCurCCKPkt );
  71
  72        if((priv->UndecoratedSmoothedSS > HiPwrUpperTh) ||
  73                (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh)))
  74        {
  75                // Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah
  76
  77        //      printk("=====>DoTxHighPower() - High Power - UndecoratedSmoothedSS:%d,  HiPwrUpperTh = %d \n", priv->UndecoratedSmoothedSS, HiPwrUpperTh );
  78                priv->bToUpdateTxPwr = true;
  79                u1bTmp= read_nic_byte(dev, CCK_TXAGC);
  80
  81                // If it never enter High Power.
  82                if( CckTxPwrIdx == u1bTmp)
  83                {
  84                u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0;  // 8dbm
  85                write_nic_byte(dev, CCK_TXAGC, u1bTmp);
  86
  87                u1bTmp= read_nic_byte(dev, OFDM_TXAGC);
  88                u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0;  // 8dbm
  89                write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
  90                }
  91
  92        }
  93        else if((priv->UndecoratedSmoothedSS < HiPwrLowerTh) &&
  94                (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh))
  95        {
  96        //       printk("DoTxHighPower() - lower Power - UndecoratedSmoothedSS:%d,  HiPwrUpperTh = %d \n", priv->UndecoratedSmoothedSS, HiPwrLowerTh );
  97                if(priv->bToUpdateTxPwr)
  98                {
  99                        priv->bToUpdateTxPwr = false;
 100                        //SD3 required.
 101                        u1bTmp= read_nic_byte(dev, CCK_TXAGC);
 102                        if(u1bTmp < CckTxPwrIdx)
 103                        {
 104                        //u1bTmp = ((u1bTmp+16) > 35) ? 35: (u1bTmp+16);  // 8dbm
 105                        //write_nic_byte(dev, CCK_TXAGC, u1bTmp);
 106                        write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx);
 107                        }
 108
 109                        u1bTmp= read_nic_byte(dev, OFDM_TXAGC);
 110                        if(u1bTmp < OfdmTxPwrIdx)
 111                        {
 112                        //u1bTmp = ((u1bTmp+16) > 35) ? 35: (u1bTmp+16);  // 8dbm
 113                        //write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
 114                        write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
 115                        }
 116                }
 117        }
 118
 119        //printk("<---- DoTxHighPower()\n");
 120}
 121
 122
 123//
 124//      Description:
 125//              Callback function of UpdateTxPowerWorkItem.
 126//              Because of some event happened, e.g. CCX TPC, High Power Mechanism,
 127//              We update Tx power of current channel again.
 128//
 129void rtl8180_tx_pw_wq (struct work_struct *work)
 130{
 131//      struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
 132//      struct ieee80211_device * ieee = (struct ieee80211_device*)
 133//                                             container_of(work, struct ieee80211_device, watch_dog_wq);
 134        struct delayed_work *dwork = to_delayed_work(work);
 135        struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,tx_pw_wq);
 136        struct net_device *dev = ieee->dev;
 137
 138//      printk("----> UpdateTxPowerWorkItemCallback()\n");
 139
 140        DoTxHighPower(dev);
 141
 142//      printk("<---- UpdateTxPowerWorkItemCallback()\n");
 143}
 144
 145
 146//
 147//      Description:
 148//              Return TRUE if we shall perform DIG Mecahnism, FALSE otherwise.
 149//
 150bool
 151CheckDig(
 152        struct net_device *dev
 153        )
 154{
 155        struct r8180_priv *priv = ieee80211_priv(dev);
 156        struct ieee80211_device *ieee = priv->ieee80211;
 157
 158        if(!priv->bDigMechanism)
 159                return false;
 160
 161        if(ieee->state != IEEE80211_LINKED)
 162                return false;
 163
 164        //if(priv->CurrentOperaRate < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01.
 165        if((priv->ieee80211->rate/5) < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01.
 166                return false;
 167        return true;
 168}
 169//
 170//      Description:
 171//              Implementation of DIG for Zebra and Zebra2.
 172//
 173void
 174DIG_Zebra(
 175        struct net_device *dev
 176        )
 177{
 178        struct r8180_priv *priv = ieee80211_priv(dev);
 179        u16                     CCKFalseAlarm, OFDMFalseAlarm;
 180        u16                     OfdmFA1, OfdmFA2;
 181        int                     InitialGainStep = 7; // The number of initial gain stages.
 182        int                     LowestGainStage = 4; // The capable lowest stage of performing dig workitem.
 183        u32                     AwakePeriodIn2Sec=0;
 184
 185        //printk("---------> DIG_Zebra()\n");
 186
 187        CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff);
 188        OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff);
 189        OfdmFA1 =  0x15;
 190        OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8;
 191
 192//      printk("DIG**********CCK False Alarm: %#X \n",CCKFalseAlarm);
 193//      printk("DIG**********OFDM False Alarm: %#X \n",OFDMFalseAlarm);
 194
 195        // The number of initial gain steps is different, by Bruce, 2007-04-13.
 196        if (priv->InitialGain == 0 ) //autoDIG
 197        { // Advised from SD3 DZ
 198                priv->InitialGain = 4; // In 87B, m74dBm means State 4 (m82dBm)
 199        }
 200        { // Advised from SD3 DZ
 201                OfdmFA1 =  0x20;
 202        }
 203
 204#if 1 //lzm reserved 080826
 205        AwakePeriodIn2Sec = (2000-priv ->DozePeriodInPast2Sec);
 206        //printk("&&& DozePeriod=%d AwakePeriod=%d\n", priv->DozePeriodInPast2Sec, AwakePeriodIn2Sec);
 207        priv ->DozePeriodInPast2Sec=0;
 208
 209        if(AwakePeriodIn2Sec)
 210        {
 211                //RT_TRACE(COMP_DIG, DBG_TRACE, ("DIG: AwakePeriodIn2Sec(%d) - FATh(0x%X , 0x%X) ->",AwakePeriodIn2Sec, OfdmFA1, OfdmFA2));
 212                // adjuest DIG threshold.
 213                OfdmFA1 =  (u16)((OfdmFA1*AwakePeriodIn2Sec)  / 2000) ;
 214                OfdmFA2 =  (u16)((OfdmFA2*AwakePeriodIn2Sec)  / 2000) ;
 215                //RT_TRACE(COMP_DIG, DBG_TRACE, ("( 0x%X , 0x%X)\n", OfdmFA1, OfdmFA2));
 216        }
 217        else
 218        {
 219                ;//RT_TRACE(COMP_DIG, DBG_WARNING, ("ERROR!!  AwakePeriodIn2Sec should not be ZERO!!\n"));
 220        }
 221#endif
 222
 223        InitialGainStep = 8;
 224        LowestGainStage = priv->RegBModeGainStage; // Lowest gain stage.
 225
 226        if (OFDMFalseAlarm > OfdmFA1)
 227        {
 228                if (OFDMFalseAlarm > OfdmFA2)
 229                {
 230                        priv->DIG_NumberFallbackVote++;
 231                        if (priv->DIG_NumberFallbackVote >1)
 232                        {
 233                                //serious OFDM  False Alarm, need fallback
 234                                if (priv->InitialGain < InitialGainStep)
 235                                {
 236                                        priv->InitialGainBackUp= priv->InitialGain;
 237
 238                                        priv->InitialGain = (priv->InitialGain + 1);
 239//                                      printk("DIG**********OFDM False Alarm: %#X,  OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2);
 240//                                      printk("DIG+++++++ fallback OFDM:%d \n", priv->InitialGain);
 241                                        UpdateInitialGain(dev);
 242                                }
 243                                priv->DIG_NumberFallbackVote = 0;
 244                                priv->DIG_NumberUpgradeVote=0;
 245                        }
 246                }
 247                else
 248                {
 249                        if (priv->DIG_NumberFallbackVote)
 250                                priv->DIG_NumberFallbackVote--;
 251                }
 252                priv->DIG_NumberUpgradeVote=0;
 253        }
 254        else
 255        {
 256                if (priv->DIG_NumberFallbackVote)
 257                        priv->DIG_NumberFallbackVote--;
 258                priv->DIG_NumberUpgradeVote++;
 259
 260                if (priv->DIG_NumberUpgradeVote>9)
 261                {
 262                        if (priv->InitialGain > LowestGainStage) // In 87B, m78dBm means State 4 (m864dBm)
 263                        {
 264                                priv->InitialGainBackUp= priv->InitialGain;
 265
 266                                priv->InitialGain = (priv->InitialGain - 1);
 267//                              printk("DIG**********OFDM False Alarm: %#X,  OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2);
 268//                              printk("DIG--------- Upgrade OFDM:%d \n", priv->InitialGain);
 269                                UpdateInitialGain(dev);
 270                        }
 271                        priv->DIG_NumberFallbackVote = 0;
 272                        priv->DIG_NumberUpgradeVote=0;
 273                }
 274        }
 275
 276//      printk("DIG+++++++ OFDM:%d\n", priv->InitialGain);
 277        //printk("<--------- DIG_Zebra()\n");
 278}
 279
 280//
 281//      Description:
 282//              Dispatch DIG implementation according to RF.
 283//
 284void
 285DynamicInitGain(struct net_device *dev)
 286{
 287        DIG_Zebra(dev);
 288}
 289
 290void rtl8180_hw_dig_wq (struct work_struct *work)
 291{
 292        struct delayed_work *dwork = to_delayed_work(work);
 293        struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq);
 294        struct net_device *dev = ieee->dev;
 295        struct r8180_priv *priv = ieee80211_priv(dev);
 296
 297        // Read CCK and OFDM False Alarm.
 298        priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM);
 299
 300
 301        // Adjust Initial Gain dynamically.
 302        DynamicInitGain(dev);
 303
 304}
 305
 306int
 307IncludedInSupportedRates(
 308        struct r8180_priv       *priv,
 309        u8              TxRate  )
 310{
 311    u8 rate_len;
 312        u8 rate_ex_len;
 313        u8                      RateMask = 0x7F;
 314        u8                      idx;
 315        unsigned short          Found = 0;
 316        u8                      NaiveTxRate = TxRate&RateMask;
 317
 318    rate_len = priv->ieee80211->current_network.rates_len;
 319        rate_ex_len = priv->ieee80211->current_network.rates_ex_len;
 320        for( idx=0; idx< rate_len; idx++ )
 321        {
 322                if( (priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate )
 323                {
 324                        Found = 1;
 325                        goto found_rate;
 326                }
 327        }
 328    for( idx=0; idx< rate_ex_len; idx++ )
 329        {
 330                if( (priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate )
 331                {
 332                        Found = 1;
 333                        goto found_rate;
 334                }
 335        }
 336        return Found;
 337        found_rate:
 338        return Found;
 339}
 340
 341//
 342//      Description:
 343//              Get the Tx rate one degree up form the input rate in the supported rates.
 344//              Return the upgrade rate if it is successed, otherwise return the input rate.
 345//      By Bruce, 2007-06-05.
 346//
 347u8
 348GetUpgradeTxRate(
 349        struct net_device *dev,
 350        u8                              rate
 351        )
 352{
 353        struct r8180_priv *priv = ieee80211_priv(dev);
 354        u8                      UpRate;
 355
 356        // Upgrade 1 degree.
 357        switch(rate)
 358        {
 359        case 108: // Up to 54Mbps.
 360                UpRate = 108;
 361                break;
 362
 363        case 96: // Up to 54Mbps.
 364                UpRate = 108;
 365                break;
 366
 367        case 72: // Up to 48Mbps.
 368                UpRate = 96;
 369                break;
 370
 371        case 48: // Up to 36Mbps.
 372                UpRate = 72;
 373                break;
 374
 375        case 36: // Up to 24Mbps.
 376                UpRate = 48;
 377                break;
 378
 379        case 22: // Up to 18Mbps.
 380                UpRate = 36;
 381                break;
 382
 383        case 11: // Up to 11Mbps.
 384                UpRate = 22;
 385                break;
 386
 387        case 4: // Up to 5.5Mbps.
 388                UpRate = 11;
 389                break;
 390
 391        case 2: // Up to 2Mbps.
 392                UpRate = 4;
 393                break;
 394
 395        default:
 396                printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
 397                return rate;
 398        }
 399        // Check if the rate is valid.
 400        if(IncludedInSupportedRates(priv, UpRate))
 401        {
 402//              printk("GetUpgradeTxRate(): GetUpgrade Tx rate(%d) from %d !\n", UpRate, priv->CurrentOperaRate);
 403                return UpRate;
 404        }
 405        else
 406        {
 407                //printk("GetUpgradeTxRate(): Tx rate (%d) is not in supported rates\n", UpRate);
 408                return rate;
 409        }
 410        return rate;
 411}
 412//
 413//      Description:
 414//              Get the Tx rate one degree down form the input rate in the supported rates.
 415//              Return the degrade rate if it is successed, otherwise return the input rate.
 416//      By Bruce, 2007-06-05.
 417//
 418u8
 419GetDegradeTxRate(
 420        struct net_device *dev,
 421        u8         rate
 422        )
 423{
 424        struct r8180_priv *priv = ieee80211_priv(dev);
 425        u8                      DownRate;
 426
 427        // Upgrade 1 degree.
 428        switch(rate)
 429        {
 430        case 108: // Down to 48Mbps.
 431                DownRate = 96;
 432                break;
 433
 434        case 96: // Down to 36Mbps.
 435                DownRate = 72;
 436                break;
 437
 438        case 72: // Down to 24Mbps.
 439                DownRate = 48;
 440                break;
 441
 442        case 48: // Down to 18Mbps.
 443                DownRate = 36;
 444                break;
 445
 446        case 36: // Down to 11Mbps.
 447                DownRate = 22;
 448                break;
 449
 450        case 22: // Down to 5.5Mbps.
 451                DownRate = 11;
 452                break;
 453
 454        case 11: // Down to 2Mbps.
 455                DownRate = 4;
 456                break;
 457
 458        case 4: // Down to 1Mbps.
 459                DownRate = 2;
 460                break;
 461
 462        case 2: // Down to 1Mbps.
 463                DownRate = 2;
 464                break;
 465
 466        default:
 467                printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
 468                return rate;
 469        }
 470        // Check if the rate is valid.
 471        if(IncludedInSupportedRates(priv, DownRate))
 472        {
 473//              printk("GetDegradeTxRate(): GetDegrade Tx rate(%d) from %d!\n", DownRate, priv->CurrentOperaRate);
 474                return DownRate;
 475        }
 476        else
 477        {
 478                //printk("GetDegradeTxRate(): Tx rate (%d) is not in supported rates\n", DownRate);
 479                return rate;
 480        }
 481        return rate;
 482}
 483//
 484//      Helper function to determine if specified data rate is
 485//      CCK rate.
 486//      2005.01.25, by rcnjko.
 487//
 488bool
 489MgntIsCckRate(
 490        u16     rate
 491        )
 492{
 493        bool bReturn = false;
 494
 495        if((rate <= 22) && (rate != 12) && (rate != 18))
 496        {
 497                bReturn = true;
 498        }
 499
 500        return bReturn;
 501}
 502//
 503//      Description:
 504//              Tx Power tracking mechanism routine on 87SE.
 505//      Created by Roger, 2007.12.11.
 506//
 507void
 508TxPwrTracking87SE(
 509        struct net_device *dev
 510)
 511{
 512        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 513        u8      tmpu1Byte, CurrentThermal, Idx;
 514        char    CckTxPwrIdx, OfdmTxPwrIdx;
 515        //u32   u4bRfReg;
 516
 517        tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL);
 518        CurrentThermal = (tmpu1Byte & 0xf0)>>4; //[ 7:4]: thermal meter indication.
 519        CurrentThermal = (CurrentThermal>0x0c)? 0x0c:CurrentThermal;//lzm add 080826
 520
 521        //printk("TxPwrTracking87SE(): CurrentThermal(%d)\n", CurrentThermal);
 522
 523        if( CurrentThermal != priv->ThermalMeter)
 524        {
 525//              printk("TxPwrTracking87SE(): Thermal meter changed!!!\n");
 526
 527                // Update Tx Power level on each channel.
 528                for(Idx = 1; Idx<15; Idx++)
 529                {
 530                        CckTxPwrIdx = priv->chtxpwr[Idx];
 531                        OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx];
 532
 533                        if( CurrentThermal > priv->ThermalMeter )
 534                        { // higher thermal meter.
 535                                CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2;
 536                                OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2;
 537
 538                                if(CckTxPwrIdx >35)
 539                                        CckTxPwrIdx = 35; // Force TxPower to maximal index.
 540                                if(OfdmTxPwrIdx >35)
 541                                        OfdmTxPwrIdx = 35;
 542                        }
 543                        else
 544                        { // lower thermal meter.
 545                                CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2;
 546                                OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2;
 547
 548                                if(CckTxPwrIdx <0)
 549                                        CckTxPwrIdx = 0;
 550                                if(OfdmTxPwrIdx <0)
 551                                        OfdmTxPwrIdx = 0;
 552                        }
 553
 554                        // Update TxPower level on CCK and OFDM resp.
 555                        priv->chtxpwr[Idx] = CckTxPwrIdx;
 556                        priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx;
 557                }
 558
 559                // Update TxPower level immediately.
 560                rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel);
 561        }
 562        priv->ThermalMeter = CurrentThermal;
 563}
 564void
 565StaRateAdaptive87SE(
 566        struct net_device *dev
 567        )
 568{
 569        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 570        unsigned long                   CurrTxokCnt;
 571        u16                     CurrRetryCnt;
 572        u16                     CurrRetryRate;
 573        //u16                   i,idx;
 574        unsigned long           CurrRxokCnt;
 575        bool                    bTryUp = false;
 576        bool                    bTryDown = false;
 577        u8                      TryUpTh = 1;
 578        u8                      TryDownTh = 2;
 579        u32                     TxThroughput;
 580        long            CurrSignalStrength;
 581        bool            bUpdateInitialGain = false;
 582        u8                      u1bOfdm=0, u1bCck = 0;
 583        char            OfdmTxPwrIdx, CckTxPwrIdx;
 584
 585        priv->RateAdaptivePeriod= RATE_ADAPTIVE_TIMER_PERIOD;
 586
 587
 588        CurrRetryCnt    = priv->CurrRetryCnt;
 589        CurrTxokCnt     = priv->NumTxOkTotal - priv->LastTxokCnt;
 590        CurrRxokCnt     = priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt;
 591        CurrSignalStrength = priv->Stats_RecvSignalPower;
 592        TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes);
 593        priv->LastTxOKBytes = priv->NumTxOkBytesTotal;
 594        priv->CurrentOperaRate = priv->ieee80211->rate/5;
 595        //printk("priv->CurrentOperaRate is %d\n",priv->CurrentOperaRate);
 596        //2 Compute retry ratio.
 597        if (CurrTxokCnt>0)
 598        {
 599                CurrRetryRate = (u16)(CurrRetryCnt*100/CurrTxokCnt);
 600        }
 601        else
 602        { // It may be serious retry. To distinguish serious retry or no packets modified by Bruce
 603                CurrRetryRate = (u16)(CurrRetryCnt*100/1);
 604        }
 605
 606
 607        //
 608        // Added by Roger, 2007.01.02.
 609        // For debug information.
 610        //
 611        //printk("\n(1) pHalData->LastRetryRate: %d \n",priv->LastRetryRate);
 612        //printk("(2) RetryCnt = %d  \n", CurrRetryCnt);
 613        //printk("(3) TxokCnt = %d \n", CurrTxokCnt);
 614        //printk("(4) CurrRetryRate = %d \n", CurrRetryRate);
 615        //printk("(5) CurrSignalStrength = %d \n",CurrSignalStrength);
 616        //printk("(6) TxThroughput is %d\n",TxThroughput);
 617        //printk("priv->NumTxOkBytesTotal is %d\n",priv->NumTxOkBytesTotal);
 618
 619        priv->LastRetryCnt = priv->CurrRetryCnt;
 620        priv->LastTxokCnt = priv->NumTxOkTotal;
 621        priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal;
 622        priv->CurrRetryCnt = 0;
 623
 624        //2No Tx packets, return to init_rate or not?
 625        if (CurrRetryRate==0 && CurrTxokCnt == 0)
 626        {
 627                //
 628                //After 9 (30*300ms) seconds in this condition, we try to raise rate.
 629                //
 630                priv->TryupingCountNoData++;
 631
 632//              printk("No Tx packets, TryupingCountNoData(%d)\n", priv->TryupingCountNoData);
 633                //[TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00
 634                if (priv->TryupingCountNoData>30)
 635                {
 636                        priv->TryupingCountNoData = 0;
 637                        priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
 638                        // Reset Fail Record
 639                        priv->LastFailTxRate = 0;
 640                        priv->LastFailTxRateSS = -200;
 641                        priv->FailTxRateCount = 0;
 642                }
 643                goto SetInitialGain;
 644        }
 645        else
 646        {
 647                priv->TryupingCountNoData=0; //Reset trying up times.
 648        }
 649
 650
 651        //
 652        // For Netgear case, I comment out the following signal strength estimation,
 653        // which can results in lower rate to transmit when sample is NOT enough (e.g. PING request).
 654        // 2007.04.09, by Roger.
 655        //
 656
 657        //
 658        // Restructure rate adaptive as the following main stages:
 659        // (1) Add retry threshold in 54M upgrading condition with signal strength.
 660        // (2) Add the mechanism to degrade to CCK rate according to signal strength
 661        //              and retry rate.
 662        // (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated
 663        //              situation, Initial Gain Update is upon on DIG mechanism except CCK rate.
 664        // (4) Add the mehanism of trying to upgrade tx rate.
 665        // (5) Record the information of upping tx rate to avoid trying upping tx rate constantly.
 666        // By Bruce, 2007-06-05.
 667        //
 668        //
 669
 670        // 11Mbps or 36Mbps
 671        // Check more times in these rate(key rates).
 672        //
 673        if(priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72)
 674        {
 675                TryUpTh += 9;
 676        }
 677        //
 678        // Let these rates down more difficult.
 679        //
 680        if(MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36)
 681        {
 682                        TryDownTh += 1;
 683        }
 684
 685        //1 Adjust Rate.
 686        if (priv->bTryuping == true)
 687        {
 688                //2 For Test Upgrading mechanism
 689                // Note:
 690                //      Sometimes the throughput is upon on the capability bwtween the AP and NIC,
 691                //      thus the low data rate does not improve the performance.
 692                //      We randomly upgrade the data rate and check if the retry rate is improved.
 693
 694                // Upgrading rate did not improve the retry rate, fallback to the original rate.
 695                if ( (CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput)
 696                {
 697                        //Not necessary raising rate, fall back rate.
 698                        bTryDown = true;
 699                        //printk("case1-1: Not necessary raising rate, fall back rate....\n");
 700                        //printk("case1-1: pMgntInfo->CurrentOperaRate =%d, TxThroughput = %d, LastThroughput = %d\n",
 701                        //              priv->CurrentOperaRate, TxThroughput, priv->LastTxThroughput);
 702                }
 703                else
 704                {
 705                        priv->bTryuping = false;
 706                }
 707        }
 708        else if (CurrSignalStrength > -47 && (CurrRetryRate < 50))
 709        {
 710                //2For High Power
 711                //
 712                // Added by Roger, 2007.04.09.
 713                // Return to highest data rate, if signal strength is good enough.
 714                // SignalStrength threshold(-50dbm) is for RTL8186.
 715                // Revise SignalStrength threshold to -51dbm.
 716                //
 717                // Also need to check retry rate for safety, by Bruce, 2007-06-05.
 718                if(priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate )
 719                {
 720                        bTryUp = true;
 721                        // Upgrade Tx Rate directly.
 722                        priv->TryupingCount += TryUpTh;
 723                }
 724//              printk("case2: StaRateAdaptive87SE: Power(%d) is high enough!!. \n", CurrSignalStrength);
 725
 726        }
 727        else if(CurrTxokCnt > 9 && CurrTxokCnt< 100 && CurrRetryRate >= 600)
 728        {
 729                //2 For Serious Retry
 730                //
 731                // Traffic is not busy but our Tx retry is serious.
 732                //
 733                bTryDown = true;
 734                // Let Rate Mechanism to degrade tx rate directly.
 735                priv->TryDownCountLowData += TryDownTh;
 736//              printk("case3: RA: Tx Retry is serious. Degrade Tx Rate to %d directly...\n", priv->CurrentOperaRate);
 737        }
 738        else if ( priv->CurrentOperaRate == 108 )
 739        {
 740                //2For 54Mbps
 741                // Air Link
 742                if ( (CurrRetryRate>26)&&(priv->LastRetryRate>25))
 743//              if ( (CurrRetryRate>40)&&(priv->LastRetryRate>39))
 744                {
 745                        //Down to rate 48Mbps.
 746                        bTryDown = true;
 747                }
 748                // Cable Link
 749                else if ( (CurrRetryRate>17)&&(priv->LastRetryRate>16) && (CurrSignalStrength > -72))
 750//              else if ( (CurrRetryRate>17)&&(priv->LastRetryRate>16) && (CurrSignalStrength > -72))
 751                {
 752                        //Down to rate 48Mbps.
 753                        bTryDown = true;
 754                }
 755
 756                if(bTryDown && (CurrSignalStrength < -75)) //cable link
 757                {
 758                        priv->TryDownCountLowData += TryDownTh;
 759                }
 760                //printk("case4---54M \n");
 761
 762        }
 763        else if ( priv->CurrentOperaRate == 96 )
 764        {
 765                //2For 48Mbps
 766                //Air Link
 767                if ( ((CurrRetryRate>48) && (priv->LastRetryRate>47)))
 768//              if ( ((CurrRetryRate>65) && (priv->LastRetryRate>64)))
 769
 770                {
 771                        //Down to rate 36Mbps.
 772                        bTryDown = true;
 773                }
 774                //Cable Link
 775                else if ( ((CurrRetryRate>21) && (priv->LastRetryRate>20)) && (CurrSignalStrength > -74))
 776                {
 777                        //Down to rate 36Mbps.
 778                        bTryDown = true;
 779                }
 780                else if((CurrRetryRate>  (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 ))
 781//              else if((CurrRetryRate>  (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 ))
 782                {
 783                        bTryDown = true;
 784                        priv->TryDownCountLowData += TryDownTh;
 785                }
 786                else if ( (CurrRetryRate<8) && (priv->LastRetryRate<8) ) //TO DO: need to consider (RSSI)
 787//              else if ( (CurrRetryRate<28) && (priv->LastRetryRate<8) )
 788                {
 789                        bTryUp = true;
 790                }
 791
 792                if(bTryDown && (CurrSignalStrength < -75))
 793                {
 794                        priv->TryDownCountLowData += TryDownTh;
 795                }
 796                //printk("case5---48M \n");
 797        }
 798        else if ( priv->CurrentOperaRate == 72 )
 799        {
 800                //2For 36Mbps
 801                if ( (CurrRetryRate>43) && (priv->LastRetryRate>41))
 802//              if ( (CurrRetryRate>60) && (priv->LastRetryRate>59))
 803                {
 804                        //Down to rate 24Mbps.
 805                        bTryDown = true;
 806                }
 807                else if((CurrRetryRate>  (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 ))
 808//              else if((CurrRetryRate>  (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 ))
 809                {
 810                        bTryDown = true;
 811                        priv->TryDownCountLowData += TryDownTh;
 812                }
 813                else if ( (CurrRetryRate<15) &&  (priv->LastRetryRate<16)) //TO DO: need to consider (RSSI)
 814//              else if ( (CurrRetryRate<35) &&  (priv->LastRetryRate<36))
 815                {
 816                        bTryUp = true;
 817                }
 818
 819                if(bTryDown && (CurrSignalStrength < -80))
 820                {
 821                        priv->TryDownCountLowData += TryDownTh;
 822                }
 823                //printk("case6---36M \n");
 824        }
 825        else if ( priv->CurrentOperaRate == 48 )
 826        {
 827                //2For 24Mbps
 828                // Air Link
 829                if ( ((CurrRetryRate>63) && (priv->LastRetryRate>62)))
 830//              if ( ((CurrRetryRate>83) && (priv->LastRetryRate>82)))
 831                {
 832                        //Down to rate 18Mbps.
 833                        bTryDown = true;
 834                }
 835                //Cable Link
 836                else if ( ((CurrRetryRate>33) && (priv->LastRetryRate>32)) && (CurrSignalStrength > -82) )
 837//               else if ( ((CurrRetryRate>50) && (priv->LastRetryRate>49)) && (CurrSignalStrength > -82) )
 838                {
 839                        //Down to rate 18Mbps.
 840                        bTryDown = true;
 841                }
 842                else if((CurrRetryRate>  (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 ))
 843//              else if((CurrRetryRate>  (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 ))
 844
 845                {
 846                        bTryDown = true;
 847                        priv->TryDownCountLowData += TryDownTh;
 848                }
 849                else if ( (CurrRetryRate<20) && (priv->LastRetryRate<21)) //TO DO: need to consider (RSSI)
 850//              else if ( (CurrRetryRate<40) && (priv->LastRetryRate<41))
 851                {
 852                        bTryUp = true;
 853                }
 854
 855                if(bTryDown && (CurrSignalStrength < -82))
 856                {
 857                        priv->TryDownCountLowData += TryDownTh;
 858                }
 859                //printk("case7---24M \n");
 860        }
 861        else if ( priv->CurrentOperaRate == 36 )
 862        {
 863                //2For 18Mbps
 864                // original (109, 109)
 865                //[TRC Dell Lab] (90, 91), Isaiah 2008-02-18 23:24
 866                //                           (85, 86), Isaiah 2008-02-18 24:00
 867                if ( ((CurrRetryRate>85) && (priv->LastRetryRate>86)))
 868//              if ( ((CurrRetryRate>115) && (priv->LastRetryRate>116)))
 869                {
 870                        //Down to rate 11Mbps.
 871                        bTryDown = true;
 872                }
 873                //[TRC Dell Lab]  Isaiah 2008-02-18 23:24
 874                else if((CurrRetryRate>  (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 ))
 875//              else if((CurrRetryRate>  (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 ))
 876                {
 877                        bTryDown = true;
 878                        priv->TryDownCountLowData += TryDownTh;
 879                }
 880                else if ( (CurrRetryRate<22) && (priv->LastRetryRate<23)) //TO DO: need to consider (RSSI)
 881//              else if ( (CurrRetryRate<42) && (priv->LastRetryRate<43))
 882                {
 883                        bTryUp = true;
 884                }
 885                //printk("case8---18M \n");
 886        }
 887        else if ( priv->CurrentOperaRate == 22 )
 888        {
 889                //2For 11Mbps
 890                if (CurrRetryRate>95)
 891//              if (CurrRetryRate>155)
 892                {
 893                        bTryDown = true;
 894                }
 895                else if ( (CurrRetryRate<29) && (priv->LastRetryRate <30) )//TO DO: need to consider (RSSI)
 896//              else if ( (CurrRetryRate<49) && (priv->LastRetryRate <50) )
 897                        {
 898                        bTryUp = true;
 899                        }
 900                //printk("case9---11M \n");
 901                }
 902        else if ( priv->CurrentOperaRate == 11 )
 903        {
 904                //2For 5.5Mbps
 905                if (CurrRetryRate>149)
 906//              if (CurrRetryRate>189)
 907                {
 908                        bTryDown = true;
 909                }
 910                else if ( (CurrRetryRate<60) && (priv->LastRetryRate < 65))
 911//              else if ( (CurrRetryRate<80) && (priv->LastRetryRate < 85))
 912
 913                        {
 914                        bTryUp = true;
 915                        }
 916                //printk("case10---5.5M \n");
 917                }
 918        else if ( priv->CurrentOperaRate == 4 )
 919        {
 920                //2For 2 Mbps
 921                if((CurrRetryRate>99) && (priv->LastRetryRate>99))
 922//              if((CurrRetryRate>199) && (priv->LastRetryRate>199))
 923                {
 924                        bTryDown = true;
 925                }
 926                else if ( (CurrRetryRate < 65) && (priv->LastRetryRate < 70))
 927//              else if ( (CurrRetryRate < 85) && (priv->LastRetryRate < 90))
 928                {
 929                        bTryUp = true;
 930                }
 931                //printk("case11---2M \n");
 932        }
 933        else if ( priv->CurrentOperaRate == 2 )
 934        {
 935                //2For 1 Mbps
 936                if( (CurrRetryRate<70) && (priv->LastRetryRate<75))
 937//              if( (CurrRetryRate<90) && (priv->LastRetryRate<95))
 938                {
 939                        bTryUp = true;
 940                }
 941                //printk("case12---1M \n");
 942        }
 943
 944        if(bTryUp && bTryDown)
 945        printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
 946
 947        //1 Test Upgrading Tx Rate
 948        // Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC.
 949        // To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate.
 950        if(!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0)
 951                && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2)
 952        {
 953                if(jiffies% (CurrRetryRate + 101) == 0)
 954                {
 955                        bTryUp = true;
 956                        priv->bTryuping = true;
 957                        //printk("StaRateAdaptive87SE(): Randomly try upgrading...\n");
 958                }
 959        }
 960
 961        //1 Rate Mechanism
 962        if(bTryUp)
 963        {
 964                priv->TryupingCount++;
 965                priv->TryDownCountLowData = 0;
 966
 967                {
 968//                      printk("UP: pHalData->TryupingCount = %d\n", priv->TryupingCount);
 969//                      printk("UP: TryUpTh(%d)+ (FailTxRateCount(%d))^2 =%d\n",
 970//                              TryUpTh, priv->FailTxRateCount, (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount) );
 971//                      printk("UP: pHalData->bTryuping=%d\n",  priv->bTryuping);
 972
 973                }
 974
 975                //
 976                // Check more times if we need to upgrade indeed.
 977                // Because the largest value of pHalData->TryupingCount is 0xFFFF and
 978                // the largest value of pHalData->FailTxRateCount is 0x14,
 979                // this condition will be satisfied at most every 2 min.
 980                //
 981
 982                if((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) ||
 983                        (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping)
 984                {
 985                        priv->TryupingCount = 0;
 986                        //
 987                        // When transferring from CCK to OFDM, DIG is an important issue.
 988                        //
 989                        if(priv->CurrentOperaRate == 22)
 990                                bUpdateInitialGain = true;
 991
 992                        // The difference in throughput between 48Mbps and 36Mbps is 8M.
 993                        // So, we must be carefully in this rate scale. Isaiah 2008-02-15.
 994                        //
 995                        if(  ((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) &&
 996                                (priv->FailTxRateCount > 2) )
 997                                priv->RateAdaptivePeriod= (RATE_ADAPTIVE_TIMER_PERIOD/2);
 998
 999                        // (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold.
1000                        // (2)If the signal strength is increased, it may be able to upgrade.
1001
1002                        priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
1003//                      printk("StaRateAdaptive87SE(): Upgrade Tx Rate to %d\n", priv->CurrentOperaRate);
1004
1005                        //[TRC Dell Lab] Bypass 12/9/6, Isaiah 2008-02-18 20:00
1006                        if(priv->CurrentOperaRate ==36)
1007                        {
1008                                priv->bUpdateARFR=true;
1009                                write_nic_word(dev, ARFR, 0x0F8F); //bypass 12/9/6
1010//                              printk("UP: ARFR=0xF8F\n");
1011                        }
1012                        else if(priv->bUpdateARFR)
1013                        {
1014                                priv->bUpdateARFR=false;
1015                                write_nic_word(dev, ARFR, 0x0FFF); //set 1M ~ 54Mbps.
1016//                              printk("UP: ARFR=0xFFF\n");
1017                        }
1018
1019                        // Update Fail Tx rate and count.
1020                        if(priv->LastFailTxRate != priv->CurrentOperaRate)
1021                        {
1022                                priv->LastFailTxRate = priv->CurrentOperaRate;
1023                                priv->FailTxRateCount = 0;
1024                                priv->LastFailTxRateSS = -200; // Set lowest power.
1025                        }
1026                }
1027        }
1028        else
1029        {
1030                if(priv->TryupingCount > 0)
1031                        priv->TryupingCount --;
1032        }
1033
1034        if(bTryDown)
1035        {
1036                priv->TryDownCountLowData++;
1037                priv->TryupingCount = 0;
1038                {
1039//                      printk("DN: pHalData->TryDownCountLowData = %d\n",priv->TryDownCountLowData);
1040//                      printk("DN: TryDownTh =%d\n", TryDownTh);
1041//                      printk("DN: pHalData->bTryuping=%d\n",  priv->bTryuping);
1042                }
1043
1044                //Check if Tx rate can be degraded or Test trying upgrading should fallback.
1045                if(priv->TryDownCountLowData > TryDownTh || priv->bTryuping)
1046                {
1047                        priv->TryDownCountLowData = 0;
1048                        priv->bTryuping = false;
1049                        // Update fail information.
1050                        if(priv->LastFailTxRate == priv->CurrentOperaRate)
1051                        {
1052                                priv->FailTxRateCount ++;
1053                                // Record the Tx fail rate signal strength.
1054                                if(CurrSignalStrength > priv->LastFailTxRateSS)
1055                                {
1056                                        priv->LastFailTxRateSS = CurrSignalStrength;
1057                                }
1058                        }
1059                        else
1060                        {
1061                                priv->LastFailTxRate = priv->CurrentOperaRate;
1062                                priv->FailTxRateCount = 1;
1063                                priv->LastFailTxRateSS = CurrSignalStrength;
1064                        }
1065                        priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate);
1066
1067                        // Reduce chariot training time at weak signal strength situation. SD3 ED demand.
1068                        //[TRC Dell Lab] Revise Signal Threshold from -75 to -80 , Isaiah 2008-02-18 20:00
1069                        if( (CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72 ))
1070                        {
1071                                priv->CurrentOperaRate = 72;
1072//                              printk("DN: weak signal strength (%d), degrade to 36Mbps\n", CurrSignalStrength);
1073                        }
1074
1075                        //[TRC Dell Lab] Bypass 12/9/6, Isaiah 2008-02-18 20:00
1076                        if(priv->CurrentOperaRate ==36)
1077                        {
1078                                priv->bUpdateARFR=true;
1079                                write_nic_word(dev, ARFR, 0x0F8F); //bypass 12/9/6
1080//                              printk("DN: ARFR=0xF8F\n");
1081                        }
1082                        else if(priv->bUpdateARFR)
1083                        {
1084                                priv->bUpdateARFR=false;
1085                                write_nic_word(dev, ARFR, 0x0FFF); //set 1M ~ 54Mbps.
1086//                              printk("DN: ARFR=0xFFF\n");
1087                        }
1088
1089                        //
1090                        // When it is CCK rate, it may need to update initial gain to receive lower power packets.
1091                        //
1092                        if(MgntIsCckRate(priv->CurrentOperaRate))
1093                        {
1094                                bUpdateInitialGain = true;
1095                        }
1096//                      printk("StaRateAdaptive87SE(): Degrade Tx Rate to %d\n", priv->CurrentOperaRate);
1097                }
1098        }
1099        else
1100        {
1101                if(priv->TryDownCountLowData > 0)
1102                        priv->TryDownCountLowData --;
1103        }
1104
1105        // Keep the Tx fail rate count to equal to 0x15 at most.
1106        // Reduce the fail count at least to 10 sec if tx rate is tending stable.
1107        if(priv->FailTxRateCount >= 0x15 ||
1108                (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6))
1109        {
1110                priv->FailTxRateCount --;
1111        }
1112
1113
1114        OfdmTxPwrIdx  = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
1115        CckTxPwrIdx  = priv->chtxpwr[priv->ieee80211->current_network.channel];
1116
1117        //[TRC Dell Lab] Mac0x9e increase 2 level in 36M~18M situation, Isaiah 2008-02-18 24:00
1118        if((priv->CurrentOperaRate < 96) &&(priv->CurrentOperaRate > 22))
1119        {
1120                u1bCck = read_nic_byte(dev, CCK_TXAGC);
1121                u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
1122
1123                // case 1: Never enter High power
1124                if(u1bCck == CckTxPwrIdx )
1125                {
1126                        if(u1bOfdm != (OfdmTxPwrIdx+2) )
1127                        {
1128                        priv->bEnhanceTxPwr= true;
1129                        u1bOfdm = ((u1bOfdm+2) > 35) ? 35: (u1bOfdm+2);
1130                        write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
1131//                      printk("Enhance OFDM_TXAGC : +++++ u1bOfdm= 0x%x\n", u1bOfdm);
1132                        }
1133                }
1134                // case 2: enter high power
1135                else if(u1bCck < CckTxPwrIdx)
1136                {
1137                        if(!priv->bEnhanceTxPwr)
1138                        {
1139                                priv->bEnhanceTxPwr= true;
1140                                u1bOfdm = ((u1bOfdm+2) > 35) ? 35: (u1bOfdm+2);
1141                                write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
1142                                //RT_TRACE(COMP_RATE, DBG_TRACE, ("Enhance OFDM_TXAGC(2) : +++++ u1bOfdm= 0x%x\n", u1bOfdm));
1143                        }
1144                }
1145        }
1146        else if(priv->bEnhanceTxPwr)  //54/48/11/5.5/2/1
1147        {
1148                u1bCck = read_nic_byte(dev, CCK_TXAGC);
1149                u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
1150
1151                // case 1: Never enter High power
1152                if(u1bCck == CckTxPwrIdx )
1153                {
1154                priv->bEnhanceTxPwr= false;
1155                write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
1156                //printk("Recover OFDM_TXAGC : ===== u1bOfdm= 0x%x\n", OfdmTxPwrIdx);
1157                }
1158                // case 2: enter high power
1159                else if(u1bCck < CckTxPwrIdx)
1160                {
1161                        priv->bEnhanceTxPwr= false;
1162                        u1bOfdm = ((u1bOfdm-2) > 0) ? (u1bOfdm-2): 0;
1163                        write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
1164                        //RT_TRACE(COMP_RATE, DBG_TRACE, ("Recover OFDM_TXAGC(2): ===== u1bOfdm= 0x%x\n", u1bOfdm));
1165
1166                }
1167        }
1168
1169        //
1170        // We need update initial gain when we set tx rate "from OFDM to CCK" or
1171        // "from CCK to OFDM".
1172        //
1173SetInitialGain:
1174        if(bUpdateInitialGain)
1175        {
1176                if(MgntIsCckRate(priv->CurrentOperaRate)) // CCK
1177                {
1178                        if(priv->InitialGain > priv->RegBModeGainStage)
1179                        {
1180                                priv->InitialGainBackUp= priv->InitialGain;
1181
1182                                if(CurrSignalStrength < -85) // Low power, OFDM [0x17] = 26.
1183                                {
1184                                        //SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26.
1185                                        priv->InitialGain = priv->RegBModeGainStage;
1186                                }
1187                                else if(priv->InitialGain > priv->RegBModeGainStage + 1)
1188                                {
1189                                        priv->InitialGain -= 2;
1190                                }
1191                                else
1192                                {
1193                                        priv->InitialGain --;
1194                                }
1195                                printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate);
1196                                UpdateInitialGain(dev);
1197                        }
1198                }
1199                else // OFDM
1200                {
1201                        if(priv->InitialGain < 4)
1202                        {
1203                                priv->InitialGainBackUp= priv->InitialGain;
1204
1205                                priv->InitialGain ++;
1206                                printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate);
1207                                UpdateInitialGain(dev);
1208                        }
1209                }
1210        }
1211
1212        //Record the related info
1213        priv->LastRetryRate = CurrRetryRate;
1214        priv->LastTxThroughput = TxThroughput;
1215        priv->ieee80211->rate = priv->CurrentOperaRate * 5;
1216}
1217
1218void rtl8180_rate_adapter(struct work_struct * work)
1219{
1220        struct delayed_work *dwork = to_delayed_work(work);
1221        struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,rate_adapter_wq);
1222        struct net_device *dev = ieee->dev;
1223        //struct r8180_priv *priv = ieee80211_priv(dev);
1224//    DMESG("---->rtl8180_rate_adapter");
1225        StaRateAdaptive87SE(dev);
1226//   DMESG("<----rtl8180_rate_adapter");
1227}
1228void timer_rate_adaptive(unsigned long data)
1229{
1230        struct r8180_priv* priv = ieee80211_priv((struct net_device *)data);
1231        //DMESG("---->timer_rate_adaptive()\n");
1232        if(!priv->up)
1233        {
1234//              DMESG("<----timer_rate_adaptive():driver is not up!\n");
1235                return;
1236        }
1237        if((priv->ieee80211->iw_mode != IW_MODE_MASTER)
1238                        && (priv->ieee80211->state == IEEE80211_LINKED) &&
1239                        (priv->ForcedDataRate == 0) )
1240        {
1241//      DMESG("timer_rate_adaptive():schedule rate_adapter_wq\n");
1242                queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq);
1243//              StaRateAdaptive87SE((struct net_device *)data);
1244        }
1245        priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod);
1246        add_timer(&priv->rateadapter_timer);
1247        //DMESG("<----timer_rate_adaptive()\n");
1248}
1249//by amy 080312}
1250void
1251SwAntennaDiversityRxOk8185(
1252        struct net_device *dev,
1253        u8 SignalStrength
1254        )
1255{
1256        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1257
1258//      printk("+SwAntennaDiversityRxOk8185: RxSs: %d\n", SignalStrength);
1259
1260        priv->AdRxOkCnt++;
1261
1262        if( priv->AdRxSignalStrength != -1)
1263        {
1264                priv->AdRxSignalStrength = ((priv->AdRxSignalStrength*7) + (SignalStrength*3)) / 10;
1265        }
1266        else
1267        { // Initialization case.
1268                priv->AdRxSignalStrength = SignalStrength;
1269        }
1270//{+by amy 080312
1271        if( priv->LastRxPktAntenna ) //Main antenna.
1272                priv->AdMainAntennaRxOkCnt++;
1273        else     // Aux antenna.
1274                priv->AdAuxAntennaRxOkCnt++;
1275//+by amy 080312
1276//      printk("-SwAntennaDiversityRxOk8185: AdRxOkCnt: %d AdRxSignalStrength: %d\n", priv->AdRxOkCnt, priv->AdRxSignalStrength);
1277}
1278//
1279//      Description:
1280//              Change Antenna Switch.
1281//
1282bool
1283SetAntenna8185(
1284        struct net_device *dev,
1285        u8              u1bAntennaIndex
1286        )
1287{
1288        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1289        bool bAntennaSwitched = false;
1290
1291//      printk("+SetAntenna8185(): Antenna is switching to: %d \n", u1bAntennaIndex);
1292
1293        switch(u1bAntennaIndex)
1294        {
1295        case 0:
1296                /* Mac register, main antenna */
1297                write_nic_byte(dev, ANTSEL, 0x03);
1298                /* base band */
1299                write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
1300                write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
1301
1302                bAntennaSwitched = true;
1303                break;
1304
1305        case 1:
1306                /* Mac register, aux antenna */
1307                write_nic_byte(dev, ANTSEL, 0x00);
1308                /* base band */
1309                write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
1310                write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
1311
1312                bAntennaSwitched = true;
1313
1314                break;
1315
1316        default:
1317                printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex);
1318                break;
1319        }
1320
1321        if(bAntennaSwitched)
1322        {
1323                priv->CurrAntennaIndex = u1bAntennaIndex;
1324        }
1325
1326//      printk("-SetAntenna8185(): return (%#X)\n", bAntennaSwitched);
1327
1328        return bAntennaSwitched;
1329}
1330//
1331//      Description:
1332//              Toggle Antenna switch.
1333//
1334bool
1335SwitchAntenna(
1336        struct net_device *dev
1337        )
1338{
1339        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1340
1341        bool            bResult;
1342
1343        if(priv->CurrAntennaIndex == 0)
1344        {
1345                        bResult = SetAntenna8185(dev, 1);
1346//by amy 080312
1347//              printk("SwitchAntenna(): switching to antenna 1 ......\n");
1348//              bResult = SetAntenna8185(dev, 1);//-by amy 080312
1349        }
1350        else
1351        {
1352                        bResult = SetAntenna8185(dev, 0);
1353//by amy 080312
1354//              printk("SwitchAntenna(): switching to antenna 0 ......\n");
1355//              bResult = SetAntenna8185(dev, 0);//-by amy 080312
1356        }
1357
1358        return bResult;
1359}
1360//
1361//      Description:
1362//              Engine of SW Antenna Diversity mechanism.
1363//              Since 8187 has no Tx part information,
1364//              this implementation is only dependend on Rx part information.
1365//
1366//      2006.04.17, by rcnjko.
1367//
1368void
1369SwAntennaDiversity(
1370        struct net_device *dev
1371        )
1372{
1373        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1374        bool   bSwCheckSS=false;
1375//      printk("+SwAntennaDiversity(): CurrAntennaIndex: %d\n", priv->CurrAntennaIndex);
1376//      printk("AdTickCount is %d\n",priv->AdTickCount);
1377//by amy 080312
1378        if(bSwCheckSS)
1379        {
1380                priv->AdTickCount++;
1381
1382                printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n",
1383                        priv->AdTickCount, priv->AdCheckPeriod);
1384                printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n",
1385                        priv->AdRxSignalStrength, priv->AdRxSsThreshold);
1386        }
1387//      priv->AdTickCount++;//-by amy 080312
1388
1389        // Case 1. No Link.
1390        if(priv->ieee80211->state != IEEE80211_LINKED)
1391        {
1392        //      printk("SwAntennaDiversity(): Case 1. No Link.\n");
1393
1394                priv->bAdSwitchedChecking = false;
1395                // I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko..
1396                SwitchAntenna(dev);
1397        }
1398        // Case 2. Linked but no packet received.
1399        else if(priv->AdRxOkCnt == 0)
1400        {
1401        //      printk("SwAntennaDiversity(): Case 2. Linked but no packet received.\n");
1402
1403                priv->bAdSwitchedChecking = false;
1404                SwitchAntenna(dev);
1405        }
1406        // Case 3. Evaluate last antenna switch action and undo it if necessary.
1407        else if(priv->bAdSwitchedChecking == true)
1408        {
1409        //      printk("SwAntennaDiversity(): Case 3. Evaluate last antenna switch action.\n");
1410
1411                priv->bAdSwitchedChecking = false;
1412
1413                // Adjust Rx signal strength threshold.
1414                priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2;
1415
1416                priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
1417                                        priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;
1418                if(priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched)
1419                { // Rx signal strength is not improved after we swtiched antenna. => Swich back.
1420//                      printk("SwAntennaDiversity(): Rx Signal Strength is not improved, CurrRxSs: %d, LastRxSs: %d\n",
1421//                              priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched);
1422//by amy 080312
1423                        // Increase Antenna Diversity checking period due to bad decision.
1424                        priv->AdCheckPeriod *= 2;
1425//by amy 080312
1426                        // Increase Antenna Diversity checking period.
1427                        if(priv->AdCheckPeriod > priv->AdMaxCheckPeriod)
1428                                priv->AdCheckPeriod = priv->AdMaxCheckPeriod;
1429
1430                        // Wrong deceision => switch back.
1431                        SwitchAntenna(dev);
1432                }
1433                else
1434                { // Rx Signal Strength is improved.
1435//                      printk("SwAntennaDiversity(): Rx Signal Strength is improved, CurrRxSs: %d, LastRxSs: %d\n",
1436//                              priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched);
1437
1438                        // Reset Antenna Diversity checking period to its min value.
1439                        priv->AdCheckPeriod = priv->AdMinCheckPeriod;
1440                }
1441
1442//              printk("SwAntennaDiversity(): AdRxSsThreshold: %d, AdCheckPeriod: %d\n",
1443//                      priv->AdRxSsThreshold, priv->AdCheckPeriod);
1444        }
1445        // Case 4. Evaluate if we shall switch antenna now.
1446        // Cause Table Speed is very fast in TRC Dell Lab, we check it every time.
1447        else// if(priv->AdTickCount >= priv->AdCheckPeriod)//-by amy 080312
1448        {
1449//              printk("SwAntennaDiversity(): Case 4. Evaluate if we shall switch antenna now.\n");
1450
1451                priv->AdTickCount = 0;
1452
1453                //
1454                // <Roger_Notes> We evaluate RxOk counts for each antenna first and than
1455                // evaluate signal strength.
1456                // The following operation can overcome the disability of CCA on both two antennas
1457                // When signal strength was extremely low or high.
1458                // 2008.01.30.
1459                //
1460
1461                //
1462                // Evaluate RxOk count from each antenna if we shall switch default antenna now.
1463                // Added by Roger, 2008.02.21.
1464//{by amy 080312
1465                if((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt)
1466                        && (priv->CurrAntennaIndex == 0))
1467                { // We set Main antenna as default but RxOk count was less than Aux ones.
1468
1469        //              printk("SwAntennaDiversity(): Main antenna RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n",
1470        //                      priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt);
1471
1472                        // Switch to Aux antenna.
1473                        SwitchAntenna(dev);
1474                        priv->bHWAdSwitched = true;
1475                }
1476                else if((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt)
1477                        && (priv->CurrAntennaIndex == 1))
1478                { // We set Aux antenna as default but RxOk count was less than Main ones.
1479
1480        //              printk("SwAntennaDiversity(): Aux antenna RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n",
1481        //                      priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt);
1482
1483                        // Switch to Main antenna.
1484                        SwitchAntenna(dev);
1485                        priv->bHWAdSwitched = true;
1486                }
1487                else
1488                {// Default antenna is better.
1489
1490        //              printk("SwAntennaDiversity(): Default antenna is better., AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n",
1491        //                      priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt);
1492
1493                        // Still need to check current signal strength.
1494                        priv->bHWAdSwitched = false;
1495                }
1496                //
1497                // <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
1498                // didn't changed by HW evaluation.
1499                // 2008.02.27.
1500                //
1501                // [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05
1502                // For example, Throughput of aux is better than main antenna(about 10M v.s 2M),
1503                // but AdRxSignalStrength is less than main.
1504                // Our guess is that main antenna have lower throughput and get many change
1505                // to receive more CCK packets(ex.Beacon) which have stronger SignalStrength.
1506                //
1507                if( (!priv->bHWAdSwitched) && (bSwCheckSS))
1508                {
1509//by amy 080312}
1510                // Evaluate Rx signal strength if we shall switch antenna now.
1511                if(priv->AdRxSignalStrength < priv->AdRxSsThreshold)
1512                { // Rx signal strength is weak => Switch Antenna.
1513//                      printk("SwAntennaDiversity(): Rx Signal Strength is weak, CurrRxSs: %d, RxSsThreshold: %d\n",
1514//                              priv->AdRxSignalStrength, priv->AdRxSsThreshold);
1515
1516                        priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength;
1517                        priv->bAdSwitchedChecking = true;
1518
1519                        SwitchAntenna(dev);
1520                }
1521                else
1522                { // Rx signal strength is OK.
1523//                      printk("SwAntennaDiversity(): Rx Signal Strength is OK, CurrRxSs: %d, RxSsThreshold: %d\n",
1524//                              priv->AdRxSignalStrength, priv->AdRxSsThreshold);
1525
1526                        priv->bAdSwitchedChecking = false;
1527                        // Increase Rx signal strength threshold if necessary.
1528                        if(     (priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && // Signal is much stronger than current threshold
1529                                priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) // Current threhold is not yet reach upper limit.
1530                        {
1531                                priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2;
1532                                priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
1533                                                                                                priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;//+by amy 080312
1534                        }
1535
1536                        // Reduce Antenna Diversity checking period if possible.
1537                        if( priv->AdCheckPeriod > priv->AdMinCheckPeriod )
1538                        {
1539                                priv->AdCheckPeriod /= 2;
1540                        }
1541                }
1542                }
1543        }
1544//by amy 080312
1545        // Reset antenna diversity Rx related statistics.
1546        priv->AdRxOkCnt = 0;
1547        priv->AdMainAntennaRxOkCnt = 0;
1548        priv->AdAuxAntennaRxOkCnt = 0;
1549//by amy 080312
1550
1551//      priv->AdRxOkCnt = 0;//-by amy 080312
1552
1553//      printk("-SwAntennaDiversity()\n");
1554}
1555
1556//
1557//      Description:
1558//              Return TRUE if we shall perform Tx Power Tracking Mecahnism, FALSE otherwise.
1559//
1560bool
1561CheckTxPwrTracking(     struct net_device *dev)
1562{
1563        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1564
1565        if(!priv->bTxPowerTrack)
1566        {
1567                return false;
1568        }
1569
1570//lzm reserved 080826
1571        //if(priv->bScanInProgress)
1572        //{
1573        //      return false;
1574        //}
1575
1576        //if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah
1577        if(priv->bToUpdateTxPwr)
1578        {
1579                return false;
1580        }
1581
1582        return true;
1583}
1584
1585
1586//
1587//      Description:
1588//              Timer callback function of SW Antenna Diversity.
1589//
1590void
1591SwAntennaDiversityTimerCallback(
1592        struct net_device *dev
1593        )
1594{
1595        struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1596        RT_RF_POWER_STATE rtState;
1597
1598        //printk("+SwAntennaDiversityTimerCallback()\n");
1599
1600        //
1601        // We do NOT need to switch antenna while RF is off.
1602        // 2007.05.09, added by Roger.
1603        //
1604        rtState = priv->eRFPowerState;
1605        do{
1606                if (rtState == eRfOff)
1607                {
1608//                      printk("SwAntennaDiversityTimer - RF is OFF.\n");
1609                        break;
1610                }
1611                else if (rtState == eRfSleep)
1612                {
1613                        // Don't access BB/RF under Disable PLL situation.
1614                        //RT_TRACE((COMP_RF|COMP_ANTENNA), DBG_LOUD, ("SwAntennaDiversityTimerCallback(): RF is Sleep => skip it\n"));
1615                        break;
1616                }
1617                SwAntennaDiversity(dev);
1618
1619        }while(false);
1620
1621        if(priv->up)
1622        {
1623                priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD);
1624                add_timer(&priv->SwAntennaDiversityTimer);
1625        }
1626
1627        //printk("-SwAntennaDiversityTimerCallback()\n");
1628}
1629
1630