Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
r8180_dm.c
Go to the documentation of this file.
1 #include "r8180_dm.h"
2 #include "r8180_hw.h"
3 #include "r8180_93cx6.h"
4 
5  /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */
6 #define RATE_ADAPTIVE_TIMER_PERIOD 300
7 
9 {
10  struct r8180_priv *priv = ieee80211_priv(dev);
11  struct ieee80211_device *ieee = priv->ieee80211;
12 
13  if(!priv->bRegHighPowerMechanism)
14  return false;
15 
16  if(ieee->state == IEEE80211_LINKED_SCANNING)
17  return false;
18 
19  return true;
20 }
21 
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  */
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 
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 
51  /* lzm add 080826 */
52  OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
53  CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel];
54 
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 */
58 
59  priv->bToUpdateTxPwr = true;
60  u1bTmp= read_nic_byte(dev, CCK_TXAGC);
61 
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);
66 
67  u1bTmp= read_nic_byte(dev, OFDM_TXAGC);
68  u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0; /* 8dbm */
69  write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
70  }
71 
72  } else if ((priv->UndecoratedSmoothedSS < HiPwrLowerTh) &&
73  (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) {
74  if (priv->bToUpdateTxPwr) {
75  priv->bToUpdateTxPwr = false;
76  /* SD3 required. */
77  u1bTmp= read_nic_byte(dev, CCK_TXAGC);
78  if (u1bTmp < CckTxPwrIdx) {
79  write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx);
80  }
81 
82  u1bTmp= read_nic_byte(dev, OFDM_TXAGC);
83  if (u1bTmp < OfdmTxPwrIdx) {
84  write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
85  }
86  }
87  }
88 }
89 
90 
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  */
98 {
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;
102 
103  DoTxHighPower(dev);
104 }
105 
106 
107 /*
108  * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise.
109  */
110 bool CheckDig(struct net_device *dev)
111 {
112  struct r8180_priv *priv = ieee80211_priv(dev);
113  struct ieee80211_device *ieee = priv->ieee80211;
114 
115  if (!priv->bDigMechanism)
116  return false;
117 
118  if (ieee->state != IEEE80211_LINKED)
119  return false;
120 
121  if ((priv->ieee80211->rate / 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */
122  return false;
123  return true;
124 }
125 /*
126  * Implementation of DIG for Zebra and Zebra2.
127  */
128 void DIG_Zebra(struct net_device *dev)
129 {
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;
136 
137  CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff);
138  OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff);
139  OfdmFA1 = 0x15;
140  OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8;
141 
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) */
146  }
147  /* Advised from SD3 DZ */
148  OfdmFA1 = 0x20;
149 
150 #if 1 /* lzm reserved 080826 */
151  AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec);
152  priv ->DozePeriodInPast2Sec = 0;
153 
154  if (AwakePeriodIn2Sec) {
155  OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000) ;
156  OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000) ;
157  } else {
158  ;
159  }
160 #endif
161 
162  InitialGainStep = 8;
163  LowestGainStage = priv->RegBModeGainStage; /* Lowest gain stage. */
164 
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;
172 
173  priv->InitialGain = (priv->InitialGain + 1);
174  UpdateInitialGain(dev);
175  }
176  priv->DIG_NumberFallbackVote = 0;
177  priv->DIG_NumberUpgradeVote = 0;
178  }
179  } else {
180  if (priv->DIG_NumberFallbackVote)
181  priv->DIG_NumberFallbackVote--;
182  }
183  priv->DIG_NumberUpgradeVote = 0;
184  } else {
185  if (priv->DIG_NumberFallbackVote)
186  priv->DIG_NumberFallbackVote--;
187  priv->DIG_NumberUpgradeVote++;
188 
189  if (priv->DIG_NumberUpgradeVote > 9) {
190  if (priv->InitialGain > LowestGainStage) { /* In 87B, m78dBm means State 4 (m864dBm) */
191  priv->InitialGainBackUp = priv->InitialGain;
192 
193  priv->InitialGain = (priv->InitialGain - 1);
194  UpdateInitialGain(dev);
195  }
196  priv->DIG_NumberFallbackVote = 0;
197  priv->DIG_NumberUpgradeVote = 0;
198  }
199  }
200 }
201 
202 /*
203  * Dispatch DIG implementation according to RF.
204  */
206 {
207  DIG_Zebra(dev);
208 }
209 
211 {
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);
216 
217  /* Read CCK and OFDM False Alarm. */
219 
220 
221  /* Adjust Initial Gain dynamically. */
222  DynamicInitGain(dev);
223 
224 }
225 
227 {
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;
237  for (idx=0; idx < rate_len; idx++) {
238  if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) {
239  Found = 1;
240  goto found_rate;
241  }
242  }
243  for (idx = 0; idx < rate_ex_len; idx++) {
244  if ((priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate) {
245  Found = 1;
246  goto found_rate;
247  }
248  }
249  return Found;
250  found_rate:
251  return Found;
252 }
253 
254 /*
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.
257  */
259 {
260  struct r8180_priv *priv = ieee80211_priv(dev);
261  u8 UpRate;
262 
263  /* Upgrade 1 degree. */
264  switch (rate) {
265  case 108: /* Up to 54Mbps. */
266  UpRate = 108;
267  break;
268 
269  case 96: /* Up to 54Mbps. */
270  UpRate = 108;
271  break;
272 
273  case 72: /* Up to 48Mbps. */
274  UpRate = 96;
275  break;
276 
277  case 48: /* Up to 36Mbps. */
278  UpRate = 72;
279  break;
280 
281  case 36: /* Up to 24Mbps. */
282  UpRate = 48;
283  break;
284 
285  case 22: /* Up to 18Mbps. */
286  UpRate = 36;
287  break;
288 
289  case 11: /* Up to 11Mbps. */
290  UpRate = 22;
291  break;
292 
293  case 4: /* Up to 5.5Mbps. */
294  UpRate = 11;
295  break;
296 
297  case 2: /* Up to 2Mbps. */
298  UpRate = 4;
299  break;
300 
301  default:
302  printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
303  return rate;
304  }
305  /* Check if the rate is valid. */
306  if (IncludedInSupportedRates(priv, UpRate)) {
307  return UpRate;
308  } else {
309  return rate;
310  }
311  return rate;
312 }
313 /*
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.
316  */
317 
319 {
320  struct r8180_priv *priv = ieee80211_priv(dev);
321  u8 DownRate;
322 
323  /* Upgrade 1 degree. */
324  switch (rate) {
325  case 108: /* Down to 48Mbps. */
326  DownRate = 96;
327  break;
328 
329  case 96: /* Down to 36Mbps. */
330  DownRate = 72;
331  break;
332 
333  case 72: /* Down to 24Mbps. */
334  DownRate = 48;
335  break;
336 
337  case 48: /* Down to 18Mbps. */
338  DownRate = 36;
339  break;
340 
341  case 36: /* Down to 11Mbps. */
342  DownRate = 22;
343  break;
344 
345  case 22: /* Down to 5.5Mbps. */
346  DownRate = 11;
347  break;
348 
349  case 11: /* Down to 2Mbps. */
350  DownRate = 4;
351  break;
352 
353  case 4: /* Down to 1Mbps. */
354  DownRate = 2;
355  break;
356 
357  case 2: /* Down to 1Mbps. */
358  DownRate = 2;
359  break;
360 
361  default:
362  printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate);
363  return rate;
364  }
365  /* Check if the rate is valid. */
366  if (IncludedInSupportedRates(priv, DownRate)) {
367  return DownRate;
368  } else {
369  return rate;
370  }
371  return rate;
372 }
373 /*
374  * Helper function to determine if specified data rate is
375  * CCK rate.
376  */
377 
379 {
380  bool bReturn = false;
381 
382  if ((rate <= 22) && (rate != 12) && (rate != 18)) {
383  bReturn = true;
384  }
385 
386  return bReturn;
387 }
388 /*
389  * Description:
390  * Tx Power tracking mechanism routine on 87SE.
391  */
393 {
394  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
395  u8 tmpu1Byte, CurrentThermal, Idx;
396  char CckTxPwrIdx, OfdmTxPwrIdx;
397 
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 */
401 
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];
407 
408  if (CurrentThermal > priv->ThermalMeter) {
409  /* higher thermal meter. */
410  CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
411  OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2;
412 
413  if (CckTxPwrIdx > 35)
414  CckTxPwrIdx = 35; /* Force TxPower to maximal index. */
415  if (OfdmTxPwrIdx > 35)
416  OfdmTxPwrIdx = 35;
417  } else {
418  /* lower thermal meter. */
419  CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
420  OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2;
421 
422  if (CckTxPwrIdx < 0)
423  CckTxPwrIdx = 0;
424  if (OfdmTxPwrIdx < 0)
425  OfdmTxPwrIdx = 0;
426  }
427 
428  /* Update TxPower level on CCK and OFDM resp. */
429  priv->chtxpwr[Idx] = CckTxPwrIdx;
430  priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx;
431  }
432 
433  /* Update TxPower level immediately. */
434  rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel);
435  }
436  priv->ThermalMeter = CurrentThermal;
437 }
439 {
440  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
441  unsigned long CurrTxokCnt;
444  unsigned long CurrRxokCnt;
445  bool bTryUp = false;
446  bool bTryDown = false;
447  u8 TryUpTh = 1;
448  u8 TryDownTh = 2;
449  u32 TxThroughput;
450  long CurrSignalStrength;
451  bool bUpdateInitialGain = false;
452  u8 u1bOfdm = 0, u1bCck = 0;
453  char OfdmTxPwrIdx, CckTxPwrIdx;
454 
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;
464  priv->CurrentOperaRate = priv->ieee80211->rate / 5;
465  /* 2 Compute retry ratio. */
466  if (CurrTxokCnt > 0) {
467  CurrRetryRate = (u16)(CurrRetryCnt * 100 / CurrTxokCnt);
468  } else {
469  /* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */
470  CurrRetryRate = (u16)(CurrRetryCnt * 100 / 1);
471  }
472 
473  priv->LastRetryCnt = priv->CurrRetryCnt;
474  priv->LastTxokCnt = priv->NumTxOkTotal;
475  priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal;
476  priv->CurrRetryCnt = 0;
477 
478  /* 2No Tx packets, return to init_rate or not? */
479  if (CurrRetryRate == 0 && CurrTxokCnt == 0) {
480  /*
481  * After 9 (30*300ms) seconds in this condition, we try to raise rate.
482  */
483  priv->TryupingCountNoData++;
484 
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;
489  /* Reset Fail Record */
490  priv->LastFailTxRate = 0;
491  priv->LastFailTxRateSS = -200;
492  priv->FailTxRateCount = 0;
493  }
494  goto SetInitialGain;
495  } else {
496  priv->TryupingCountNoData = 0; /*Reset trying up times. */
497  }
498 
499 
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).
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.
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.
512  *
513  */
514 
515  /*
516  * 11Mbps or 36Mbps
517  * Check more times in these rate(key rates).
518  */
519  if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72)
520  TryUpTh += 9;
521  /*
522  * Let these rates down more difficult.
523  */
524  if (MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36)
525  TryDownTh += 1;
526 
527  /* 1 Adjust Rate. */
528  if (priv->bTryuping == true) {
529  /* 2 For Test Upgrading mechanism
530  * Note:
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.
534  */
535 
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. */
539  bTryDown = true;
540  } else {
541  priv->bTryuping = false;
542  }
543  } else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) {
544  /*
545  * 2For High Power
546  *
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. */
552  if (priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate) {
553  bTryUp = true;
554  /* Upgrade Tx Rate directly. */
555  priv->TryupingCount += TryUpTh;
556  }
557 
558  } else if (CurrTxokCnt > 9 && CurrTxokCnt < 100 && CurrRetryRate >= 600) {
559  /*
560  *2 For Serious Retry
561  *
562  * Traffic is not busy but our Tx retry is serious.
563  */
564  bTryDown = true;
565  /* Let Rate Mechanism to degrade tx rate directly. */
566  priv->TryDownCountLowData += TryDownTh;
567  } else if (priv->CurrentOperaRate == 108) {
568  /* 2For 54Mbps */
569  /* Air Link */
570  if ((CurrRetryRate > 26) && (priv->LastRetryRate > 25)) {
571  bTryDown = true;
572  }
573  /* Cable Link */
574  else if ((CurrRetryRate > 17) && (priv->LastRetryRate > 16) && (CurrSignalStrength > -72)) {
575  bTryDown = true;
576  }
577 
578  if (bTryDown && (CurrSignalStrength < -75)) /* cable link */
579  priv->TryDownCountLowData += TryDownTh;
580  }
581  else if (priv->CurrentOperaRate == 96) {
582  /* 2For 48Mbps */
583  /* Air Link */
584  if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) {
585  bTryDown = true;
586  } else if (((CurrRetryRate > 21) && (priv->LastRetryRate > 20)) && (CurrSignalStrength > -74)) { /* Cable Link */
587  /* Down to rate 36Mbps. */
588  bTryDown = true;
589  } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
590  bTryDown = true;
591  priv->TryDownCountLowData += TryDownTh;
592  } else if ((CurrRetryRate < 8) && (priv->LastRetryRate < 8)) { /* TO DO: need to consider (RSSI) */
593  bTryUp = true;
594  }
595 
596  if (bTryDown && (CurrSignalStrength < -75)){
597  priv->TryDownCountLowData += TryDownTh;
598  }
599  } else if (priv->CurrentOperaRate == 72) {
600  /* 2For 36Mbps */
601  if ((CurrRetryRate > 43) && (priv->LastRetryRate > 41)) {
602  /* Down to rate 24Mbps. */
603  bTryDown = true;
604  } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
605  bTryDown = true;
606  priv->TryDownCountLowData += TryDownTh;
607  } else if ((CurrRetryRate < 15) && (priv->LastRetryRate < 16)) { /* TO DO: need to consider (RSSI) */
608  bTryUp = true;
609  }
610 
611  if (bTryDown && (CurrSignalStrength < -80))
612  priv->TryDownCountLowData += TryDownTh;
613 
614  } else if (priv->CurrentOperaRate == 48) {
615  /* 2For 24Mbps */
616  /* Air Link */
617  if (((CurrRetryRate > 63) && (priv->LastRetryRate > 62))) {
618  bTryDown = true;
619  } else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */
620  bTryDown = true;
621  } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2 )) {
622  bTryDown = true;
623  priv->TryDownCountLowData += TryDownTh;
624  } else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */
625  bTryUp = true;
626  }
627 
628  if (bTryDown && (CurrSignalStrength < -82))
629  priv->TryDownCountLowData += TryDownTh;
630 
631  } else if (priv->CurrentOperaRate == 36) {
632  if (((CurrRetryRate > 85) && (priv->LastRetryRate > 86))) {
633  bTryDown = true;
634  } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
635  bTryDown = true;
636  priv->TryDownCountLowData += TryDownTh;
637  } else if ((CurrRetryRate < 22) && (priv->LastRetryRate < 23)) { /* TO DO: need to consider (RSSI) */
638  bTryUp = true;
639  }
640  } else if (priv->CurrentOperaRate == 22) {
641  /* 2For 11Mbps */
642  if (CurrRetryRate > 95) {
643  bTryDown = true;
644  }
645  else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */
646  bTryUp = true;
647  }
648  } else if (priv->CurrentOperaRate == 11) {
649  /* 2For 5.5Mbps */
650  if (CurrRetryRate > 149) {
651  bTryDown = true;
652  } else if ((CurrRetryRate < 60) && (priv->LastRetryRate < 65)) {
653  bTryUp = true;
654  }
655  } else if (priv->CurrentOperaRate == 4) {
656  /* 2For 2 Mbps */
657  if ((CurrRetryRate > 99) && (priv->LastRetryRate > 99)) {
658  bTryDown = true;
659  } else if ((CurrRetryRate < 65) && (priv->LastRetryRate < 70)) {
660  bTryUp = true;
661  }
662  } else if (priv->CurrentOperaRate == 2) {
663  /* 2For 1 Mbps */
664  if ((CurrRetryRate < 70) && (priv->LastRetryRate < 75)) {
665  bTryUp = true;
666  }
667  }
668 
669  if (bTryUp && bTryDown)
670  printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
671 
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.
675  */
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) {
679  bTryUp = true;
680  priv->bTryuping = true;
681  }
682  }
683 
684  /* 1 Rate Mechanism */
685  if (bTryUp) {
686  priv->TryupingCount++;
687  priv->TryDownCountLowData = 0;
688 
689  /*
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.
694  */
695 
696  if ((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) ||
697  (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) {
698  priv->TryupingCount = 0;
699  /*
700  * When transferring from CCK to OFDM, DIG is an important issue.
701  */
702  if (priv->CurrentOperaRate == 22)
703  bUpdateInitialGain = true;
704 
705  /*
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.
708  */
709  if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) &&
710  (priv->FailTxRateCount > 2))
712 
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. */
715 
717 
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. */
724  }
725 
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. */
731  }
732  }
733  } else {
734  if (priv->TryupingCount > 0)
735  priv->TryupingCount --;
736  }
737 
738  if (bTryDown) {
739  priv->TryDownCountLowData++;
740  priv->TryupingCount = 0;
741 
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;
752  } else {
753  priv->LastFailTxRate = priv->CurrentOperaRate;
754  priv->FailTxRateCount = 1;
755  priv->LastFailTxRateSS = CurrSignalStrength;
756  }
758 
759  /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
760  if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72 )) {
761  priv->CurrentOperaRate = 72;
762  }
763 
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. */
770  }
771 
772  /*
773  * When it is CCK rate, it may need to update initial gain to receive lower power packets.
774  */
775  if (MgntIsCckRate(priv->CurrentOperaRate)) {
776  bUpdateInitialGain = true;
777  }
778  }
779  } else {
780  if (priv->TryDownCountLowData > 0)
781  priv->TryDownCountLowData--;
782  }
783 
784  /*
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.
787  */
788  if (priv->FailTxRateCount >= 0x15 ||
789  (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) {
790  priv->FailTxRateCount--;
791  }
792 
793 
794  OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel];
795  CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel];
796 
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);
801 
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);
808  }
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);
815  }
816  }
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);
820 
821  /* case 1: Never enter High power */
822  if (u1bCck == CckTxPwrIdx) {
823  priv->bEnhanceTxPwr = false;
824  write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
825  }
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);
831  }
832  }
833 
834  /*
835  * We need update initial gain when we set tx rate "from OFDM to CCK" or
836  * "from CCK to OFDM".
837  */
838 SetInitialGain:
839  if (bUpdateInitialGain) {
840  if (MgntIsCckRate(priv->CurrentOperaRate)) { /* CCK */
841  if (priv->InitialGain > priv->RegBModeGainStage) {
842  priv->InitialGainBackUp = priv->InitialGain;
843 
844  if (CurrSignalStrength < -85) /* Low power, OFDM [0x17] = 26. */
845  /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */
846  priv->InitialGain = priv->RegBModeGainStage;
847 
848  else if (priv->InitialGain > priv->RegBModeGainStage + 1)
849  priv->InitialGain -= 2;
850 
851  else
852  priv->InitialGain--;
853 
854  printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate);
855  UpdateInitialGain(dev);
856  }
857  } else { /* OFDM */
858  if (priv->InitialGain < 4) {
859  priv->InitialGainBackUp = priv->InitialGain;
860 
861  priv->InitialGain++;
862  printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate);
863  UpdateInitialGain(dev);
864  }
865  }
866  }
867 
868  /* Record the related info */
870  priv->LastTxThroughput = TxThroughput;
871  priv->ieee80211->rate = priv->CurrentOperaRate * 5;
872 }
873 
875 {
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);
880 }
881 void timer_rate_adaptive(unsigned long data)
882 {
883  struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
884  if (!priv->up) {
885  return;
886  }
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);
891  }
892  priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod);
894 }
895 
897 {
898  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
899 
900  priv->AdRxOkCnt++;
901 
902  if (priv->AdRxSignalStrength != -1) {
903  priv->AdRxSignalStrength = ((priv->AdRxSignalStrength * 7) + (SignalStrength * 3)) / 10;
904  } else { /* Initialization case. */
906  }
907 
908  if (priv->LastRxPktAntenna) /* Main antenna. */
909  priv->AdMainAntennaRxOkCnt++;
910  else /* Aux antenna. */
911  priv->AdAuxAntennaRxOkCnt++;
912 }
913  /* Change Antenna Switch. */
914 bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex)
915 {
916  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
917  bool bAntennaSwitched = false;
918 
919  switch (u1bAntennaIndex) {
920  case 0:
921  /* Mac register, main antenna */
922  write_nic_byte(dev, ANTSEL, 0x03);
923  /* base band */
924  write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
925  write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
926 
927  bAntennaSwitched = true;
928  break;
929 
930  case 1:
931  /* Mac register, aux antenna */
932  write_nic_byte(dev, ANTSEL, 0x00);
933  /* base band */
934  write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
935  write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
936 
937  bAntennaSwitched = true;
938 
939  break;
940 
941  default:
942  printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex);
943  break;
944  }
945 
946  if(bAntennaSwitched)
947  priv->CurrAntennaIndex = u1bAntennaIndex;
948 
949  return bAntennaSwitched;
950 }
951  /* Toggle Antenna switch. */
953 {
954  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
955 
956  bool bResult;
957 
958  if (priv->CurrAntennaIndex == 0) {
959  bResult = SetAntenna8185(dev, 1);
960  } else {
961  bResult = SetAntenna8185(dev, 0);
962  }
963 
964  return bResult;
965 }
966 /*
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.
970  */
972 {
973  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
974  bool bSwCheckSS = false;
975  if (bSwCheckSS) {
976  priv->AdTickCount++;
977 
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);
982  }
983 
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.. */
988  SwitchAntenna(dev);
989 
990  /* Case 2. Linked but no packet receive.d */
991  } else if (priv->AdRxOkCnt == 0) {
992  priv->bAdSwitchedChecking = false;
993  SwitchAntenna(dev);
994 
995  /* Case 3. Evaluate last antenna switch action and undo it if necessary. */
996  } else if (priv->bAdSwitchedChecking == true) {
997  priv->bAdSwitchedChecking = false;
998 
999  /* Adjust Rx signal strength threshold. */
1000  priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2;
1001 
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;
1011 
1012  /* Wrong decision => switch back. */
1013  SwitchAntenna(dev);
1014  } else {
1015  /* Rx Signal Strength is improved. */
1016 
1017  /* Reset Antenna Diversity checking period to its min value. */
1018  priv->AdCheckPeriod = priv->AdMinCheckPeriod;
1019  }
1020 
1021  }
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. */
1024  else {
1025  priv->AdTickCount = 0;
1026 
1027  /*
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.
1032  * 2008.01.30.
1033  */
1034 
1035  /*
1036  * Evaluate RxOk count from each antenna if we shall switch default antenna now.
1037  */
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. */
1041 
1042  /* Switch to Aux antenna. */
1043  SwitchAntenna(dev);
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. */
1048 
1049  /* Switch to Main antenna. */
1050  SwitchAntenna(dev);
1051  priv->bHWAdSwitched = true;
1052  } else {
1053  /* Default antenna is better. */
1054 
1055  /* Still need to check current signal strength. */
1056  priv->bHWAdSwitched = false;
1057  }
1058  /*
1059  * <Roger_Notes> We evaluate Rx signal strength ONLY when default antenna
1060  * didn't change by HW evaluation.
1061  * 2008.02.27.
1062  *
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.
1068  */
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. */
1074  priv->bAdSwitchedChecking = true;
1075 
1076  SwitchAntenna(dev);
1077  } else {
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. */
1083 
1084  priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2;
1085  priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
1086  priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;/* +by amy 080312 */
1087  }
1088 
1089  /* Reduce Antenna Diversity checking period if possible. */
1090  if (priv->AdCheckPeriod > priv->AdMinCheckPeriod)
1091  priv->AdCheckPeriod /= 2;
1092  }
1093  }
1094  }
1095  /* Reset antenna diversity Rx related statistics. */
1096  priv->AdRxOkCnt = 0;
1097  priv->AdMainAntennaRxOkCnt = 0;
1098  priv->AdAuxAntennaRxOkCnt = 0;
1099 }
1100 
1101  /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */
1103 {
1104  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1105 
1106  if (!priv->bTxPowerTrack)
1107  return false;
1108 
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)
1111  return false;
1112 
1113  return true;
1114 }
1115 
1116 
1117  /* Timer callback function of SW Antenna Diversity. */
1119 {
1120  struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1121  RT_RF_POWER_STATE rtState;
1122 
1123  /* We do NOT need to switch antenna while RF is off. */
1124  rtState = priv->eRFPowerState;
1125  do {
1126  if (rtState == eRfOff) {
1127  break;
1128  } else if (rtState == eRfSleep) {
1129  /* Don't access BB/RF under Disable PLL situation. */
1130  break;
1131  }
1132  SwAntennaDiversity(dev);
1133 
1134  } while (false);
1135 
1136  if (priv->up) {
1139  }
1140 }
1141