ARM: common: edma: Fix xbar mapping
[deliverable/linux.git] / drivers / staging / rtl8187se / r8180_dm.c
CommitLineData
88adc104
GKH
1#include "r8180_dm.h"
2#include "r8180_hw.h"
3#include "r8180_93cx6.h"
da45e3fe 4
ed2cb4f3 5 /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */
88adc104
GKH
6#define RATE_ADAPTIVE_TIMER_PERIOD 300
7
8bool CheckHighPower(struct net_device *dev)
9{
10 struct r8180_priv *priv = ieee80211_priv(dev);
11 struct ieee80211_device *ieee = priv->ieee80211;
12
9cf66a95 13 if (!priv->bRegHighPowerMechanism)
88adc104 14 return false;
88adc104 15
9cf66a95 16 if (ieee->state == IEEE80211_LINKED_SCANNING)
88adc104 17 return false;
88adc104
GKH
18
19 return true;
20}
21
da45e3fe
AM
22/*
23 * Description:
24 * Update Tx power level if necessary.
25 * See also DoRxHighPower() and SetTxPowerLevel8185() for reference.
26 *
27 * Note:
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.
32 */
17ab33ee 33static void DoTxHighPower(struct net_device *dev)
88adc104
GKH
34{
35 struct r8180_priv *priv = ieee80211_priv(dev);
36 u16 HiPwrUpperTh = 0;
37 u16 HiPwrLowerTh = 0;
38 u8 RSSIHiPwrUpperTh;
39 u8 RSSIHiPwrLowerTh;
40 u8 u1bTmp;
41 char OfdmTxPwrIdx, CckTxPwrIdx;
42
88adc104
GKH
43 HiPwrUpperTh = priv->RegHiPwrUpperTh;
44 HiPwrLowerTh = priv->RegHiPwrLowerTh;
45
46 HiPwrUpperTh = HiPwrUpperTh * 10;
47 HiPwrLowerTh = HiPwrLowerTh * 10;
48 RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh;
49 RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh;
50
da45e3fe 51 /* lzm add 080826 */
88adc104
GKH
52 OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
53 CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel];
54
536d190d 55 if ((priv->UndecoratedSmoothedSS > HiPwrUpperTh) ||
aada7fdd 56 (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) {
da45e3fe 57 /* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */
88adc104 58
88adc104 59 priv->bToUpdateTxPwr = true;
9cf66a95 60 u1bTmp = read_nic_byte(dev, CCK_TXAGC);
88adc104 61
da45e3fe 62 /* If it never enter High Power. */
536d190d 63 if (CckTxPwrIdx == u1bTmp) {
9cf66a95 64 u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */
1748d2de 65 write_nic_byte(dev, CCK_TXAGC, u1bTmp);
88adc104 66
9cf66a95
AR
67 u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
68 u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */
1748d2de 69 write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
88adc104
GKH
70 }
71
536d190d 72 } else if ((priv->UndecoratedSmoothedSS < HiPwrLowerTh) &&
aada7fdd 73 (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) {
536d190d 74 if (priv->bToUpdateTxPwr) {
88adc104 75 priv->bToUpdateTxPwr = false;
da45e3fe 76 /* SD3 required. */
9cf66a95 77 u1bTmp = read_nic_byte(dev, CCK_TXAGC);
536d190d 78 if (u1bTmp < CckTxPwrIdx) {
1748d2de 79 write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx);
88adc104
GKH
80 }
81
9cf66a95 82 u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
536d190d 83 if (u1bTmp < OfdmTxPwrIdx) {
1748d2de 84 write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
88adc104
GKH
85 }
86 }
87 }
88adc104
GKH
88}
89
90
da45e3fe
AM
91/*
92 * Description:
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.
96 */
536d190d 97void rtl8180_tx_pw_wq(struct work_struct *work)
88adc104 98{
5f546031 99 struct delayed_work *dwork = to_delayed_work(work);
9cf66a95 100 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, tx_pw_wq);
1748d2de 101 struct net_device *dev = ieee->dev;
88adc104 102
88adc104 103 DoTxHighPower(dev);
88adc104
GKH
104}
105
106
da45e3fe 107/*
ed2cb4f3 108 * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise.
da45e3fe 109 */
536d190d 110bool CheckDig(struct net_device *dev)
88adc104
GKH
111{
112 struct r8180_priv *priv = ieee80211_priv(dev);
113 struct ieee80211_device *ieee = priv->ieee80211;
114
536d190d 115 if (!priv->bDigMechanism)
88adc104
GKH
116 return false;
117
536d190d 118 if (ieee->state != IEEE80211_LINKED)
88adc104
GKH
119 return false;
120
da45e3fe 121 if ((priv->ieee80211->rate / 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */
88adc104
GKH
122 return false;
123 return true;
124}
da45e3fe 125/*
3e837dca 126 * Implementation of DIG for Zebra and Zebra2.
da45e3fe 127 */
17ab33ee 128static void DIG_Zebra(struct net_device *dev)
88adc104
GKH
129{
130 struct r8180_priv *priv = ieee80211_priv(dev);
131 u16 CCKFalseAlarm, OFDMFalseAlarm;
132 u16 OfdmFA1, OfdmFA2;
da45e3fe
AM
133 int InitialGainStep = 7; /* The number of initial gain stages. */
134 int LowestGainStage = 4; /* The capable lowest stage of performing dig workitem. */
536d190d 135 u32 AwakePeriodIn2Sec = 0;
88adc104 136
88adc104
GKH
137 CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff);
138 OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff);
139 OfdmFA1 = 0x15;
140 OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8;
141
da45e3fe
AM
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) */
88adc104 146 }
da45e3fe 147 /* Advised from SD3 DZ */
536d190d 148 OfdmFA1 = 0x20;
88adc104 149
da45e3fe 150#if 1 /* lzm reserved 080826 */
536d190d 151 AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec);
9cf66a95 152 priv->DozePeriodInPast2Sec = 0;
88adc104 153
536d190d 154 if (AwakePeriodIn2Sec) {
9cf66a95
AR
155 OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000);
156 OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000);
aada7fdd 157 } else {
3e837dca 158 ;
88adc104
GKH
159 }
160#endif
161
162 InitialGainStep = 8;
da45e3fe 163 LowestGainStage = priv->RegBModeGainStage; /* Lowest gain stage. */
88adc104 164
aada7fdd
AM
165 if (OFDMFalseAlarm > OfdmFA1) {
166 if (OFDMFalseAlarm > OfdmFA2) {
88adc104 167 priv->DIG_NumberFallbackVote++;
536d190d 168 if (priv->DIG_NumberFallbackVote > 1) {
da45e3fe 169 /* serious OFDM False Alarm, need fallback */
aada7fdd 170 if (priv->InitialGain < InitialGainStep) {
536d190d 171 priv->InitialGainBackUp = priv->InitialGain;
88adc104
GKH
172
173 priv->InitialGain = (priv->InitialGain + 1);
88adc104
GKH
174 UpdateInitialGain(dev);
175 }
176 priv->DIG_NumberFallbackVote = 0;
536d190d 177 priv->DIG_NumberUpgradeVote = 0;
88adc104 178 }
aada7fdd 179 } else {
88adc104
GKH
180 if (priv->DIG_NumberFallbackVote)
181 priv->DIG_NumberFallbackVote--;
182 }
536d190d 183 priv->DIG_NumberUpgradeVote = 0;
aada7fdd 184 } else {
88adc104
GKH
185 if (priv->DIG_NumberFallbackVote)
186 priv->DIG_NumberFallbackVote--;
187 priv->DIG_NumberUpgradeVote++;
188
536d190d 189 if (priv->DIG_NumberUpgradeVote > 9) {
da45e3fe 190 if (priv->InitialGain > LowestGainStage) { /* In 87B, m78dBm means State 4 (m864dBm) */
536d190d 191 priv->InitialGainBackUp = priv->InitialGain;
88adc104
GKH
192
193 priv->InitialGain = (priv->InitialGain - 1);
88adc104
GKH
194 UpdateInitialGain(dev);
195 }
196 priv->DIG_NumberFallbackVote = 0;
536d190d 197 priv->DIG_NumberUpgradeVote = 0;
88adc104
GKH
198 }
199 }
88adc104
GKH
200}
201
da45e3fe 202/*
3e837dca 203 * Dispatch DIG implementation according to RF.
da45e3fe 204 */
17ab33ee 205static void DynamicInitGain(struct net_device *dev)
88adc104 206{
8daba6b9 207 DIG_Zebra(dev);
88adc104
GKH
208}
209
536d190d 210void rtl8180_hw_dig_wq(struct work_struct *work)
88adc104 211{
5f546031 212 struct delayed_work *dwork = to_delayed_work(work);
9cf66a95 213 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_dig_wq);
1748d2de 214 struct net_device *dev = ieee->dev;
88adc104
GKH
215 struct r8180_priv *priv = ieee80211_priv(dev);
216
da45e3fe 217 /* Read CCK and OFDM False Alarm. */
88adc104
GKH
218 priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM);
219
220
da45e3fe 221 /* Adjust Initial Gain dynamically. */
88adc104
GKH
222 DynamicInitGain(dev);
223
224}
225
17ab33ee 226static int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate)
88adc104 227{
1748d2de
AM
228 u8 rate_len;
229 u8 rate_ex_len;
230 u8 RateMask = 0x7F;
231 u8 idx;
232 unsigned short Found = 0;
233 u8 NaiveTxRate = TxRate&RateMask;
234
235 rate_len = priv->ieee80211->current_network.rates_len;
236 rate_ex_len = priv->ieee80211->current_network.rates_ex_len;
9cf66a95 237 for (idx = 0; idx < rate_len; idx++) {
536d190d 238 if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) {
1748d2de
AM
239 Found = 1;
240 goto found_rate;
241 }
242 }
536d190d
AM
243 for (idx = 0; idx < rate_ex_len; idx++) {
244 if ((priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate) {
1748d2de
AM
245 Found = 1;
246 goto found_rate;
247 }
248 }
249 return Found;
9cf66a95 250found_rate:
1748d2de 251 return Found;
88adc104
GKH
252}
253
da45e3fe 254/*
3e837dca
AM
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.
da45e3fe 257 */
17ab33ee 258static u8 GetUpgradeTxRate(struct net_device *dev, u8 rate)
88adc104 259{
1748d2de
AM
260 struct r8180_priv *priv = ieee80211_priv(dev);
261 u8 UpRate;
262
da45e3fe 263 /* Upgrade 1 degree. */
536d190d 264 switch (rate) {
da45e3fe 265 case 108: /* Up to 54Mbps. */
1748d2de
AM
266 UpRate = 108;
267 break;
268
da45e3fe 269 case 96: /* Up to 54Mbps. */
1748d2de
AM
270 UpRate = 108;
271 break;
272
da45e3fe 273 case 72: /* Up to 48Mbps. */
1748d2de
AM
274 UpRate = 96;
275 break;
276
da45e3fe 277 case 48: /* Up to 36Mbps. */
1748d2de
AM
278 UpRate = 72;
279 break;
280
da45e3fe 281 case 36: /* Up to 24Mbps. */
1748d2de
AM
282 UpRate = 48;
283 break;
284
da45e3fe 285 case 22: /* Up to 18Mbps. */
1748d2de
AM
286 UpRate = 36;
287 break;
288
da45e3fe 289 case 11: /* Up to 11Mbps. */
1748d2de
AM
290 UpRate = 22;
291 break;
292
da45e3fe 293 case 4: /* Up to 5.5Mbps. */
1748d2de
AM
294 UpRate = 11;
295 break;
296
da45e3fe 297 case 2: /* Up to 2Mbps. */
1748d2de
AM
298 UpRate = 4;
299 break;
300
301 default:
302 printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
303 return rate;
304 }
da45e3fe 305 /* Check if the rate is valid. */
536d190d 306 if (IncludedInSupportedRates(priv, UpRate)) {
1748d2de
AM
307 return UpRate;
308 } else {
1748d2de
AM
309 return rate;
310 }
311 return rate;
88adc104 312}
da45e3fe 313/*
3e837dca
AM
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.
da45e3fe
AM
316 */
317
17ab33ee 318static u8 GetDegradeTxRate(struct net_device *dev, u8 rate)
88adc104 319{
1748d2de
AM
320 struct r8180_priv *priv = ieee80211_priv(dev);
321 u8 DownRate;
322
da45e3fe 323 /* Upgrade 1 degree. */
536d190d 324 switch (rate) {
da45e3fe 325 case 108: /* Down to 48Mbps. */
1748d2de
AM
326 DownRate = 96;
327 break;
328
da45e3fe 329 case 96: /* Down to 36Mbps. */
1748d2de
AM
330 DownRate = 72;
331 break;
332
da45e3fe 333 case 72: /* Down to 24Mbps. */
1748d2de
AM
334 DownRate = 48;
335 break;
336
da45e3fe 337 case 48: /* Down to 18Mbps. */
1748d2de
AM
338 DownRate = 36;
339 break;
340
da45e3fe 341 case 36: /* Down to 11Mbps. */
1748d2de
AM
342 DownRate = 22;
343 break;
344
da45e3fe 345 case 22: /* Down to 5.5Mbps. */
1748d2de
AM
346 DownRate = 11;
347 break;
348
da45e3fe 349 case 11: /* Down to 2Mbps. */
1748d2de
AM
350 DownRate = 4;
351 break;
352
da45e3fe 353 case 4: /* Down to 1Mbps. */
1748d2de
AM
354 DownRate = 2;
355 break;
356
da45e3fe 357 case 2: /* Down to 1Mbps. */
1748d2de
AM
358 DownRate = 2;
359 break;
360
361 default:
362 printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
363 return rate;
364 }
da45e3fe 365 /* Check if the rate is valid. */
536d190d 366 if (IncludedInSupportedRates(priv, DownRate)) {
1748d2de
AM
367 return DownRate;
368 } else {
1748d2de
AM
369 return rate;
370 }
371 return rate;
88adc104 372}
da45e3fe
AM
373/*
374 * Helper function to determine if specified data rate is
375 * CCK rate.
da45e3fe
AM
376 */
377
17ab33ee 378static bool MgntIsCckRate(u16 rate)
88adc104 379{
1748d2de 380 bool bReturn = false;
88adc104 381
536d190d 382 if ((rate <= 22) && (rate != 12) && (rate != 18)) {
1748d2de
AM
383 bReturn = true;
384 }
88adc104 385
1748d2de 386 return bReturn;
88adc104 387}
da45e3fe
AM
388/*
389 * Description:
390 * Tx Power tracking mechanism routine on 87SE.
da45e3fe 391 */
536d190d 392void TxPwrTracking87SE(struct net_device *dev)
88adc104
GKH
393{
394 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
395 u8 tmpu1Byte, CurrentThermal, Idx;
396 char CckTxPwrIdx, OfdmTxPwrIdx;
88adc104
GKH
397
398 tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL);
da45e3fe 399 CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */
9cf66a95 400 CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c : CurrentThermal;/* lzm add 080826 */
88adc104 401
536d190d 402 if (CurrentThermal != priv->ThermalMeter) {
da45e3fe 403 /* Update Tx Power level on each channel. */
536d190d 404 for (Idx = 1; Idx < 15; Idx++) {
88adc104
GKH
405 CckTxPwrIdx = priv->chtxpwr[Idx];
406 OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx];
407
536d190d 408 if (CurrentThermal > priv->ThermalMeter) {
da45e3fe 409 /* higher thermal meter. */
536d190d
AM
410 CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
411 OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
88adc104 412
536d190d 413 if (CckTxPwrIdx > 35)
da45e3fe 414 CckTxPwrIdx = 35; /* Force TxPower to maximal index. */
536d190d 415 if (OfdmTxPwrIdx > 35)
88adc104 416 OfdmTxPwrIdx = 35;
aada7fdd 417 } else {
da45e3fe 418 /* lower thermal meter. */
536d190d
AM
419 CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
420 OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
88adc104 421
536d190d 422 if (CckTxPwrIdx < 0)
88adc104 423 CckTxPwrIdx = 0;
536d190d 424 if (OfdmTxPwrIdx < 0)
88adc104
GKH
425 OfdmTxPwrIdx = 0;
426 }
427
da45e3fe 428 /* Update TxPower level on CCK and OFDM resp. */
88adc104
GKH
429 priv->chtxpwr[Idx] = CckTxPwrIdx;
430 priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx;
431 }
432
da45e3fe 433 /* Update TxPower level immediately. */
88adc104
GKH
434 rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel);
435 }
436 priv->ThermalMeter = CurrentThermal;
437}
17ab33ee 438static void StaRateAdaptive87SE(struct net_device *dev)
88adc104
GKH
439{
440 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1748d2de
AM
441 unsigned long CurrTxokCnt;
442 u16 CurrRetryCnt;
443 u16 CurrRetryRate;
1748d2de
AM
444 unsigned long CurrRxokCnt;
445 bool bTryUp = false;
446 bool bTryDown = false;
447 u8 TryUpTh = 1;
448 u8 TryDownTh = 2;
449 u32 TxThroughput;
88adc104
GKH
450 long CurrSignalStrength;
451 bool bUpdateInitialGain = false;
536d190d 452 u8 u1bOfdm = 0, u1bCck = 0;
88adc104
GKH
453 char OfdmTxPwrIdx, CckTxPwrIdx;
454
536d190d 455 priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
88adc104
GKH
456
457
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;
536d190d 464 priv->CurrentOperaRate = priv->ieee80211->rate / 5;
da45e3fe 465 /* 2 Compute retry ratio. */
536d190d
AM
466 if (CurrTxokCnt > 0) {
467 CurrRetryRate = (u16)(CurrRetryCnt * 100 / CurrTxokCnt);
aada7fdd 468 } else {
da45e3fe 469 /* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */
536d190d 470 CurrRetryRate = (u16)(CurrRetryCnt * 100 / 1);
88adc104
GKH
471 }
472
88adc104
GKH
473 priv->LastRetryCnt = priv->CurrRetryCnt;
474 priv->LastTxokCnt = priv->NumTxOkTotal;
475 priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal;
476 priv->CurrRetryCnt = 0;
477
da45e3fe 478 /* 2No Tx packets, return to init_rate or not? */
536d190d 479 if (CurrRetryRate == 0 && CurrTxokCnt == 0) {
da45e3fe
AM
480 /*
481 * After 9 (30*300ms) seconds in this condition, we try to raise rate.
482 */
88adc104
GKH
483 priv->TryupingCountNoData++;
484
da45e3fe 485 /* [TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 */
536d190d 486 if (priv->TryupingCountNoData > 30) {
88adc104 487 priv->TryupingCountNoData = 0;
004c7acb 488 priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
da45e3fe 489 /* Reset Fail Record */
88adc104
GKH
490 priv->LastFailTxRate = 0;
491 priv->LastFailTxRateSS = -200;
492 priv->FailTxRateCount = 0;
493 }
494 goto SetInitialGain;
aada7fdd 495 } else {
da45e3fe 496 priv->TryupingCountNoData = 0; /*Reset trying up times. */
88adc104
GKH
497 }
498
499
da45e3fe
AM
500 /*
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).
da45e3fe
AM
503 *
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
507 * and retry rate.
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.
ed2cb4f3 510 * (4) Add the mechanism of trying to upgrade tx rate.
da45e3fe 511 * (5) Record the information of upping tx rate to avoid trying upping tx rate constantly.
da45e3fe
AM
512 *
513 */
514
515 /*
9cf66a95 516 * 11Mbps or 36Mbps
da45e3fe
AM
517 * Check more times in these rate(key rates).
518 */
536d190d 519 if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72)
88adc104 520 TryUpTh += 9;
da45e3fe
AM
521 /*
522 * Let these rates down more difficult.
523 */
536d190d 524 if (MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36)
1748d2de 525 TryDownTh += 1;
88adc104 526
da45e3fe 527 /* 1 Adjust Rate. */
aada7fdd 528 if (priv->bTryuping == true) {
da45e3fe
AM
529 /* 2 For Test Upgrading mechanism
530 * Note:
ed2cb4f3 531 * Sometimes the throughput is upon on the capability between the AP and NIC,
da45e3fe
AM
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.
534 */
535
536 /* Upgrading rate did not improve the retry rate, fallback to the original rate. */
536d190d 537 if ((CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) {
da45e3fe 538 /*Not necessary raising rate, fall back rate. */
88adc104 539 bTryDown = true;
aada7fdd 540 } else {
88adc104
GKH
541 priv->bTryuping = false;
542 }
aada7fdd 543 } else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) {
da45e3fe 544 /*
9cf66a95 545 * 2For High Power
da45e3fe 546 *
da45e3fe
AM
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.
550 */
551 /* Also need to check retry rate for safety, by Bruce, 2007-06-05. */
536d190d 552 if (priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate) {
88adc104 553 bTryUp = true;
da45e3fe 554 /* Upgrade Tx Rate directly. */
88adc104
GKH
555 priv->TryupingCount += TryUpTh;
556 }
88adc104 557
536d190d 558 } else if (CurrTxokCnt > 9 && CurrTxokCnt < 100 && CurrRetryRate >= 600) {
da45e3fe
AM
559 /*
560 *2 For Serious Retry
561 *
562 * Traffic is not busy but our Tx retry is serious.
563 */
88adc104 564 bTryDown = true;
da45e3fe 565 /* Let Rate Mechanism to degrade tx rate directly. */
88adc104 566 priv->TryDownCountLowData += TryDownTh;
536d190d 567 } else if (priv->CurrentOperaRate == 108) {
da45e3fe
AM
568 /* 2For 54Mbps */
569 /* Air Link */
536d190d 570 if ((CurrRetryRate > 26) && (priv->LastRetryRate > 25)) {
88adc104
GKH
571 bTryDown = true;
572 }
da45e3fe 573 /* Cable Link */
536d190d 574 else if ((CurrRetryRate > 17) && (priv->LastRetryRate > 16) && (CurrSignalStrength > -72)) {
88adc104
GKH
575 bTryDown = true;
576 }
577
da45e3fe 578 if (bTryDown && (CurrSignalStrength < -75)) /* cable link */
88adc104 579 priv->TryDownCountLowData += TryDownTh;
9cf66a95 580 } else if (priv->CurrentOperaRate == 96) {
da45e3fe
AM
581 /* 2For 48Mbps */
582 /* Air Link */
536d190d 583 if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) {
88adc104 584 bTryDown = true;
da45e3fe
AM
585 } else if (((CurrRetryRate > 21) && (priv->LastRetryRate > 20)) && (CurrSignalStrength > -74)) { /* Cable Link */
586 /* Down to rate 36Mbps. */
88adc104 587 bTryDown = true;
536d190d 588 } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
88adc104
GKH
589 bTryDown = true;
590 priv->TryDownCountLowData += TryDownTh;
da45e3fe 591 } else if ((CurrRetryRate < 8) && (priv->LastRetryRate < 8)) { /* TO DO: need to consider (RSSI) */
88adc104
GKH
592 bTryUp = true;
593 }
594
9cf66a95 595 if (bTryDown && (CurrSignalStrength < -75)) {
88adc104
GKH
596 priv->TryDownCountLowData += TryDownTh;
597 }
536d190d 598 } else if (priv->CurrentOperaRate == 72) {
da45e3fe 599 /* 2For 36Mbps */
536d190d 600 if ((CurrRetryRate > 43) && (priv->LastRetryRate > 41)) {
da45e3fe 601 /* Down to rate 24Mbps. */
88adc104 602 bTryDown = true;
536d190d 603 } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
88adc104
GKH
604 bTryDown = true;
605 priv->TryDownCountLowData += TryDownTh;
da45e3fe 606 } else if ((CurrRetryRate < 15) && (priv->LastRetryRate < 16)) { /* TO DO: need to consider (RSSI) */
88adc104
GKH
607 bTryUp = true;
608 }
609
536d190d 610 if (bTryDown && (CurrSignalStrength < -80))
88adc104 611 priv->TryDownCountLowData += TryDownTh;
aada7fdd 612
536d190d 613 } else if (priv->CurrentOperaRate == 48) {
da45e3fe
AM
614 /* 2For 24Mbps */
615 /* Air Link */
536d190d 616 if (((CurrRetryRate > 63) && (priv->LastRetryRate > 62))) {
88adc104 617 bTryDown = true;
da45e3fe 618 } else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */
88adc104 619 bTryDown = true;
9cf66a95 620 } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
88adc104
GKH
621 bTryDown = true;
622 priv->TryDownCountLowData += TryDownTh;
da45e3fe 623 } else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */
88adc104
GKH
624 bTryUp = true;
625 }
626
536d190d 627 if (bTryDown && (CurrSignalStrength < -82))
88adc104 628 priv->TryDownCountLowData += TryDownTh;
aada7fdd 629
536d190d 630 } else if (priv->CurrentOperaRate == 36) {
536d190d 631 if (((CurrRetryRate > 85) && (priv->LastRetryRate > 86))) {
88adc104 632 bTryDown = true;
536d190d 633 } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
88adc104
GKH
634 bTryDown = true;
635 priv->TryDownCountLowData += TryDownTh;
da45e3fe 636 } else if ((CurrRetryRate < 22) && (priv->LastRetryRate < 23)) { /* TO DO: need to consider (RSSI) */
88adc104
GKH
637 bTryUp = true;
638 }
536d190d 639 } else if (priv->CurrentOperaRate == 22) {
da45e3fe 640 /* 2For 11Mbps */
536d190d 641 if (CurrRetryRate > 95) {
88adc104 642 bTryDown = true;
9cf66a95 643 } else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */
88adc104 644 bTryUp = true;
88adc104 645 }
536d190d 646 } else if (priv->CurrentOperaRate == 11) {
da45e3fe 647 /* 2For 5.5Mbps */
536d190d 648 if (CurrRetryRate > 149) {
88adc104 649 bTryDown = true;
536d190d 650 } else if ((CurrRetryRate < 60) && (priv->LastRetryRate < 65)) {
88adc104 651 bTryUp = true;
88adc104 652 }
536d190d 653 } else if (priv->CurrentOperaRate == 4) {
da45e3fe 654 /* 2For 2 Mbps */
536d190d 655 if ((CurrRetryRate > 99) && (priv->LastRetryRate > 99)) {
88adc104 656 bTryDown = true;
536d190d 657 } else if ((CurrRetryRate < 65) && (priv->LastRetryRate < 70)) {
88adc104
GKH
658 bTryUp = true;
659 }
536d190d 660 } else if (priv->CurrentOperaRate == 2) {
da45e3fe 661 /* 2For 1 Mbps */
536d190d 662 if ((CurrRetryRate < 70) && (priv->LastRetryRate < 75)) {
88adc104
GKH
663 bTryUp = true;
664 }
88adc104
GKH
665 }
666
536d190d 667 if (bTryUp && bTryDown)
3717013a 668 printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
88adc104 669
da45e3fe
AM
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.
9cf66a95 673 */
536d190d 674 if (!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0)
aada7fdd 675 && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) {
536d190d 676 if (jiffies % (CurrRetryRate + 101) == 0) {
88adc104
GKH
677 bTryUp = true;
678 priv->bTryuping = true;
88adc104
GKH
679 }
680 }
681
da45e3fe 682 /* 1 Rate Mechanism */
536d190d 683 if (bTryUp) {
88adc104
GKH
684 priv->TryupingCount++;
685 priv->TryDownCountLowData = 0;
686
da45e3fe
AM
687 /*
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.
692 */
88adc104 693
536d190d 694 if ((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) ||
aada7fdd 695 (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) {
88adc104 696 priv->TryupingCount = 0;
da45e3fe
AM
697 /*
698 * When transferring from CCK to OFDM, DIG is an important issue.
699 */
536d190d 700 if (priv->CurrentOperaRate == 22)
88adc104
GKH
701 bUpdateInitialGain = true;
702
9cf66a95 703 /*
da45e3fe 704 * The difference in throughput between 48Mbps and 36Mbps is 8M.
ed2cb4f3 705 * So, we must be careful in this rate scale. Isaiah 2008-02-15.
da45e3fe 706 */
536d190d
AM
707 if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) &&
708 (priv->FailTxRateCount > 2))
709 priv->RateAdaptivePeriod = (RATE_ADAPTIVE_TIMER_PERIOD / 2);
88adc104 710
da45e3fe
AM
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. */
88adc104
GKH
713
714 priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate);
88adc104 715
536d190d
AM
716 if (priv->CurrentOperaRate == 36) {
717 priv->bUpdateARFR = true;
da45e3fe 718 write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
9cf66a95 719 } else if (priv->bUpdateARFR) {
536d190d 720 priv->bUpdateARFR = false;
da45e3fe 721 write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
88adc104
GKH
722 }
723
da45e3fe 724 /* Update Fail Tx rate and count. */
536d190d 725 if (priv->LastFailTxRate != priv->CurrentOperaRate) {
88adc104
GKH
726 priv->LastFailTxRate = priv->CurrentOperaRate;
727 priv->FailTxRateCount = 0;
da45e3fe 728 priv->LastFailTxRateSS = -200; /* Set lowest power. */
88adc104
GKH
729 }
730 }
aada7fdd 731 } else {
536d190d 732 if (priv->TryupingCount > 0)
9cf66a95 733 priv->TryupingCount--;
88adc104
GKH
734 }
735
536d190d 736 if (bTryDown) {
88adc104
GKH
737 priv->TryDownCountLowData++;
738 priv->TryupingCount = 0;
aada7fdd 739
da45e3fe 740 /* Check if Tx rate can be degraded or Test trying upgrading should fallback. */
536d190d 741 if (priv->TryDownCountLowData > TryDownTh || priv->bTryuping) {
88adc104
GKH
742 priv->TryDownCountLowData = 0;
743 priv->bTryuping = false;
da45e3fe 744 /* Update fail information. */
536d190d
AM
745 if (priv->LastFailTxRate == priv->CurrentOperaRate) {
746 priv->FailTxRateCount++;
da45e3fe 747 /* Record the Tx fail rate signal strength. */
536d190d 748 if (CurrSignalStrength > priv->LastFailTxRateSS)
88adc104 749 priv->LastFailTxRateSS = CurrSignalStrength;
aada7fdd 750 } else {
88adc104
GKH
751 priv->LastFailTxRate = priv->CurrentOperaRate;
752 priv->FailTxRateCount = 1;
753 priv->LastFailTxRateSS = CurrSignalStrength;
754 }
755 priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate);
756
da45e3fe 757 /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
9cf66a95 758 if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72)) {
88adc104 759 priv->CurrentOperaRate = 72;
88adc104
GKH
760 }
761
536d190d
AM
762 if (priv->CurrentOperaRate == 36) {
763 priv->bUpdateARFR = true;
da45e3fe 764 write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
536d190d
AM
765 } else if (priv->bUpdateARFR) {
766 priv->bUpdateARFR = false;
da45e3fe 767 write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
88adc104
GKH
768 }
769
da45e3fe
AM
770 /*
771 * When it is CCK rate, it may need to update initial gain to receive lower power packets.
772 */
536d190d 773 if (MgntIsCckRate(priv->CurrentOperaRate)) {
88adc104
GKH
774 bUpdateInitialGain = true;
775 }
88adc104 776 }
aada7fdd 777 } else {
536d190d
AM
778 if (priv->TryDownCountLowData > 0)
779 priv->TryDownCountLowData--;
88adc104
GKH
780 }
781
9cf66a95
AR
782 /*
783 * Keep the Tx fail rate count to equal to 0x15 at most.
da45e3fe
AM
784 * Reduce the fail count at least to 10 sec if tx rate is tending stable.
785 */
536d190d 786 if (priv->FailTxRateCount >= 0x15 ||
aada7fdd 787 (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) {
536d190d 788 priv->FailTxRateCount--;
88adc104
GKH
789 }
790
791
792 OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
793 CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel];
794
3e837dca 795 /* Mac0x9e increase 2 level in 36M~18M situation */
536d190d 796 if ((priv->CurrentOperaRate < 96) && (priv->CurrentOperaRate > 22)) {
88adc104
GKH
797 u1bCck = read_nic_byte(dev, CCK_TXAGC);
798 u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
799
da45e3fe 800 /* case 1: Never enter High power */
536d190d
AM
801 if (u1bCck == CckTxPwrIdx) {
802 if (u1bOfdm != (OfdmTxPwrIdx + 2)) {
803 priv->bEnhanceTxPwr = true;
9cf66a95 804 u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
88adc104 805 write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
88adc104 806 }
536d190d 807 } else if (u1bCck < CckTxPwrIdx) {
da45e3fe 808 /* case 2: enter high power */
536d190d
AM
809 if (!priv->bEnhanceTxPwr) {
810 priv->bEnhanceTxPwr = true;
9cf66a95 811 u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
88adc104 812 write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
88adc104
GKH
813 }
814 }
da45e3fe 815 } else if (priv->bEnhanceTxPwr) { /* 54/48/11/5.5/2/1 */
88adc104
GKH
816 u1bCck = read_nic_byte(dev, CCK_TXAGC);
817 u1bOfdm = read_nic_byte(dev, OFDM_TXAGC);
818
da45e3fe 819 /* case 1: Never enter High power */
536d190d
AM
820 if (u1bCck == CckTxPwrIdx) {
821 priv->bEnhanceTxPwr = false;
1748d2de 822 write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
88adc104 823 }
da45e3fe 824 /* case 2: enter high power */
536d190d
AM
825 else if (u1bCck < CckTxPwrIdx) {
826 priv->bEnhanceTxPwr = false;
9cf66a95 827 u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2) : 0;
88adc104 828 write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
88adc104
GKH
829 }
830 }
831
da45e3fe
AM
832 /*
833 * We need update initial gain when we set tx rate "from OFDM to CCK" or
834 * "from CCK to OFDM".
835 */
88adc104 836SetInitialGain:
536d190d 837 if (bUpdateInitialGain) {
da45e3fe 838 if (MgntIsCckRate(priv->CurrentOperaRate)) { /* CCK */
536d190d
AM
839 if (priv->InitialGain > priv->RegBModeGainStage) {
840 priv->InitialGainBackUp = priv->InitialGain;
88adc104 841
da45e3fe
AM
842 if (CurrSignalStrength < -85) /* Low power, OFDM [0x17] = 26. */
843 /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */
88adc104 844 priv->InitialGain = priv->RegBModeGainStage;
aada7fdd 845
536d190d 846 else if (priv->InitialGain > priv->RegBModeGainStage + 1)
88adc104 847 priv->InitialGain -= 2;
aada7fdd 848
1748d2de 849 else
536d190d 850 priv->InitialGain--;
aada7fdd 851
9cf66a95 852 printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
88adc104
GKH
853 UpdateInitialGain(dev);
854 }
da45e3fe 855 } else { /* OFDM */
536d190d
AM
856 if (priv->InitialGain < 4) {
857 priv->InitialGainBackUp = priv->InitialGain;
88adc104 858
536d190d 859 priv->InitialGain++;
9cf66a95 860 printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
88adc104
GKH
861 UpdateInitialGain(dev);
862 }
863 }
864 }
865
da45e3fe 866 /* Record the related info */
88adc104
GKH
867 priv->LastRetryRate = CurrRetryRate;
868 priv->LastTxThroughput = TxThroughput;
869 priv->ieee80211->rate = priv->CurrentOperaRate * 5;
870}
0370453f 871
536d190d 872void rtl8180_rate_adapter(struct work_struct *work)
88adc104 873{
5f546031 874 struct delayed_work *dwork = to_delayed_work(work);
536d190d 875 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, rate_adapter_wq);
1748d2de 876 struct net_device *dev = ieee->dev;
1748d2de 877 StaRateAdaptive87SE(dev);
88adc104
GKH
878}
879void timer_rate_adaptive(unsigned long data)
880{
536d190d 881 struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
536d190d 882 if (!priv->up) {
88adc104
GKH
883 return;
884 }
536d190d 885 if ((priv->ieee80211->iw_mode != IW_MODE_MASTER)
88adc104 886 && (priv->ieee80211->state == IEEE80211_LINKED) &&
536d190d 887 (priv->ForcedDataRate == 0)) {
88adc104 888 queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq);
88adc104
GKH
889 }
890 priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod);
891 add_timer(&priv->rateadapter_timer);
88adc104 892}
3e837dca 893
536d190d 894void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength)
88adc104
GKH
895{
896 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
897
88adc104
GKH
898 priv->AdRxOkCnt++;
899
536d190d
AM
900 if (priv->AdRxSignalStrength != -1) {
901 priv->AdRxSignalStrength = ((priv->AdRxSignalStrength * 7) + (SignalStrength * 3)) / 10;
da45e3fe 902 } else { /* Initialization case. */
88adc104
GKH
903 priv->AdRxSignalStrength = SignalStrength;
904 }
9cf66a95 905
da45e3fe 906 if (priv->LastRxPktAntenna) /* Main antenna. */
88adc104 907 priv->AdMainAntennaRxOkCnt++;
da45e3fe 908 else /* Aux antenna. */
88adc104 909 priv->AdAuxAntennaRxOkCnt++;
88adc104 910}
3e837dca 911 /* Change Antenna Switch. */
536d190d 912bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex)
88adc104
GKH
913{
914 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
915 bool bAntennaSwitched = false;
916
536d190d 917 switch (u1bAntennaIndex) {
88adc104 918 case 0:
8daba6b9
LF
919 /* Mac register, main antenna */
920 write_nic_byte(dev, ANTSEL, 0x03);
921 /* base band */
922 write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
923 write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
88adc104 924
8daba6b9 925 bAntennaSwitched = true;
88adc104
GKH
926 break;
927
928 case 1:
8daba6b9
LF
929 /* Mac register, aux antenna */
930 write_nic_byte(dev, ANTSEL, 0x00);
931 /* base band */
932 write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
933 write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
934
935 bAntennaSwitched = true;
936
88adc104
GKH
937 break;
938
939 default:
bbc9a991 940 printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex);
88adc104
GKH
941 break;
942 }
943
9cf66a95 944 if (bAntennaSwitched)
88adc104 945 priv->CurrAntennaIndex = u1bAntennaIndex;
88adc104 946
88adc104
GKH
947 return bAntennaSwitched;
948}
3e837dca 949 /* Toggle Antenna switch. */
536d190d 950bool SwitchAntenna(struct net_device *dev)
88adc104
GKH
951{
952 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
953
954 bool bResult;
955
536d190d 956 if (priv->CurrAntennaIndex == 0) {
1748d2de 957 bResult = SetAntenna8185(dev, 1);
aada7fdd 958 } else {
1748d2de 959 bResult = SetAntenna8185(dev, 0);
88adc104
GKH
960 }
961
962 return bResult;
963}
da45e3fe 964/*
3e837dca
AM
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.
da45e3fe 968 */
536d190d 969void SwAntennaDiversity(struct net_device *dev)
88adc104
GKH
970{
971 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
536d190d 972 bool bSwCheckSS = false;
536d190d 973 if (bSwCheckSS) {
88adc104
GKH
974 priv->AdTickCount++;
975
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);
980 }
88adc104 981
da45e3fe 982 /* Case 1. No Link. */
536d190d 983 if (priv->ieee80211->state != IEEE80211_LINKED) {
88adc104 984 priv->bAdSwitchedChecking = false;
da45e3fe 985 /* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */
88adc104 986 SwitchAntenna(dev);
aada7fdd 987
da45e3fe 988 /* Case 2. Linked but no packet receive.d */
536d190d 989 } else if (priv->AdRxOkCnt == 0) {
88adc104
GKH
990 priv->bAdSwitchedChecking = false;
991 SwitchAntenna(dev);
aada7fdd 992
da45e3fe 993 /* Case 3. Evaluate last antenna switch action and undo it if necessary. */
536d190d 994 } else if (priv->bAdSwitchedChecking == true) {
88adc104
GKH
995 priv->bAdSwitchedChecking = false;
996
da45e3fe 997 /* Adjust Rx signal strength threshold. */
88adc104
GKH
998 priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2;
999
1000 priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
9cf66a95
AR
1001 priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;
1002 if (priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) {
da45e3fe 1003 /* Rx signal strength is not improved after we swtiched antenna. => Swich back. */
da45e3fe 1004 /* Increase Antenna Diversity checking period due to bad decision. */
88adc104 1005 priv->AdCheckPeriod *= 2;
da45e3fe 1006 /* Increase Antenna Diversity checking period. */
536d190d 1007 if (priv->AdCheckPeriod > priv->AdMaxCheckPeriod)
88adc104
GKH
1008 priv->AdCheckPeriod = priv->AdMaxCheckPeriod;
1009
ed2cb4f3 1010 /* Wrong decision => switch back. */
88adc104 1011 SwitchAntenna(dev);
1748d2de 1012 } else {
da45e3fe 1013 /* Rx Signal Strength is improved. */
88adc104 1014
da45e3fe 1015 /* Reset Antenna Diversity checking period to its min value. */
88adc104
GKH
1016 priv->AdCheckPeriod = priv->AdMinCheckPeriod;
1017 }
1018
88adc104 1019 }
da45e3fe
AM
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. */
3e837dca 1022 else {
88adc104
GKH
1023 priv->AdTickCount = 0;
1024
da45e3fe
AM
1025 /*
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.
1030 * 2008.01.30.
1031 */
1032
1033 /*
1034 * Evaluate RxOk count from each antenna if we shall switch default antenna now.
da45e3fe 1035 */
536d190d 1036 if ((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt)
aada7fdd 1037 && (priv->CurrAntennaIndex == 0)) {
da45e3fe 1038 /* We set Main antenna as default but RxOk count was less than Aux ones. */
88adc104 1039
da45e3fe 1040 /* Switch to Aux antenna. */
88adc104
GKH
1041 SwitchAntenna(dev);
1042 priv->bHWAdSwitched = true;
536d190d 1043 } else if ((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt)
aada7fdd 1044 && (priv->CurrAntennaIndex == 1)) {
da45e3fe 1045 /* We set Aux antenna as default but RxOk count was less than Main ones. */
88adc104 1046
da45e3fe 1047 /* Switch to Main antenna. */
88adc104
GKH
1048 SwitchAntenna(dev);
1049 priv->bHWAdSwitched = true;
aada7fdd 1050 } else {
da45e3fe 1051 /* Default antenna is better. */
88adc104 1052
da45e3fe 1053 /* Still need to check current signal strength. */
88adc104
GKH
1054 priv->bHWAdSwitched = false;
1055 }
da45e3fe
AM
1056 /*
1057 * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
ed2cb4f3 1058 * didn't change by HW evaluation.
da45e3fe
AM
1059 * 2008.02.27.
1060 *
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.
1066 */
536d190d 1067 if ((!priv->bHWAdSwitched) && (bSwCheckSS)) {
da45e3fe 1068 /* Evaluate Rx signal strength if we shall switch antenna now. */
536d190d 1069 if (priv->AdRxSignalStrength < priv->AdRxSsThreshold) {
da45e3fe 1070 /* Rx signal strength is weak => Switch Antenna. */
1748d2de
AM
1071 priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength;
1072 priv->bAdSwitchedChecking = true;
88adc104 1073
1748d2de
AM
1074 SwitchAntenna(dev);
1075 } else {
da45e3fe 1076 /* Rx signal strength is OK. */
1748d2de 1077 priv->bAdSwitchedChecking = false;
da45e3fe
AM
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. */
aada7fdd 1081
1748d2de
AM
1082 priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2;
1083 priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
9cf66a95 1084 priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;/* +by amy 080312 */
1748d2de 1085 }
88adc104 1086
da45e3fe 1087 /* Reduce Antenna Diversity checking period if possible. */
536d190d 1088 if (priv->AdCheckPeriod > priv->AdMinCheckPeriod)
1748d2de
AM
1089 priv->AdCheckPeriod /= 2;
1090 }
88adc104
GKH
1091 }
1092 }
da45e3fe 1093 /* Reset antenna diversity Rx related statistics. */
88adc104
GKH
1094 priv->AdRxOkCnt = 0;
1095 priv->AdMainAntennaRxOkCnt = 0;
1096 priv->AdAuxAntennaRxOkCnt = 0;
88adc104
GKH
1097}
1098
ed2cb4f3 1099 /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
536d190d 1100bool CheckTxPwrTracking(struct net_device *dev)
88adc104
GKH
1101{
1102 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1103
536d190d 1104 if (!priv->bTxPowerTrack)
88adc104 1105 return false;
88adc104 1106
da45e3fe 1107 /* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */
536d190d 1108 if (priv->bToUpdateTxPwr)
88adc104 1109 return false;
88adc104
GKH
1110
1111 return true;
1112}
1113
1114
3e837dca 1115 /* Timer callback function of SW Antenna Diversity. */
536d190d 1116void SwAntennaDiversityTimerCallback(struct net_device *dev)
88adc104
GKH
1117{
1118 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
c0cfe01f 1119 enum rt_rf_power_state rtState;
88adc104 1120
3e837dca 1121 /* We do NOT need to switch antenna while RF is off. */
88adc104 1122 rtState = priv->eRFPowerState;
aada7fdd 1123 do {
c0cfe01f 1124 if (rtState == RF_OFF) {
88adc104 1125 break;
c0cfe01f 1126 } else if (rtState == RF_SLEEP) {
da45e3fe 1127 /* Don't access BB/RF under Disable PLL situation. */
88adc104
GKH
1128 break;
1129 }
1130 SwAntennaDiversity(dev);
1131
536d190d 1132 } while (false);
88adc104 1133
536d190d 1134 if (priv->up) {
88adc104
GKH
1135 priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD);
1136 add_timer(&priv->SwAntennaDiversityTimer);
1137 }
88adc104
GKH
1138}
1139
This page took 0.571265 seconds and 5 git commands to generate.