3 #include "r8180_93cx6.h"
5 /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */
6 #define RATE_ADAPTIVE_TIMER_PERIOD 300
8 bool CheckHighPower(struct net_device
*dev
)
10 struct r8180_priv
*priv
= ieee80211_priv(dev
);
11 struct ieee80211_device
*ieee
= priv
->ieee80211
;
13 if (!priv
->bRegHighPowerMechanism
)
16 if (ieee
->state
== IEEE80211_LINKED_SCANNING
)
24 * Update Tx power level if necessary.
25 * See also DoRxHighPower() and SetTxPowerLevel8185() for reference.
28 * The reason why we udpate Tx power level here instead of DoRxHighPower()
29 * is the number of IO to change Tx power is much more than channel TR switch
30 * and they are related to OFDM and MAC registers.
31 * So, we don't want to update it so frequently in per-Rx packet base.
33 static void DoTxHighPower(struct net_device
*dev
)
35 struct r8180_priv
*priv
= ieee80211_priv(dev
);
41 char OfdmTxPwrIdx
, CckTxPwrIdx
;
43 HiPwrUpperTh
= priv
->RegHiPwrUpperTh
;
44 HiPwrLowerTh
= priv
->RegHiPwrLowerTh
;
46 HiPwrUpperTh
= HiPwrUpperTh
* 10;
47 HiPwrLowerTh
= HiPwrLowerTh
* 10;
48 RSSIHiPwrUpperTh
= priv
->RegRSSIHiPwrUpperTh
;
49 RSSIHiPwrLowerTh
= priv
->RegRSSIHiPwrLowerTh
;
52 OfdmTxPwrIdx
= priv
->chtxpwr_ofdm
[priv
->ieee80211
->current_network
.channel
];
53 CckTxPwrIdx
= priv
->chtxpwr
[priv
->ieee80211
->current_network
.channel
];
55 if ((priv
->UndecoratedSmoothedSS
> HiPwrUpperTh
) ||
56 (priv
->bCurCCKPkt
&& (priv
->CurCCKRSSI
> RSSIHiPwrUpperTh
))) {
57 /* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */
59 priv
->bToUpdateTxPwr
= true;
60 u1bTmp
= read_nic_byte(dev
, CCK_TXAGC
);
62 /* If it never enter High Power. */
63 if (CckTxPwrIdx
== u1bTmp
) {
64 u1bTmp
= (u1bTmp
> 16) ? (u1bTmp
- 16) : 0; /* 8dbm */
65 write_nic_byte(dev
, CCK_TXAGC
, u1bTmp
);
67 u1bTmp
= read_nic_byte(dev
, OFDM_TXAGC
);
68 u1bTmp
= (u1bTmp
> 16) ? (u1bTmp
- 16) : 0; /* 8dbm */
69 write_nic_byte(dev
, OFDM_TXAGC
, u1bTmp
);
72 } else if ((priv
->UndecoratedSmoothedSS
< HiPwrLowerTh
) &&
73 (!priv
->bCurCCKPkt
|| priv
->CurCCKRSSI
< RSSIHiPwrLowerTh
)) {
74 if (priv
->bToUpdateTxPwr
) {
75 priv
->bToUpdateTxPwr
= false;
77 u1bTmp
= read_nic_byte(dev
, CCK_TXAGC
);
78 if (u1bTmp
< CckTxPwrIdx
) {
79 write_nic_byte(dev
, CCK_TXAGC
, CckTxPwrIdx
);
82 u1bTmp
= read_nic_byte(dev
, OFDM_TXAGC
);
83 if (u1bTmp
< OfdmTxPwrIdx
) {
84 write_nic_byte(dev
, OFDM_TXAGC
, OfdmTxPwrIdx
);
93 * Callback function of UpdateTxPowerWorkItem.
94 * Because of some event happened, e.g. CCX TPC, High Power Mechanism,
95 * We update Tx power of current channel again.
97 void rtl8180_tx_pw_wq(struct work_struct
*work
)
99 struct delayed_work
*dwork
= to_delayed_work(work
);
100 struct ieee80211_device
*ieee
= container_of(dwork
, struct ieee80211_device
, tx_pw_wq
);
101 struct net_device
*dev
= ieee
->dev
;
108 * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise.
110 bool CheckDig(struct net_device
*dev
)
112 struct r8180_priv
*priv
= ieee80211_priv(dev
);
113 struct ieee80211_device
*ieee
= priv
->ieee80211
;
115 if (!priv
->bDigMechanism
)
118 if (ieee
->state
!= IEEE80211_LINKED
)
121 if ((priv
->ieee80211
->rate
/ 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */
126 * Implementation of DIG for Zebra and Zebra2.
128 static void DIG_Zebra(struct net_device
*dev
)
130 struct r8180_priv
*priv
= ieee80211_priv(dev
);
131 u16 CCKFalseAlarm
, OFDMFalseAlarm
;
132 u16 OfdmFA1
, OfdmFA2
;
133 int InitialGainStep
= 7; /* The number of initial gain stages. */
134 int LowestGainStage
= 4; /* The capable lowest stage of performing dig workitem. */
135 u32 AwakePeriodIn2Sec
= 0;
137 CCKFalseAlarm
= (u16
)(priv
->FalseAlarmRegValue
& 0x0000ffff);
138 OFDMFalseAlarm
= (u16
)((priv
->FalseAlarmRegValue
>> 16) & 0x0000ffff);
140 OfdmFA2
= ((u16
)(priv
->RegDigOfdmFaUpTh
)) << 8;
142 /* The number of initial gain steps is different, by Bruce, 2007-04-13. */
143 if (priv
->InitialGain
== 0) { /* autoDIG */
144 /* Advised from SD3 DZ */
145 priv
->InitialGain
= 4; /* In 87B, m74dBm means State 4 (m82dBm) */
147 /* Advised from SD3 DZ */
150 #if 1 /* lzm reserved 080826 */
151 AwakePeriodIn2Sec
= (2000 - priv
->DozePeriodInPast2Sec
);
152 priv
->DozePeriodInPast2Sec
= 0;
154 if (AwakePeriodIn2Sec
) {
155 OfdmFA1
= (u16
)((OfdmFA1
* AwakePeriodIn2Sec
) / 2000);
156 OfdmFA2
= (u16
)((OfdmFA2
* AwakePeriodIn2Sec
) / 2000);
163 LowestGainStage
= priv
->RegBModeGainStage
; /* Lowest gain stage. */
165 if (OFDMFalseAlarm
> OfdmFA1
) {
166 if (OFDMFalseAlarm
> OfdmFA2
) {
167 priv
->DIG_NumberFallbackVote
++;
168 if (priv
->DIG_NumberFallbackVote
> 1) {
169 /* serious OFDM False Alarm, need fallback */
170 if (priv
->InitialGain
< InitialGainStep
) {
171 priv
->InitialGainBackUp
= priv
->InitialGain
;
173 priv
->InitialGain
= (priv
->InitialGain
+ 1);
174 UpdateInitialGain(dev
);
176 priv
->DIG_NumberFallbackVote
= 0;
177 priv
->DIG_NumberUpgradeVote
= 0;
180 if (priv
->DIG_NumberFallbackVote
)
181 priv
->DIG_NumberFallbackVote
--;
183 priv
->DIG_NumberUpgradeVote
= 0;
185 if (priv
->DIG_NumberFallbackVote
)
186 priv
->DIG_NumberFallbackVote
--;
187 priv
->DIG_NumberUpgradeVote
++;
189 if (priv
->DIG_NumberUpgradeVote
> 9) {
190 if (priv
->InitialGain
> LowestGainStage
) { /* In 87B, m78dBm means State 4 (m864dBm) */
191 priv
->InitialGainBackUp
= priv
->InitialGain
;
193 priv
->InitialGain
= (priv
->InitialGain
- 1);
194 UpdateInitialGain(dev
);
196 priv
->DIG_NumberFallbackVote
= 0;
197 priv
->DIG_NumberUpgradeVote
= 0;
203 * Dispatch DIG implementation according to RF.
205 static void DynamicInitGain(struct net_device
*dev
)
210 void rtl8180_hw_dig_wq(struct work_struct
*work
)
212 struct delayed_work
*dwork
= to_delayed_work(work
);
213 struct ieee80211_device
*ieee
= container_of(dwork
, struct ieee80211_device
, hw_dig_wq
);
214 struct net_device
*dev
= ieee
->dev
;
215 struct r8180_priv
*priv
= ieee80211_priv(dev
);
217 /* Read CCK and OFDM False Alarm. */
218 priv
->FalseAlarmRegValue
= read_nic_dword(dev
, CCK_FALSE_ALARM
);
221 /* Adjust Initial Gain dynamically. */
222 DynamicInitGain(dev
);
226 static int IncludedInSupportedRates(struct r8180_priv
*priv
, u8 TxRate
)
232 unsigned short Found
= 0;
233 u8 NaiveTxRate
= TxRate
&RateMask
;
235 rate_len
= priv
->ieee80211
->current_network
.rates_len
;
236 rate_ex_len
= priv
->ieee80211
->current_network
.rates_ex_len
;
237 for (idx
= 0; idx
< rate_len
; idx
++) {
238 if ((priv
->ieee80211
->current_network
.rates
[idx
] & RateMask
) == NaiveTxRate
) {
243 for (idx
= 0; idx
< rate_ex_len
; idx
++) {
244 if ((priv
->ieee80211
->current_network
.rates_ex
[idx
] & RateMask
) == NaiveTxRate
) {
255 * Get the Tx rate one degree up form the input rate in the supported rates.
256 * Return the upgrade rate if it is successed, otherwise return the input rate.
258 static u8
GetUpgradeTxRate(struct net_device
*dev
, u8 rate
)
260 struct r8180_priv
*priv
= ieee80211_priv(dev
);
263 /* Upgrade 1 degree. */
265 case 108: /* Up to 54Mbps. */
269 case 96: /* Up to 54Mbps. */
273 case 72: /* Up to 48Mbps. */
277 case 48: /* Up to 36Mbps. */
281 case 36: /* Up to 24Mbps. */
285 case 22: /* Up to 18Mbps. */
289 case 11: /* Up to 11Mbps. */
293 case 4: /* Up to 5.5Mbps. */
297 case 2: /* Up to 2Mbps. */
302 printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate
);
305 /* Check if the rate is valid. */
306 if (IncludedInSupportedRates(priv
, UpRate
)) {
314 * Get the Tx rate one degree down form the input rate in the supported rates.
315 * Return the degrade rate if it is successed, otherwise return the input rate.
318 static u8
GetDegradeTxRate(struct net_device
*dev
, u8 rate
)
320 struct r8180_priv
*priv
= ieee80211_priv(dev
);
323 /* Upgrade 1 degree. */
325 case 108: /* Down to 48Mbps. */
329 case 96: /* Down to 36Mbps. */
333 case 72: /* Down to 24Mbps. */
337 case 48: /* Down to 18Mbps. */
341 case 36: /* Down to 11Mbps. */
345 case 22: /* Down to 5.5Mbps. */
349 case 11: /* Down to 2Mbps. */
353 case 4: /* Down to 1Mbps. */
357 case 2: /* Down to 1Mbps. */
362 printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate
);
365 /* Check if the rate is valid. */
366 if (IncludedInSupportedRates(priv
, DownRate
)) {
374 * Helper function to determine if specified data rate is
378 static bool MgntIsCckRate(u16 rate
)
380 bool bReturn
= false;
382 if ((rate
<= 22) && (rate
!= 12) && (rate
!= 18)) {
390 * Tx Power tracking mechanism routine on 87SE.
392 void TxPwrTracking87SE(struct net_device
*dev
)
394 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
395 u8 tmpu1Byte
, CurrentThermal
, Idx
;
396 char CckTxPwrIdx
, OfdmTxPwrIdx
;
398 tmpu1Byte
= read_nic_byte(dev
, EN_LPF_CAL
);
399 CurrentThermal
= (tmpu1Byte
& 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */
400 CurrentThermal
= (CurrentThermal
> 0x0c) ? 0x0c : CurrentThermal
;/* lzm add 080826 */
402 if (CurrentThermal
!= priv
->ThermalMeter
) {
403 /* Update Tx Power level on each channel. */
404 for (Idx
= 1; Idx
< 15; Idx
++) {
405 CckTxPwrIdx
= priv
->chtxpwr
[Idx
];
406 OfdmTxPwrIdx
= priv
->chtxpwr_ofdm
[Idx
];
408 if (CurrentThermal
> priv
->ThermalMeter
) {
409 /* higher thermal meter. */
410 CckTxPwrIdx
+= (CurrentThermal
- priv
->ThermalMeter
) * 2;
411 OfdmTxPwrIdx
+= (CurrentThermal
- priv
->ThermalMeter
) * 2;
413 if (CckTxPwrIdx
> 35)
414 CckTxPwrIdx
= 35; /* Force TxPower to maximal index. */
415 if (OfdmTxPwrIdx
> 35)
418 /* lower thermal meter. */
419 CckTxPwrIdx
-= (priv
->ThermalMeter
- CurrentThermal
) * 2;
420 OfdmTxPwrIdx
-= (priv
->ThermalMeter
- CurrentThermal
) * 2;
424 if (OfdmTxPwrIdx
< 0)
428 /* Update TxPower level on CCK and OFDM resp. */
429 priv
->chtxpwr
[Idx
] = CckTxPwrIdx
;
430 priv
->chtxpwr_ofdm
[Idx
] = OfdmTxPwrIdx
;
433 /* Update TxPower level immediately. */
434 rtl8225z2_SetTXPowerLevel(dev
, priv
->ieee80211
->current_network
.channel
);
436 priv
->ThermalMeter
= CurrentThermal
;
438 static void StaRateAdaptive87SE(struct net_device
*dev
)
440 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
441 unsigned long CurrTxokCnt
;
444 unsigned long CurrRxokCnt
;
446 bool bTryDown
= false;
450 long CurrSignalStrength
;
451 bool bUpdateInitialGain
= false;
452 u8 u1bOfdm
= 0, u1bCck
= 0;
453 char OfdmTxPwrIdx
, CckTxPwrIdx
;
455 priv
->RateAdaptivePeriod
= RATE_ADAPTIVE_TIMER_PERIOD
;
458 CurrRetryCnt
= priv
->CurrRetryCnt
;
459 CurrTxokCnt
= priv
->NumTxOkTotal
- priv
->LastTxokCnt
;
460 CurrRxokCnt
= priv
->ieee80211
->NumRxOkTotal
- priv
->LastRxokCnt
;
461 CurrSignalStrength
= priv
->Stats_RecvSignalPower
;
462 TxThroughput
= (u32
)(priv
->NumTxOkBytesTotal
- priv
->LastTxOKBytes
);
463 priv
->LastTxOKBytes
= priv
->NumTxOkBytesTotal
;
464 priv
->CurrentOperaRate
= priv
->ieee80211
->rate
/ 5;
465 /* 2 Compute retry ratio. */
466 if (CurrTxokCnt
> 0) {
467 CurrRetryRate
= (u16
)(CurrRetryCnt
* 100 / CurrTxokCnt
);
469 /* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */
470 CurrRetryRate
= (u16
)(CurrRetryCnt
* 100 / 1);
473 priv
->LastRetryCnt
= priv
->CurrRetryCnt
;
474 priv
->LastTxokCnt
= priv
->NumTxOkTotal
;
475 priv
->LastRxokCnt
= priv
->ieee80211
->NumRxOkTotal
;
476 priv
->CurrRetryCnt
= 0;
478 /* 2No Tx packets, return to init_rate or not? */
479 if (CurrRetryRate
== 0 && CurrTxokCnt
== 0) {
481 * After 9 (30*300ms) seconds in this condition, we try to raise rate.
483 priv
->TryupingCountNoData
++;
485 /* [TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 */
486 if (priv
->TryupingCountNoData
> 30) {
487 priv
->TryupingCountNoData
= 0;
488 priv
->CurrentOperaRate
= GetUpgradeTxRate(dev
, priv
->CurrentOperaRate
);
489 /* Reset Fail Record */
490 priv
->LastFailTxRate
= 0;
491 priv
->LastFailTxRateSS
= -200;
492 priv
->FailTxRateCount
= 0;
496 priv
->TryupingCountNoData
= 0; /*Reset trying up times. */
501 * For Netgear case, I comment out the following signal strength estimation,
502 * which can results in lower rate to transmit when sample is NOT enough (e.g. PING request).
504 * Restructure rate adaptive as the following main stages:
505 * (1) Add retry threshold in 54M upgrading condition with signal strength.
506 * (2) Add the mechanism to degrade to CCK rate according to signal strength
508 * (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated
509 * situation, Initial Gain Update is upon on DIG mechanism except CCK rate.
510 * (4) Add the mechanism of trying to upgrade tx rate.
511 * (5) Record the information of upping tx rate to avoid trying upping tx rate constantly.
517 * Check more times in these rate(key rates).
519 if (priv
->CurrentOperaRate
== 22 || priv
->CurrentOperaRate
== 72)
522 * Let these rates down more difficult.
524 if (MgntIsCckRate(priv
->CurrentOperaRate
) || priv
->CurrentOperaRate
== 36)
528 if (priv
->bTryuping
== true) {
529 /* 2 For Test Upgrading mechanism
531 * Sometimes the throughput is upon on the capability between the AP and NIC,
532 * thus the low data rate does not improve the performance.
533 * We randomly upgrade the data rate and check if the retry rate is improved.
536 /* Upgrading rate did not improve the retry rate, fallback to the original rate. */
537 if ((CurrRetryRate
> 25) && TxThroughput
< priv
->LastTxThroughput
) {
538 /*Not necessary raising rate, fall back rate. */
541 priv
->bTryuping
= false;
543 } else if (CurrSignalStrength
> -47 && (CurrRetryRate
< 50)) {
547 * Return to highest data rate, if signal strength is good enough.
548 * SignalStrength threshold(-50dbm) is for RTL8186.
549 * Revise SignalStrength threshold to -51dbm.
551 /* Also need to check retry rate for safety, by Bruce, 2007-06-05. */
552 if (priv
->CurrentOperaRate
!= priv
->ieee80211
->current_network
.HighestOperaRate
) {
554 /* Upgrade Tx Rate directly. */
555 priv
->TryupingCount
+= TryUpTh
;
558 } else if (CurrTxokCnt
> 9 && CurrTxokCnt
< 100 && CurrRetryRate
>= 600) {
562 * Traffic is not busy but our Tx retry is serious.
565 /* Let Rate Mechanism to degrade tx rate directly. */
566 priv
->TryDownCountLowData
+= TryDownTh
;
567 } else if (priv
->CurrentOperaRate
== 108) {
570 if ((CurrRetryRate
> 26) && (priv
->LastRetryRate
> 25)) {
574 else if ((CurrRetryRate
> 17) && (priv
->LastRetryRate
> 16) && (CurrSignalStrength
> -72)) {
578 if (bTryDown
&& (CurrSignalStrength
< -75)) /* cable link */
579 priv
->TryDownCountLowData
+= TryDownTh
;
580 } else if (priv
->CurrentOperaRate
== 96) {
583 if (((CurrRetryRate
> 48) && (priv
->LastRetryRate
> 47))) {
585 } else if (((CurrRetryRate
> 21) && (priv
->LastRetryRate
> 20)) && (CurrSignalStrength
> -74)) { /* Cable Link */
586 /* Down to rate 36Mbps. */
588 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
590 priv
->TryDownCountLowData
+= TryDownTh
;
591 } else if ((CurrRetryRate
< 8) && (priv
->LastRetryRate
< 8)) { /* TO DO: need to consider (RSSI) */
595 if (bTryDown
&& (CurrSignalStrength
< -75)) {
596 priv
->TryDownCountLowData
+= TryDownTh
;
598 } else if (priv
->CurrentOperaRate
== 72) {
600 if ((CurrRetryRate
> 43) && (priv
->LastRetryRate
> 41)) {
601 /* Down to rate 24Mbps. */
603 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
605 priv
->TryDownCountLowData
+= TryDownTh
;
606 } else if ((CurrRetryRate
< 15) && (priv
->LastRetryRate
< 16)) { /* TO DO: need to consider (RSSI) */
610 if (bTryDown
&& (CurrSignalStrength
< -80))
611 priv
->TryDownCountLowData
+= TryDownTh
;
613 } else if (priv
->CurrentOperaRate
== 48) {
616 if (((CurrRetryRate
> 63) && (priv
->LastRetryRate
> 62))) {
618 } else if (((CurrRetryRate
> 33) && (priv
->LastRetryRate
> 32)) && (CurrSignalStrength
> -82)) { /* Cable Link */
620 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
622 priv
->TryDownCountLowData
+= TryDownTh
;
623 } else if ((CurrRetryRate
< 20) && (priv
->LastRetryRate
< 21)) { /* TO DO: need to consider (RSSI) */
627 if (bTryDown
&& (CurrSignalStrength
< -82))
628 priv
->TryDownCountLowData
+= TryDownTh
;
630 } else if (priv
->CurrentOperaRate
== 36) {
631 if (((CurrRetryRate
> 85) && (priv
->LastRetryRate
> 86))) {
633 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
635 priv
->TryDownCountLowData
+= TryDownTh
;
636 } else if ((CurrRetryRate
< 22) && (priv
->LastRetryRate
< 23)) { /* TO DO: need to consider (RSSI) */
639 } else if (priv
->CurrentOperaRate
== 22) {
641 if (CurrRetryRate
> 95) {
643 } else if ((CurrRetryRate
< 29) && (priv
->LastRetryRate
< 30)) { /*TO DO: need to consider (RSSI) */
646 } else if (priv
->CurrentOperaRate
== 11) {
648 if (CurrRetryRate
> 149) {
650 } else if ((CurrRetryRate
< 60) && (priv
->LastRetryRate
< 65)) {
653 } else if (priv
->CurrentOperaRate
== 4) {
655 if ((CurrRetryRate
> 99) && (priv
->LastRetryRate
> 99)) {
657 } else if ((CurrRetryRate
< 65) && (priv
->LastRetryRate
< 70)) {
660 } else if (priv
->CurrentOperaRate
== 2) {
662 if ((CurrRetryRate
< 70) && (priv
->LastRetryRate
< 75)) {
667 if (bTryUp
&& bTryDown
)
668 printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
670 /* 1 Test Upgrading Tx Rate
671 * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC.
672 * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate.
674 if (!bTryUp
&& !bTryDown
&& (priv
->TryupingCount
== 0) && (priv
->TryDownCountLowData
== 0)
675 && priv
->CurrentOperaRate
!= priv
->ieee80211
->current_network
.HighestOperaRate
&& priv
->FailTxRateCount
< 2) {
676 if (jiffies
% (CurrRetryRate
+ 101) == 0) {
678 priv
->bTryuping
= true;
682 /* 1 Rate Mechanism */
684 priv
->TryupingCount
++;
685 priv
->TryDownCountLowData
= 0;
688 * Check more times if we need to upgrade indeed.
689 * Because the largest value of pHalData->TryupingCount is 0xFFFF and
690 * the largest value of pHalData->FailTxRateCount is 0x14,
691 * this condition will be satisfied at most every 2 min.
694 if ((priv
->TryupingCount
> (TryUpTh
+ priv
->FailTxRateCount
* priv
->FailTxRateCount
)) ||
695 (CurrSignalStrength
> priv
->LastFailTxRateSS
) || priv
->bTryuping
) {
696 priv
->TryupingCount
= 0;
698 * When transferring from CCK to OFDM, DIG is an important issue.
700 if (priv
->CurrentOperaRate
== 22)
701 bUpdateInitialGain
= true;
704 * The difference in throughput between 48Mbps and 36Mbps is 8M.
705 * So, we must be careful in this rate scale. Isaiah 2008-02-15.
707 if (((priv
->CurrentOperaRate
== 72) || (priv
->CurrentOperaRate
== 48) || (priv
->CurrentOperaRate
== 36)) &&
708 (priv
->FailTxRateCount
> 2))
709 priv
->RateAdaptivePeriod
= (RATE_ADAPTIVE_TIMER_PERIOD
/ 2);
711 /* (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. */
712 /* (2)If the signal strength is increased, it may be able to upgrade. */
714 priv
->CurrentOperaRate
= GetUpgradeTxRate(dev
, priv
->CurrentOperaRate
);
716 if (priv
->CurrentOperaRate
== 36) {
717 priv
->bUpdateARFR
= true;
718 write_nic_word(dev
, ARFR
, 0x0F8F); /* bypass 12/9/6 */
719 } else if (priv
->bUpdateARFR
) {
720 priv
->bUpdateARFR
= false;
721 write_nic_word(dev
, ARFR
, 0x0FFF); /* set 1M ~ 54Mbps. */
724 /* Update Fail Tx rate and count. */
725 if (priv
->LastFailTxRate
!= priv
->CurrentOperaRate
) {
726 priv
->LastFailTxRate
= priv
->CurrentOperaRate
;
727 priv
->FailTxRateCount
= 0;
728 priv
->LastFailTxRateSS
= -200; /* Set lowest power. */
732 if (priv
->TryupingCount
> 0)
733 priv
->TryupingCount
--;
737 priv
->TryDownCountLowData
++;
738 priv
->TryupingCount
= 0;
740 /* Check if Tx rate can be degraded or Test trying upgrading should fallback. */
741 if (priv
->TryDownCountLowData
> TryDownTh
|| priv
->bTryuping
) {
742 priv
->TryDownCountLowData
= 0;
743 priv
->bTryuping
= false;
744 /* Update fail information. */
745 if (priv
->LastFailTxRate
== priv
->CurrentOperaRate
) {
746 priv
->FailTxRateCount
++;
747 /* Record the Tx fail rate signal strength. */
748 if (CurrSignalStrength
> priv
->LastFailTxRateSS
)
749 priv
->LastFailTxRateSS
= CurrSignalStrength
;
751 priv
->LastFailTxRate
= priv
->CurrentOperaRate
;
752 priv
->FailTxRateCount
= 1;
753 priv
->LastFailTxRateSS
= CurrSignalStrength
;
755 priv
->CurrentOperaRate
= GetDegradeTxRate(dev
, priv
->CurrentOperaRate
);
757 /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
758 if ((CurrSignalStrength
< -80) && (priv
->CurrentOperaRate
> 72)) {
759 priv
->CurrentOperaRate
= 72;
762 if (priv
->CurrentOperaRate
== 36) {
763 priv
->bUpdateARFR
= true;
764 write_nic_word(dev
, ARFR
, 0x0F8F); /* bypass 12/9/6 */
765 } else if (priv
->bUpdateARFR
) {
766 priv
->bUpdateARFR
= false;
767 write_nic_word(dev
, ARFR
, 0x0FFF); /* set 1M ~ 54Mbps. */
771 * When it is CCK rate, it may need to update initial gain to receive lower power packets.
773 if (MgntIsCckRate(priv
->CurrentOperaRate
)) {
774 bUpdateInitialGain
= true;
778 if (priv
->TryDownCountLowData
> 0)
779 priv
->TryDownCountLowData
--;
783 * Keep the Tx fail rate count to equal to 0x15 at most.
784 * Reduce the fail count at least to 10 sec if tx rate is tending stable.
786 if (priv
->FailTxRateCount
>= 0x15 ||
787 (!bTryUp
&& !bTryDown
&& priv
->TryDownCountLowData
== 0 && priv
->TryupingCount
&& priv
->FailTxRateCount
> 0x6)) {
788 priv
->FailTxRateCount
--;
792 OfdmTxPwrIdx
= priv
->chtxpwr_ofdm
[priv
->ieee80211
->current_network
.channel
];
793 CckTxPwrIdx
= priv
->chtxpwr
[priv
->ieee80211
->current_network
.channel
];
795 /* Mac0x9e increase 2 level in 36M~18M situation */
796 if ((priv
->CurrentOperaRate
< 96) && (priv
->CurrentOperaRate
> 22)) {
797 u1bCck
= read_nic_byte(dev
, CCK_TXAGC
);
798 u1bOfdm
= read_nic_byte(dev
, OFDM_TXAGC
);
800 /* case 1: Never enter High power */
801 if (u1bCck
== CckTxPwrIdx
) {
802 if (u1bOfdm
!= (OfdmTxPwrIdx
+ 2)) {
803 priv
->bEnhanceTxPwr
= true;
804 u1bOfdm
= ((u1bOfdm
+ 2) > 35) ? 35 : (u1bOfdm
+ 2);
805 write_nic_byte(dev
, OFDM_TXAGC
, u1bOfdm
);
807 } else if (u1bCck
< CckTxPwrIdx
) {
808 /* case 2: enter high power */
809 if (!priv
->bEnhanceTxPwr
) {
810 priv
->bEnhanceTxPwr
= true;
811 u1bOfdm
= ((u1bOfdm
+ 2) > 35) ? 35 : (u1bOfdm
+ 2);
812 write_nic_byte(dev
, OFDM_TXAGC
, u1bOfdm
);
815 } else if (priv
->bEnhanceTxPwr
) { /* 54/48/11/5.5/2/1 */
816 u1bCck
= read_nic_byte(dev
, CCK_TXAGC
);
817 u1bOfdm
= read_nic_byte(dev
, OFDM_TXAGC
);
819 /* case 1: Never enter High power */
820 if (u1bCck
== CckTxPwrIdx
) {
821 priv
->bEnhanceTxPwr
= false;
822 write_nic_byte(dev
, OFDM_TXAGC
, OfdmTxPwrIdx
);
824 /* case 2: enter high power */
825 else if (u1bCck
< CckTxPwrIdx
) {
826 priv
->bEnhanceTxPwr
= false;
827 u1bOfdm
= ((u1bOfdm
- 2) > 0) ? (u1bOfdm
- 2) : 0;
828 write_nic_byte(dev
, OFDM_TXAGC
, u1bOfdm
);
833 * We need update initial gain when we set tx rate "from OFDM to CCK" or
834 * "from CCK to OFDM".
837 if (bUpdateInitialGain
) {
838 if (MgntIsCckRate(priv
->CurrentOperaRate
)) { /* CCK */
839 if (priv
->InitialGain
> priv
->RegBModeGainStage
) {
840 priv
->InitialGainBackUp
= priv
->InitialGain
;
842 if (CurrSignalStrength
< -85) /* Low power, OFDM [0x17] = 26. */
843 /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */
844 priv
->InitialGain
= priv
->RegBModeGainStage
;
846 else if (priv
->InitialGain
> priv
->RegBModeGainStage
+ 1)
847 priv
->InitialGain
-= 2;
852 printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv
->InitialGain
, priv
->CurrentOperaRate
);
853 UpdateInitialGain(dev
);
856 if (priv
->InitialGain
< 4) {
857 priv
->InitialGainBackUp
= priv
->InitialGain
;
860 printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv
->InitialGain
, priv
->CurrentOperaRate
);
861 UpdateInitialGain(dev
);
866 /* Record the related info */
867 priv
->LastRetryRate
= CurrRetryRate
;
868 priv
->LastTxThroughput
= TxThroughput
;
869 priv
->ieee80211
->rate
= priv
->CurrentOperaRate
* 5;
872 void rtl8180_rate_adapter(struct work_struct
*work
)
874 struct delayed_work
*dwork
= to_delayed_work(work
);
875 struct ieee80211_device
*ieee
= container_of(dwork
, struct ieee80211_device
, rate_adapter_wq
);
876 struct net_device
*dev
= ieee
->dev
;
877 StaRateAdaptive87SE(dev
);
879 void timer_rate_adaptive(unsigned long data
)
881 struct r8180_priv
*priv
= ieee80211_priv((struct net_device
*)data
);
885 if ((priv
->ieee80211
->iw_mode
!= IW_MODE_MASTER
)
886 && (priv
->ieee80211
->state
== IEEE80211_LINKED
) &&
887 (priv
->ForcedDataRate
== 0)) {
888 queue_work(priv
->ieee80211
->wq
, (void *)&priv
->ieee80211
->rate_adapter_wq
);
890 priv
->rateadapter_timer
.expires
= jiffies
+ MSECS(priv
->RateAdaptivePeriod
);
891 add_timer(&priv
->rateadapter_timer
);
894 void SwAntennaDiversityRxOk8185(struct net_device
*dev
, u8 SignalStrength
)
896 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
900 if (priv
->AdRxSignalStrength
!= -1) {
901 priv
->AdRxSignalStrength
= ((priv
->AdRxSignalStrength
* 7) + (SignalStrength
* 3)) / 10;
902 } else { /* Initialization case. */
903 priv
->AdRxSignalStrength
= SignalStrength
;
906 if (priv
->LastRxPktAntenna
) /* Main antenna. */
907 priv
->AdMainAntennaRxOkCnt
++;
908 else /* Aux antenna. */
909 priv
->AdAuxAntennaRxOkCnt
++;
911 /* Change Antenna Switch. */
912 bool SetAntenna8185(struct net_device
*dev
, u8 u1bAntennaIndex
)
914 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
915 bool bAntennaSwitched
= false;
917 switch (u1bAntennaIndex
) {
919 /* Mac register, main antenna */
920 write_nic_byte(dev
, ANTSEL
, 0x03);
922 write_phy_cck(dev
, 0x11, 0x9b); /* Config CCK RX antenna. */
923 write_phy_ofdm(dev
, 0x0d, 0x5c); /* Config OFDM RX antenna. */
925 bAntennaSwitched
= true;
929 /* Mac register, aux antenna */
930 write_nic_byte(dev
, ANTSEL
, 0x00);
932 write_phy_cck(dev
, 0x11, 0xbb); /* Config CCK RX antenna. */
933 write_phy_ofdm(dev
, 0x0d, 0x54); /* Config OFDM RX antenna. */
935 bAntennaSwitched
= true;
940 printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex
);
944 if (bAntennaSwitched
)
945 priv
->CurrAntennaIndex
= u1bAntennaIndex
;
947 return bAntennaSwitched
;
949 /* Toggle Antenna switch. */
950 bool SwitchAntenna(struct net_device
*dev
)
952 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
956 if (priv
->CurrAntennaIndex
== 0) {
957 bResult
= SetAntenna8185(dev
, 1);
959 bResult
= SetAntenna8185(dev
, 0);
965 * Engine of SW Antenna Diversity mechanism.
966 * Since 8187 has no Tx part information,
967 * this implementation is only dependend on Rx part information.
969 void SwAntennaDiversity(struct net_device
*dev
)
971 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
972 bool bSwCheckSS
= false;
976 printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n",
977 priv
->AdTickCount
, priv
->AdCheckPeriod
);
978 printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n",
979 priv
->AdRxSignalStrength
, priv
->AdRxSsThreshold
);
982 /* Case 1. No Link. */
983 if (priv
->ieee80211
->state
!= IEEE80211_LINKED
) {
984 priv
->bAdSwitchedChecking
= false;
985 /* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */
988 /* Case 2. Linked but no packet receive.d */
989 } else if (priv
->AdRxOkCnt
== 0) {
990 priv
->bAdSwitchedChecking
= false;
993 /* Case 3. Evaluate last antenna switch action and undo it if necessary. */
994 } else if (priv
->bAdSwitchedChecking
== true) {
995 priv
->bAdSwitchedChecking
= false;
997 /* Adjust Rx signal strength threshold. */
998 priv
->AdRxSsThreshold
= (priv
->AdRxSignalStrength
+ priv
->AdRxSsBeforeSwitched
) / 2;
1000 priv
->AdRxSsThreshold
= (priv
->AdRxSsThreshold
> priv
->AdMaxRxSsThreshold
) ?
1001 priv
->AdMaxRxSsThreshold
: priv
->AdRxSsThreshold
;
1002 if (priv
->AdRxSignalStrength
< priv
->AdRxSsBeforeSwitched
) {
1003 /* Rx signal strength is not improved after we swtiched antenna. => Swich back. */
1004 /* Increase Antenna Diversity checking period due to bad decision. */
1005 priv
->AdCheckPeriod
*= 2;
1006 /* Increase Antenna Diversity checking period. */
1007 if (priv
->AdCheckPeriod
> priv
->AdMaxCheckPeriod
)
1008 priv
->AdCheckPeriod
= priv
->AdMaxCheckPeriod
;
1010 /* Wrong decision => switch back. */
1013 /* Rx Signal Strength is improved. */
1015 /* Reset Antenna Diversity checking period to its min value. */
1016 priv
->AdCheckPeriod
= priv
->AdMinCheckPeriod
;
1020 /* Case 4. Evaluate if we shall switch antenna now. */
1021 /* Cause Table Speed is very fast in TRC Dell Lab, we check it every time. */
1023 priv
->AdTickCount
= 0;
1026 * <Roger_Notes> We evaluate RxOk counts for each antenna first and than
1027 * evaluate signal strength.
1028 * The following operation can overcome the disability of CCA on both two antennas
1029 * When signal strength was extremely low or high.
1034 * Evaluate RxOk count from each antenna if we shall switch default antenna now.
1036 if ((priv
->AdMainAntennaRxOkCnt
< priv
->AdAuxAntennaRxOkCnt
)
1037 && (priv
->CurrAntennaIndex
== 0)) {
1038 /* We set Main antenna as default but RxOk count was less than Aux ones. */
1040 /* Switch to Aux antenna. */
1042 priv
->bHWAdSwitched
= true;
1043 } else if ((priv
->AdAuxAntennaRxOkCnt
< priv
->AdMainAntennaRxOkCnt
)
1044 && (priv
->CurrAntennaIndex
== 1)) {
1045 /* We set Aux antenna as default but RxOk count was less than Main ones. */
1047 /* Switch to Main antenna. */
1049 priv
->bHWAdSwitched
= true;
1051 /* Default antenna is better. */
1053 /* Still need to check current signal strength. */
1054 priv
->bHWAdSwitched
= false;
1057 * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
1058 * didn't change by HW evaluation.
1061 * [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05
1062 * For example, Throughput of aux is better than main antenna(about 10M v.s 2M),
1063 * but AdRxSignalStrength is less than main.
1064 * Our guess is that main antenna have lower throughput and get many change
1065 * to receive more CCK packets(ex.Beacon) which have stronger SignalStrength.
1067 if ((!priv
->bHWAdSwitched
) && (bSwCheckSS
)) {
1068 /* Evaluate Rx signal strength if we shall switch antenna now. */
1069 if (priv
->AdRxSignalStrength
< priv
->AdRxSsThreshold
) {
1070 /* Rx signal strength is weak => Switch Antenna. */
1071 priv
->AdRxSsBeforeSwitched
= priv
->AdRxSignalStrength
;
1072 priv
->bAdSwitchedChecking
= true;
1076 /* Rx signal strength is OK. */
1077 priv
->bAdSwitchedChecking
= false;
1078 /* Increase Rx signal strength threshold if necessary. */
1079 if ((priv
->AdRxSignalStrength
> (priv
->AdRxSsThreshold
+ 10)) && /* Signal is much stronger than current threshold */
1080 priv
->AdRxSsThreshold
<= priv
->AdMaxRxSsThreshold
) { /* Current threhold is not yet reach upper limit. */
1082 priv
->AdRxSsThreshold
= (priv
->AdRxSsThreshold
+ priv
->AdRxSignalStrength
) / 2;
1083 priv
->AdRxSsThreshold
= (priv
->AdRxSsThreshold
> priv
->AdMaxRxSsThreshold
) ?
1084 priv
->AdMaxRxSsThreshold
: priv
->AdRxSsThreshold
;/* +by amy 080312 */
1087 /* Reduce Antenna Diversity checking period if possible. */
1088 if (priv
->AdCheckPeriod
> priv
->AdMinCheckPeriod
)
1089 priv
->AdCheckPeriod
/= 2;
1093 /* Reset antenna diversity Rx related statistics. */
1094 priv
->AdRxOkCnt
= 0;
1095 priv
->AdMainAntennaRxOkCnt
= 0;
1096 priv
->AdAuxAntennaRxOkCnt
= 0;
1099 /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
1100 bool CheckTxPwrTracking(struct net_device
*dev
)
1102 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
1104 if (!priv
->bTxPowerTrack
)
1107 /* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */
1108 if (priv
->bToUpdateTxPwr
)
1115 /* Timer callback function of SW Antenna Diversity. */
1116 void SwAntennaDiversityTimerCallback(struct net_device
*dev
)
1118 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
1119 RT_RF_POWER_STATE rtState
;
1121 /* We do NOT need to switch antenna while RF is off. */
1122 rtState
= priv
->eRFPowerState
;
1124 if (rtState
== eRfOff
) {
1126 } else if (rtState
== eRfSleep
) {
1127 /* Don't access BB/RF under Disable PLL situation. */
1130 SwAntennaDiversity(dev
);
1135 priv
->SwAntennaDiversityTimer
.expires
= jiffies
+ MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD
);
1136 add_timer(&priv
->SwAntennaDiversityTimer
);