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 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 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 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 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 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 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 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 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
;
581 else if (priv
->CurrentOperaRate
== 96) {
584 if (((CurrRetryRate
> 48) && (priv
->LastRetryRate
> 47))) {
586 } else if (((CurrRetryRate
> 21) && (priv
->LastRetryRate
> 20)) && (CurrSignalStrength
> -74)) { /* Cable Link */
587 /* Down to rate 36Mbps. */
589 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
591 priv
->TryDownCountLowData
+= TryDownTh
;
592 } else if ((CurrRetryRate
< 8) && (priv
->LastRetryRate
< 8)) { /* TO DO: need to consider (RSSI) */
596 if (bTryDown
&& (CurrSignalStrength
< -75)){
597 priv
->TryDownCountLowData
+= TryDownTh
;
599 } else if (priv
->CurrentOperaRate
== 72) {
601 if ((CurrRetryRate
> 43) && (priv
->LastRetryRate
> 41)) {
602 /* Down to rate 24Mbps. */
604 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
606 priv
->TryDownCountLowData
+= TryDownTh
;
607 } else if ((CurrRetryRate
< 15) && (priv
->LastRetryRate
< 16)) { /* TO DO: need to consider (RSSI) */
611 if (bTryDown
&& (CurrSignalStrength
< -80))
612 priv
->TryDownCountLowData
+= TryDownTh
;
614 } else if (priv
->CurrentOperaRate
== 48) {
617 if (((CurrRetryRate
> 63) && (priv
->LastRetryRate
> 62))) {
619 } else if (((CurrRetryRate
> 33) && (priv
->LastRetryRate
> 32)) && (CurrSignalStrength
> -82)) { /* Cable Link */
621 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2 )) {
623 priv
->TryDownCountLowData
+= TryDownTh
;
624 } else if ((CurrRetryRate
< 20) && (priv
->LastRetryRate
< 21)) { /* TO DO: need to consider (RSSI) */
628 if (bTryDown
&& (CurrSignalStrength
< -82))
629 priv
->TryDownCountLowData
+= TryDownTh
;
631 } else if (priv
->CurrentOperaRate
== 36) {
632 if (((CurrRetryRate
> 85) && (priv
->LastRetryRate
> 86))) {
634 } else if ((CurrRetryRate
> (priv
->LastRetryRate
+ 50)) && (priv
->FailTxRateCount
> 2)) {
636 priv
->TryDownCountLowData
+= TryDownTh
;
637 } else if ((CurrRetryRate
< 22) && (priv
->LastRetryRate
< 23)) { /* TO DO: need to consider (RSSI) */
640 } else if (priv
->CurrentOperaRate
== 22) {
642 if (CurrRetryRate
> 95) {
645 else if ((CurrRetryRate
< 29) && (priv
->LastRetryRate
< 30)) { /*TO DO: need to consider (RSSI) */
648 } else if (priv
->CurrentOperaRate
== 11) {
650 if (CurrRetryRate
> 149) {
652 } else if ((CurrRetryRate
< 60) && (priv
->LastRetryRate
< 65)) {
655 } else if (priv
->CurrentOperaRate
== 4) {
657 if ((CurrRetryRate
> 99) && (priv
->LastRetryRate
> 99)) {
659 } else if ((CurrRetryRate
< 65) && (priv
->LastRetryRate
< 70)) {
662 } else if (priv
->CurrentOperaRate
== 2) {
664 if ((CurrRetryRate
< 70) && (priv
->LastRetryRate
< 75)) {
669 if (bTryUp
&& bTryDown
)
670 printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
672 /* 1 Test Upgrading Tx Rate
673 * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC.
674 * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate.
676 if (!bTryUp
&& !bTryDown
&& (priv
->TryupingCount
== 0) && (priv
->TryDownCountLowData
== 0)
677 && priv
->CurrentOperaRate
!= priv
->ieee80211
->current_network
.HighestOperaRate
&& priv
->FailTxRateCount
< 2) {
678 if (jiffies
% (CurrRetryRate
+ 101) == 0) {
680 priv
->bTryuping
= true;
684 /* 1 Rate Mechanism */
686 priv
->TryupingCount
++;
687 priv
->TryDownCountLowData
= 0;
690 * Check more times if we need to upgrade indeed.
691 * Because the largest value of pHalData->TryupingCount is 0xFFFF and
692 * the largest value of pHalData->FailTxRateCount is 0x14,
693 * this condition will be satisfied at most every 2 min.
696 if ((priv
->TryupingCount
> (TryUpTh
+ priv
->FailTxRateCount
* priv
->FailTxRateCount
)) ||
697 (CurrSignalStrength
> priv
->LastFailTxRateSS
) || priv
->bTryuping
) {
698 priv
->TryupingCount
= 0;
700 * When transferring from CCK to OFDM, DIG is an important issue.
702 if (priv
->CurrentOperaRate
== 22)
703 bUpdateInitialGain
= true;
706 * The difference in throughput between 48Mbps and 36Mbps is 8M.
707 * So, we must be careful in this rate scale. Isaiah 2008-02-15.
709 if (((priv
->CurrentOperaRate
== 72) || (priv
->CurrentOperaRate
== 48) || (priv
->CurrentOperaRate
== 36)) &&
710 (priv
->FailTxRateCount
> 2))
711 priv
->RateAdaptivePeriod
= (RATE_ADAPTIVE_TIMER_PERIOD
/ 2);
713 /* (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. */
714 /* (2)If the signal strength is increased, it may be able to upgrade. */
716 priv
->CurrentOperaRate
= GetUpgradeTxRate(dev
, priv
->CurrentOperaRate
);
718 if (priv
->CurrentOperaRate
== 36) {
719 priv
->bUpdateARFR
= true;
720 write_nic_word(dev
, ARFR
, 0x0F8F); /* bypass 12/9/6 */
721 } else if(priv
->bUpdateARFR
) {
722 priv
->bUpdateARFR
= false;
723 write_nic_word(dev
, ARFR
, 0x0FFF); /* set 1M ~ 54Mbps. */
726 /* Update Fail Tx rate and count. */
727 if (priv
->LastFailTxRate
!= priv
->CurrentOperaRate
) {
728 priv
->LastFailTxRate
= priv
->CurrentOperaRate
;
729 priv
->FailTxRateCount
= 0;
730 priv
->LastFailTxRateSS
= -200; /* Set lowest power. */
734 if (priv
->TryupingCount
> 0)
735 priv
->TryupingCount
--;
739 priv
->TryDownCountLowData
++;
740 priv
->TryupingCount
= 0;
742 /* Check if Tx rate can be degraded or Test trying upgrading should fallback. */
743 if (priv
->TryDownCountLowData
> TryDownTh
|| priv
->bTryuping
) {
744 priv
->TryDownCountLowData
= 0;
745 priv
->bTryuping
= false;
746 /* Update fail information. */
747 if (priv
->LastFailTxRate
== priv
->CurrentOperaRate
) {
748 priv
->FailTxRateCount
++;
749 /* Record the Tx fail rate signal strength. */
750 if (CurrSignalStrength
> priv
->LastFailTxRateSS
)
751 priv
->LastFailTxRateSS
= CurrSignalStrength
;
753 priv
->LastFailTxRate
= priv
->CurrentOperaRate
;
754 priv
->FailTxRateCount
= 1;
755 priv
->LastFailTxRateSS
= CurrSignalStrength
;
757 priv
->CurrentOperaRate
= GetDegradeTxRate(dev
, priv
->CurrentOperaRate
);
759 /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
760 if ((CurrSignalStrength
< -80) && (priv
->CurrentOperaRate
> 72 )) {
761 priv
->CurrentOperaRate
= 72;
764 if (priv
->CurrentOperaRate
== 36) {
765 priv
->bUpdateARFR
= true;
766 write_nic_word(dev
, ARFR
, 0x0F8F); /* bypass 12/9/6 */
767 } else if (priv
->bUpdateARFR
) {
768 priv
->bUpdateARFR
= false;
769 write_nic_word(dev
, ARFR
, 0x0FFF); /* set 1M ~ 54Mbps. */
773 * When it is CCK rate, it may need to update initial gain to receive lower power packets.
775 if (MgntIsCckRate(priv
->CurrentOperaRate
)) {
776 bUpdateInitialGain
= true;
780 if (priv
->TryDownCountLowData
> 0)
781 priv
->TryDownCountLowData
--;
785 * Keep the Tx fail rate count to equal to 0x15 at most.
786 * Reduce the fail count at least to 10 sec if tx rate is tending stable.
788 if (priv
->FailTxRateCount
>= 0x15 ||
789 (!bTryUp
&& !bTryDown
&& priv
->TryDownCountLowData
== 0 && priv
->TryupingCount
&& priv
->FailTxRateCount
> 0x6)) {
790 priv
->FailTxRateCount
--;
794 OfdmTxPwrIdx
= priv
->chtxpwr_ofdm
[priv
->ieee80211
->current_network
.channel
];
795 CckTxPwrIdx
= priv
->chtxpwr
[priv
->ieee80211
->current_network
.channel
];
797 /* Mac0x9e increase 2 level in 36M~18M situation */
798 if ((priv
->CurrentOperaRate
< 96) && (priv
->CurrentOperaRate
> 22)) {
799 u1bCck
= read_nic_byte(dev
, CCK_TXAGC
);
800 u1bOfdm
= read_nic_byte(dev
, OFDM_TXAGC
);
802 /* case 1: Never enter High power */
803 if (u1bCck
== CckTxPwrIdx
) {
804 if (u1bOfdm
!= (OfdmTxPwrIdx
+ 2)) {
805 priv
->bEnhanceTxPwr
= true;
806 u1bOfdm
= ((u1bOfdm
+ 2) > 35) ? 35: (u1bOfdm
+ 2);
807 write_nic_byte(dev
, OFDM_TXAGC
, u1bOfdm
);
809 } else if (u1bCck
< CckTxPwrIdx
) {
810 /* case 2: enter high power */
811 if (!priv
->bEnhanceTxPwr
) {
812 priv
->bEnhanceTxPwr
= true;
813 u1bOfdm
= ((u1bOfdm
+ 2) > 35) ? 35: (u1bOfdm
+ 2);
814 write_nic_byte(dev
, OFDM_TXAGC
, u1bOfdm
);
817 } else if (priv
->bEnhanceTxPwr
) { /* 54/48/11/5.5/2/1 */
818 u1bCck
= read_nic_byte(dev
, CCK_TXAGC
);
819 u1bOfdm
= read_nic_byte(dev
, OFDM_TXAGC
);
821 /* case 1: Never enter High power */
822 if (u1bCck
== CckTxPwrIdx
) {
823 priv
->bEnhanceTxPwr
= false;
824 write_nic_byte(dev
, OFDM_TXAGC
, OfdmTxPwrIdx
);
826 /* case 2: enter high power */
827 else if (u1bCck
< CckTxPwrIdx
) {
828 priv
->bEnhanceTxPwr
= false;
829 u1bOfdm
= ((u1bOfdm
- 2) > 0) ? (u1bOfdm
- 2): 0;
830 write_nic_byte(dev
, OFDM_TXAGC
, u1bOfdm
);
835 * We need update initial gain when we set tx rate "from OFDM to CCK" or
836 * "from CCK to OFDM".
839 if (bUpdateInitialGain
) {
840 if (MgntIsCckRate(priv
->CurrentOperaRate
)) { /* CCK */
841 if (priv
->InitialGain
> priv
->RegBModeGainStage
) {
842 priv
->InitialGainBackUp
= priv
->InitialGain
;
844 if (CurrSignalStrength
< -85) /* Low power, OFDM [0x17] = 26. */
845 /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */
846 priv
->InitialGain
= priv
->RegBModeGainStage
;
848 else if (priv
->InitialGain
> priv
->RegBModeGainStage
+ 1)
849 priv
->InitialGain
-= 2;
854 printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv
->InitialGain
, priv
->CurrentOperaRate
);
855 UpdateInitialGain(dev
);
858 if (priv
->InitialGain
< 4) {
859 priv
->InitialGainBackUp
= priv
->InitialGain
;
862 printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv
->InitialGain
, priv
->CurrentOperaRate
);
863 UpdateInitialGain(dev
);
868 /* Record the related info */
869 priv
->LastRetryRate
= CurrRetryRate
;
870 priv
->LastTxThroughput
= TxThroughput
;
871 priv
->ieee80211
->rate
= priv
->CurrentOperaRate
* 5;
874 void rtl8180_rate_adapter(struct work_struct
*work
)
876 struct delayed_work
*dwork
= to_delayed_work(work
);
877 struct ieee80211_device
*ieee
= container_of(dwork
, struct ieee80211_device
, rate_adapter_wq
);
878 struct net_device
*dev
= ieee
->dev
;
879 StaRateAdaptive87SE(dev
);
881 void timer_rate_adaptive(unsigned long data
)
883 struct r8180_priv
*priv
= ieee80211_priv((struct net_device
*)data
);
887 if ((priv
->ieee80211
->iw_mode
!= IW_MODE_MASTER
)
888 && (priv
->ieee80211
->state
== IEEE80211_LINKED
) &&
889 (priv
->ForcedDataRate
== 0)) {
890 queue_work(priv
->ieee80211
->wq
, (void *)&priv
->ieee80211
->rate_adapter_wq
);
892 priv
->rateadapter_timer
.expires
= jiffies
+ MSECS(priv
->RateAdaptivePeriod
);
893 add_timer(&priv
->rateadapter_timer
);
896 void SwAntennaDiversityRxOk8185(struct net_device
*dev
, u8 SignalStrength
)
898 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
902 if (priv
->AdRxSignalStrength
!= -1) {
903 priv
->AdRxSignalStrength
= ((priv
->AdRxSignalStrength
* 7) + (SignalStrength
* 3)) / 10;
904 } else { /* Initialization case. */
905 priv
->AdRxSignalStrength
= SignalStrength
;
908 if (priv
->LastRxPktAntenna
) /* Main antenna. */
909 priv
->AdMainAntennaRxOkCnt
++;
910 else /* Aux antenna. */
911 priv
->AdAuxAntennaRxOkCnt
++;
913 /* Change Antenna Switch. */
914 bool SetAntenna8185(struct net_device
*dev
, u8 u1bAntennaIndex
)
916 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
917 bool bAntennaSwitched
= false;
919 switch (u1bAntennaIndex
) {
921 /* Mac register, main antenna */
922 write_nic_byte(dev
, ANTSEL
, 0x03);
924 write_phy_cck(dev
, 0x11, 0x9b); /* Config CCK RX antenna. */
925 write_phy_ofdm(dev
, 0x0d, 0x5c); /* Config OFDM RX antenna. */
927 bAntennaSwitched
= true;
931 /* Mac register, aux antenna */
932 write_nic_byte(dev
, ANTSEL
, 0x00);
934 write_phy_cck(dev
, 0x11, 0xbb); /* Config CCK RX antenna. */
935 write_phy_ofdm(dev
, 0x0d, 0x54); /* Config OFDM RX antenna. */
937 bAntennaSwitched
= true;
942 printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex
);
947 priv
->CurrAntennaIndex
= u1bAntennaIndex
;
949 return bAntennaSwitched
;
951 /* Toggle Antenna switch. */
952 bool SwitchAntenna(struct net_device
*dev
)
954 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
958 if (priv
->CurrAntennaIndex
== 0) {
959 bResult
= SetAntenna8185(dev
, 1);
961 bResult
= SetAntenna8185(dev
, 0);
967 * Engine of SW Antenna Diversity mechanism.
968 * Since 8187 has no Tx part information,
969 * this implementation is only dependend on Rx part information.
971 void SwAntennaDiversity(struct net_device
*dev
)
973 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
974 bool bSwCheckSS
= false;
978 printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n",
979 priv
->AdTickCount
, priv
->AdCheckPeriod
);
980 printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n",
981 priv
->AdRxSignalStrength
, priv
->AdRxSsThreshold
);
984 /* Case 1. No Link. */
985 if (priv
->ieee80211
->state
!= IEEE80211_LINKED
) {
986 priv
->bAdSwitchedChecking
= false;
987 /* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */
990 /* Case 2. Linked but no packet receive.d */
991 } else if (priv
->AdRxOkCnt
== 0) {
992 priv
->bAdSwitchedChecking
= false;
995 /* Case 3. Evaluate last antenna switch action and undo it if necessary. */
996 } else if (priv
->bAdSwitchedChecking
== true) {
997 priv
->bAdSwitchedChecking
= false;
999 /* Adjust Rx signal strength threshold. */
1000 priv
->AdRxSsThreshold
= (priv
->AdRxSignalStrength
+ priv
->AdRxSsBeforeSwitched
) / 2;
1002 priv
->AdRxSsThreshold
= (priv
->AdRxSsThreshold
> priv
->AdMaxRxSsThreshold
) ?
1003 priv
->AdMaxRxSsThreshold
: priv
->AdRxSsThreshold
;
1004 if(priv
->AdRxSignalStrength
< priv
->AdRxSsBeforeSwitched
) {
1005 /* Rx signal strength is not improved after we swtiched antenna. => Swich back. */
1006 /* Increase Antenna Diversity checking period due to bad decision. */
1007 priv
->AdCheckPeriod
*= 2;
1008 /* Increase Antenna Diversity checking period. */
1009 if (priv
->AdCheckPeriod
> priv
->AdMaxCheckPeriod
)
1010 priv
->AdCheckPeriod
= priv
->AdMaxCheckPeriod
;
1012 /* Wrong decision => switch back. */
1015 /* Rx Signal Strength is improved. */
1017 /* Reset Antenna Diversity checking period to its min value. */
1018 priv
->AdCheckPeriod
= priv
->AdMinCheckPeriod
;
1022 /* Case 4. Evaluate if we shall switch antenna now. */
1023 /* Cause Table Speed is very fast in TRC Dell Lab, we check it every time. */
1025 priv
->AdTickCount
= 0;
1028 * <Roger_Notes> We evaluate RxOk counts for each antenna first and than
1029 * evaluate signal strength.
1030 * The following operation can overcome the disability of CCA on both two antennas
1031 * When signal strength was extremely low or high.
1036 * Evaluate RxOk count from each antenna if we shall switch default antenna now.
1038 if ((priv
->AdMainAntennaRxOkCnt
< priv
->AdAuxAntennaRxOkCnt
)
1039 && (priv
->CurrAntennaIndex
== 0)) {
1040 /* We set Main antenna as default but RxOk count was less than Aux ones. */
1042 /* Switch to Aux antenna. */
1044 priv
->bHWAdSwitched
= true;
1045 } else if ((priv
->AdAuxAntennaRxOkCnt
< priv
->AdMainAntennaRxOkCnt
)
1046 && (priv
->CurrAntennaIndex
== 1)) {
1047 /* We set Aux antenna as default but RxOk count was less than Main ones. */
1049 /* Switch to Main antenna. */
1051 priv
->bHWAdSwitched
= true;
1053 /* Default antenna is better. */
1055 /* Still need to check current signal strength. */
1056 priv
->bHWAdSwitched
= false;
1059 * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
1060 * didn't change by HW evaluation.
1063 * [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05
1064 * For example, Throughput of aux is better than main antenna(about 10M v.s 2M),
1065 * but AdRxSignalStrength is less than main.
1066 * Our guess is that main antenna have lower throughput and get many change
1067 * to receive more CCK packets(ex.Beacon) which have stronger SignalStrength.
1069 if ((!priv
->bHWAdSwitched
) && (bSwCheckSS
)) {
1070 /* Evaluate Rx signal strength if we shall switch antenna now. */
1071 if (priv
->AdRxSignalStrength
< priv
->AdRxSsThreshold
) {
1072 /* Rx signal strength is weak => Switch Antenna. */
1073 priv
->AdRxSsBeforeSwitched
= priv
->AdRxSignalStrength
;
1074 priv
->bAdSwitchedChecking
= true;
1078 /* Rx signal strength is OK. */
1079 priv
->bAdSwitchedChecking
= false;
1080 /* Increase Rx signal strength threshold if necessary. */
1081 if ((priv
->AdRxSignalStrength
> (priv
->AdRxSsThreshold
+ 10)) && /* Signal is much stronger than current threshold */
1082 priv
->AdRxSsThreshold
<= priv
->AdMaxRxSsThreshold
) { /* Current threhold is not yet reach upper limit. */
1084 priv
->AdRxSsThreshold
= (priv
->AdRxSsThreshold
+ priv
->AdRxSignalStrength
) / 2;
1085 priv
->AdRxSsThreshold
= (priv
->AdRxSsThreshold
> priv
->AdMaxRxSsThreshold
) ?
1086 priv
->AdMaxRxSsThreshold
: priv
->AdRxSsThreshold
;/* +by amy 080312 */
1089 /* Reduce Antenna Diversity checking period if possible. */
1090 if (priv
->AdCheckPeriod
> priv
->AdMinCheckPeriod
)
1091 priv
->AdCheckPeriod
/= 2;
1095 /* Reset antenna diversity Rx related statistics. */
1096 priv
->AdRxOkCnt
= 0;
1097 priv
->AdMainAntennaRxOkCnt
= 0;
1098 priv
->AdAuxAntennaRxOkCnt
= 0;
1101 /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
1102 bool CheckTxPwrTracking(struct net_device
*dev
)
1104 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
1106 if (!priv
->bTxPowerTrack
)
1109 /* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */
1110 if (priv
->bToUpdateTxPwr
)
1117 /* Timer callback function of SW Antenna Diversity. */
1118 void SwAntennaDiversityTimerCallback(struct net_device
*dev
)
1120 struct r8180_priv
*priv
= (struct r8180_priv
*)ieee80211_priv(dev
);
1121 RT_RF_POWER_STATE rtState
;
1123 /* We do NOT need to switch antenna while RF is off. */
1124 rtState
= priv
->eRFPowerState
;
1126 if (rtState
== eRfOff
) {
1128 } else if (rtState
== eRfSleep
) {
1129 /* Don't access BB/RF under Disable PLL situation. */
1132 SwAntennaDiversity(dev
);
1137 priv
->SwAntennaDiversityTimer
.expires
= jiffies
+ MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD
);
1138 add_timer(&priv
->SwAntennaDiversityTimer
);