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