1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include "cprecomp.h"
18#include "ratectrl.h"
19
20const u32_t zcRateToPhyCtrl[] =
21 {
22
23 0x00000, 0x10000, 0x20000, 0x30000,
24
25 0xb0001, 0xf0001, 0xa0001, 0xe0001,
26
27 0x90001, 0xd0001, 0x80001, 0xc0001,
28
29 0x00002, 0x10002, 0x20002, 0x30002,
30
31 0x40002, 0x50002, 0x60002, 0x70002,
32
33 0x80002, 0x90002, 0xa0002, 0xb0002,
34
35 0xc0002, 0xd0002, 0xe0002, 0xf0002,
36
37 0x800e0002, 0x800f0002, 0x80070002
38 };
39
40
41const u8_t zcHtRateTable[15][4] =
42 {
43 { 4, 4, 0, 0},
44 { 5, 5, 1, 1},
45 { 13, 12, 2, 2},
46 { 14, 13, 3, 3},
47 { 15, 14, 13, 12},
48 { 16, 15, 14, 13},
49 { 23, 16, 15, 14},
50 { 24, 23, 16, 15},
51 { 25, 24, 23, 16},
52 { 26, 25, 24, 23},
53 { 27, 26, 25, 24},
54 { 0, 27, 26, 25},
55 { 0, 29, 27, 26},
56 { 0, 0, 0, 28},
57 { 0, 0, 0, 29}
58 };
59
60const u8_t zcHtOneTxStreamRateTable[15][4] =
61 {
62 { 4, 4, 0, 0},
63 { 5, 5, 1, 1},
64 { 13, 12, 2, 2},
65 { 14, 13, 3, 3},
66 { 15, 14, 13, 12},
67 { 16, 15, 14, 13},
68 { 17, 16, 15, 14},
69 { 18, 17, 16, 15},
70 { 19, 18, 17, 16},
71 { 0, 19, 18, 17},
72 { 0, 30, 19, 18},
73 { 0, 0, 0, 19},
74 { 0, 0, 0, 30},
75 { 0, 0, 0, 0 },
76 { 0, 0, 0, 0 }
77 };
78
79const u16_t zcRate[] =
80 {
81 1, 2, 5, 11,
82 6, 9, 12, 18,
83 24, 36, 48, 54,
84 13, 27, 40, 54,
85 81, 108, 121, 135,
86 27, 54, 81, 108,
87 162, 216, 243, 270,
88 270, 300, 150
89 };
90
91const u16_t PERThreshold[] =
92 {
93 100, 50, 50, 50,
94 50, 50, 30, 30,
95 25, 25, 25, 20,
96 50, 50, 50, 40,
97 30, 30, 30, 30,
98 30, 30, 25, 25,
99 25, 25, 15, 15,
100 15, 15, 10
101 };
102
103const u16_t FailDiff[] =
104 {
105 40, 46, 40, 0,
106 24, 17, 22, 16,
107 19, 13, 5, 0,
108 36, 22, 15, 19,
109 12, 5, 4, 7,
110 0, 0, 0, 0,
111 9, 4, 3, 3,
112 3, 0, 0
113 };
114
115
116#ifdef ZM_ENABLE_BA_RATECTRL
117u32_t TxMPDU[29];
118u32_t BAFail[29];
119u32_t BAPER[29];
120const u16_t BADiff[] =
121 {
122 0, 0, 0, 0,
123 0, 0, 0, 0,
124 0, 0, 0, 0,
125 361, 220, 151, 187,
126 122, 48, 41, 65,
127 0, 0, 0, 0,
128 88, 33, 27, 25,
129 0
130 };
131#endif
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150void zfRateCtrlInitCell(zdev_t* dev, struct zsRcCell* rcCell, u8_t type,
151 u8_t gBand, u8_t SG40)
152{
153 u8_t i;
154 u8_t maxrate;
155 zmw_get_wlan_dev(dev);
156
157 if (SG40) SG40 = 1;
158
159 if (gBand != 0)
160 {
161 if (type == 1)
162 {
163 for (i=0; i<4; i++)
164 {
165 rcCell->operationRateSet[i] = (u8_t)i;
166 }
167 for (i=4; i<10; i++)
168 {
169 rcCell->operationRateSet[i] = 2+i;
170 }
171 rcCell->operationRateCount = 10;
172 rcCell->currentRateIndex = 5;
173 }
174 else if (type == 2)
175 {
176 if (wd->wlanMode == ZM_MODE_AP)
177 {
178 for (i=0; i<15; i++)
179 {
180 rcCell->operationRateSet[i] = zcHtRateTable[i][3];
181 }
182 if(!SG40) rcCell->operationRateSet[13] = 27;
183 rcCell->operationRateCount = 14+SG40;
184 rcCell->currentRateIndex = 10;
185 }
186 else
187 {
188 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
189 {
190 for (i=0; i<15; i++)
191 {
192 rcCell->operationRateSet[i] = zcHtRateTable[i][3];
193 }
194 if(!SG40) rcCell->operationRateSet[13] = 27;
195 rcCell->operationRateCount = 14+SG40;
196 rcCell->currentRateIndex = 10;
197 }
198 else
199 {
200 for (i=0; i<13; i++)
201 {
202 rcCell->operationRateSet[i] = zcHtRateTable[i][2];
203 }
204 rcCell->operationRateCount = 13;
205 rcCell->currentRateIndex = 9;
206 }
207 }
208 }
209 else if (type == 3)
210 {
211 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
212 {
213 if(SG40 != 0)
214 {
215 maxrate = 13;
216 }
217 else
218 {
219 maxrate = 12;
220 }
221 for (i=0; i<maxrate; i++)
222 {
223 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][3];
224 }
225 rcCell->operationRateCount = i;
226 rcCell->currentRateIndex = ((i+1)*3)/4;
227 }
228 else
229 {
230 for (i=0; i<11; i++)
231 {
232 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][2];
233 }
234 rcCell->operationRateCount = i;
235 rcCell->currentRateIndex = ((i+1)*3)/4;
236 }
237 }
238 else
239 {
240 for (i=0; i<4; i++)
241 {
242 rcCell->operationRateSet[i] = (u8_t)i;
243 }
244 rcCell->operationRateCount = 4;
245 rcCell->currentRateIndex = rcCell->operationRateCount-1;
246 }
247 }
248 else
249 {
250 if (type == 2)
251 {
252 if (wd->wlanMode == ZM_MODE_AP)
253 {
254 for (i=0; i<(12+SG40); i++)
255 {
256 rcCell->operationRateSet[i] = zcHtRateTable[i][1];
257 }
258 rcCell->operationRateCount = 12+SG40;
259 rcCell->currentRateIndex = 8;
260 }
261 else
262 {
263 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
264 {
265 for (i=0; i<(12+SG40); i++)
266 {
267 rcCell->operationRateSet[i] = zcHtRateTable[i][1];
268 }
269 rcCell->operationRateCount = 12+SG40;
270 rcCell->currentRateIndex = 8;
271 }
272 else
273 {
274 for (i=0; i<11; i++)
275 {
276 rcCell->operationRateSet[i] = zcHtRateTable[i][0];
277 }
278 rcCell->operationRateCount = 11;
279 rcCell->currentRateIndex = 7;
280 }
281 }
282 }
283 else if (type == 3)
284 {
285 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
286 {
287 if(SG40 != 0)
288 {
289 maxrate = 11;
290 }
291 else
292 {
293 maxrate = 10;
294 }
295 for (i=0; i<maxrate; i++)
296 {
297 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][1];
298 }
299 rcCell->operationRateCount = i;
300 rcCell->currentRateIndex = ((i+1)*3)/4;
301 }
302 else
303 {
304 for (i=0; i<9; i++)
305 {
306 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][0];
307 }
308 rcCell->operationRateCount = i;
309 rcCell->currentRateIndex = ((i+1)*3)/4;
310 }
311 }
312 else
313 {
314 for (i=0; i<8; i++)
315 {
316 rcCell->operationRateSet[i] = i+4;
317 }
318 rcCell->operationRateCount = 8;
319 rcCell->currentRateIndex = 4;
320 }
321 }
322
323 rcCell->flag = 0;
324 rcCell->txCount = 0;
325 rcCell->failCount = 0;
326 rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
327 rcCell->lasttxCount = 0;
328 rcCell->lastTime = wd->tick;
329 rcCell->probingTime = wd->tick;
330 for (i=0; i<ZM_RATE_TABLE_SIZE; i++) {
331 wd->PER[i] = 0;
332 wd->txMPDU[i] = wd->txFail[i] = 0;
333 }
334 wd->probeCount = 0;
335 wd->probeInterval = 0;
336#ifdef ZM_ENABLE_BA_RATECTRL
337 for (i=0; i<29; i++) {
338 TxMPDU[i]=0;
339 BAFail[i]=0;
340 BAPER[i]=0;
341 }
342#endif
343 return;
344}
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362u8_t zfRateCtrlGetHigherRate(struct zsRcCell* rcCell)
363{
364 u8_t rateIndex;
365
366 rateIndex = rcCell->currentRateIndex
367 + (((rcCell->currentRateIndex+1) < rcCell->operationRateCount)?1:0);
368 return rcCell->operationRateSet[rateIndex];
369}
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387u8_t zfRateCtrlNextLowerRate(zdev_t* dev, struct zsRcCell* rcCell)
388{
389 zmw_get_wlan_dev(dev);
390 if (rcCell->currentRateIndex > 0)
391 {
392 rcCell->currentRateIndex--;
393 rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
394 }
395 zm_msg1_tx(ZM_LV_0, "Lower Tx Rate=", rcCell->currentRate);
396
397 rcCell->failCount = rcCell->txCount = 0;
398 rcCell->lasttxCount = 0;
399 rcCell->lastTime = wd->tick;
400 return rcCell->currentRate;
401}
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420u8_t zfRateCtrlRateDiff(struct zsRcCell* rcCell, u8_t retryRate)
421{
422 u16_t i;
423
424
425 for (i=0; i<rcCell->operationRateCount; i++)
426 {
427 if (retryRate == rcCell->operationRateSet[i])
428 {
429 if (i < rcCell->currentRateIndex)
430 {
431 return ((rcCell->currentRateIndex - i)+1)>>1;
432 }
433 else if (i == rcCell->currentRateIndex == 0)
434 {
435 return 1;
436 }
437 else
438 {
439 return 0;
440 }
441 }
442 }
443
444 zm_msg1_tx(ZM_LV_0, "Not in operation rate set:", retryRate);
445 return 1;
446
447}
448
449u32_t zfRateCtrlUDPTP(zdev_t* dev, u16_t Rate, u32_t PER) {
450 if ((PER < 100) && (Rate > 0) && PER)
451 return 1168000/(((12304/Rate)+197)*(100+100*PER/(100-PER)));
452 else
453 return 0;
454}
455
456u8_t zfRateCtrlFindMaxUDPTP(zdev_t* dev, struct zsRcCell* rcCell) {
457 u8_t i, maxIndex=0, rateIndex;
458 u32_t max=0, UDPThroughput;
459
460 zmw_get_wlan_dev(dev);
461
462 rateIndex = zm_agg_min(rcCell->currentRateIndex+3, rcCell->operationRateCount-1);
463 for (i=rcCell->currentRateIndex; i < rateIndex; i++) {
464 UDPThroughput = zfRateCtrlUDPTP(dev, zcRate[rcCell->operationRateSet[i]],
465 wd->PER[rcCell->operationRateSet[i]]);
466 if (max < UDPThroughput) {
467 max = UDPThroughput;
468 maxIndex = i;
469 }
470 }
471
472 return rcCell->operationRateSet[maxIndex];
473}
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491u16_t zfRateCtrlGetTxRate(zdev_t* dev, struct zsRcCell* rcCell, u16_t* probing)
492{
493 u8_t newRate, highRate;
494 zmw_get_wlan_dev(dev);
495
496 zm_msg1_tx(ZM_LV_3, "txCount=", rcCell->txCount);
497 zm_msg1_tx(ZM_LV_3, "probingTime=", rcCell->probingTime);
498 zm_msg1_tx(ZM_LV_3, "tick=", wd->tick);
499 *probing = 0;
500 newRate = rcCell->currentRate;
501
502 if (wd->probeCount && (wd->probeCount < wd->success_probing))
503 {
504 if (wd->probeInterval < 50)
505 {
506 wd->probeInterval++;
507 }
508 else
509 {
510 wd->probeInterval++;
511 if (wd->probeInterval > 52)
512 {
513 wd->probeInterval = 0;
514 }
515 newRate=zfRateCtrlGetHigherRate(rcCell);
516 *probing = 1;
517 wd->probeCount++;
518 rcCell->probingTime = wd->tick;
519 }
520 }
521
522 else if ((((wd->tick - rcCell->probingTime) > (ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK))
523 && (rcCell->txCount >= ZM_RATE_CTRL_MIN_PROBING_PACKET))
524 || (rcCell->txCount >= 1000))
525 {
526#ifndef ZM_DISABLE_RATE_CTRL
527
528 wd->probeCount = 0;
529 wd->probeSuccessCount = 0;
530 if (wd->txMPDU[rcCell->currentRate] != 0) {
531 wd->PER[rcCell->currentRate] = zm_agg_min(100,
532 (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
533 if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
534 }
535
536
537 if ((wd->PER[rcCell->currentRate] <= (ZM_RATE_PROBING_THRESHOLD+15)) ||
538 ((rcCell->currentRate <= 16) &&
539 ((wd->PER[rcCell->currentRate]/2) <= ZM_RATE_PROBING_THRESHOLD)))
540 {
541 if ((newRate=zfRateCtrlGetHigherRate(rcCell)) != rcCell->currentRate)
542 {
543 *probing = 1;
544 wd->probeCount++;
545 wd->probeInterval = 0;
546 wd->success_probing =
547 (rcCell->currentRate <= 16)? (ZM_RATE_SUCCESS_PROBING/2) : ZM_RATE_SUCCESS_PROBING;
548
549 zm_msg1_tx(ZM_LV_0, "Probing Rate=", newRate);
550 }
551 }
552#endif
553
554 zm_msg0_tx(ZM_LV_1, "Diminish counter");
555 rcCell->failCount = rcCell->failCount>>1;
556 rcCell->txCount = rcCell->txCount>>1;
557 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
558 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
559
560
561 if (rcCell->currentRate > 15) {
562 highRate = zfRateCtrlGetHigherRate(rcCell);
563 if ((highRate != rcCell->currentRate) && wd->PER[highRate] &&
564 ((wd->PER[rcCell->currentRate] + FailDiff[rcCell->currentRate]) >
565 wd->PER[highRate])) {
566
567 wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
568 zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
569 }
570 }
571 else {
572 highRate = zfRateCtrlFindMaxUDPTP(dev, rcCell);
573 if (rcCell->currentRate < highRate) {
574
575 wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
576 zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
577 }
578 }
579 rcCell->probingTime = wd->tick;
580 }
581
582 if( (wd->tick > 1000)
583 && ((wd->tick - rcCell->lastTime) > 3840) )
584 {
585 if (rcCell->lasttxCount < 70)
586 {
587 rcCell->failCount = rcCell->failCount>>1;
588 rcCell->txCount = rcCell->txCount>>1;
589 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
590 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
591
592 rcCell->failCount = (rcCell->failCount < rcCell->txCount)?
593 rcCell->failCount : rcCell->txCount;
594 wd->txFail[rcCell->currentRate] = (wd->txFail[rcCell->currentRate] < wd->txMPDU[rcCell->currentRate])?
595 wd->txFail[rcCell->currentRate] : wd->txMPDU[rcCell->currentRate];
596 }
597
598 rcCell->lastTime = wd->tick;
599 rcCell->lasttxCount = 0;
600 }
601
602 rcCell->txCount++;
603 rcCell->lasttxCount++;
604 wd->txMPDU[rcCell->currentRate]++;
605 zm_msg1_tx(ZM_LV_1, "Get Tx Rate=", newRate);
606 return newRate;
607}
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627void zfRateCtrlTxFailEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t aggRate, u32_t retryRate)
628{
629 zmw_get_wlan_dev(dev);
630
631 zmw_declare_for_critical_section();
632
633#ifndef ZM_DISABLE_RATE_CTRL
634
635 if (aggRate && (aggRate != rcCell->currentRate)) {
636 wd->txFail[aggRate] += retryRate;
637 return;
638 }
639
640 if (!aggRate) {
641 retryRate = (zfRateCtrlRateDiff(rcCell, (u8_t)retryRate)+1)>>1;
642 if (rcCell->currentRate <12)
643 {
644 retryRate*=2;
645 }
646 }
647 rcCell->failCount += retryRate;
648 wd->txFail[rcCell->currentRate] += retryRate;
649
650
651 if (rcCell->failCount > ZM_MIN_RATE_FAIL_COUNT)
652 {
653 if (wd->txMPDU[rcCell->currentRate] != 0) {
654 wd->PER[rcCell->currentRate] = zm_agg_min(100,
655 (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
656 if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
657 }
658
659
660 if (wd->PER[rcCell->currentRate] > PERThreshold[rcCell->currentRate])
661 {
662
663 zfRateCtrlNextLowerRate(dev, rcCell);
664 rcCell->flag |= ZM_RC_TRAINED_BIT;
665
666
667 if(rcCell->currentRate == 15)
668 {
669 zmw_leave_critical_section(dev);
670 zfHpSetAggPktNum(dev, 8);
671 zmw_enter_critical_section(dev);
672 }
673
674 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
675 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
676
677 wd->probeCount = wd->probeSuccessCount = 0;
678 }
679 }
680
681#endif
682 return;
683}
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702void zfRateCtrlTxSuccessEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t successRate)
703{
704
705 u16_t i, PERProbe;
706 u16_t pcount;
707 zmw_get_wlan_dev(dev);
708
709 zmw_declare_for_critical_section();
710
711
712
713 wd->probeSuccessCount++;
714 if (wd->probeCount < wd->success_probing)
715 {
716 return;
717 }
718
719 pcount = wd->probeCount;
720 if (pcount != 0)
721 {
722 PERProbe = wd->probeSuccessCount * 100 / pcount;
723 }
724 else
725 {
726 PERProbe = 1;
727 }
728
729 if (PERProbe < ((rcCell->currentRate < 16)? 80:100))
730 {
731 return;
732 }
733
734 wd->probeCount = wd->probeSuccessCount = 0;
735 for (i=0; i<rcCell->operationRateCount; i++)
736 {
737 if (successRate == rcCell->operationRateSet[i])
738 {
739 if (i > rcCell->currentRateIndex)
740 {
741
742 zm_msg1_tx(ZM_LV_0, "Raise Tx Rate=", successRate);
743
744
745
746 if((rcCell->currentRate <= 15) && (successRate > 15))
747 {
748 zmw_leave_critical_section(dev);
749 zfHpSetAggPktNum(dev, 16);
750 zmw_enter_critical_section(dev);
751 }
752
753 rcCell->currentRate = successRate;
754 rcCell->currentRateIndex = (u8_t)i;
755 rcCell->failCount = rcCell->txCount = 0;
756 rcCell->lasttxCount = 0;
757 rcCell->lastTime = wd->tick;
758 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
759 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
760 }
761 }
762 }
763
764 return;
765}
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785void zfRateCtrlRxRssiEvent(struct zsRcCell* rcCell, u16_t rxRssi)
786{
787
788 if ((rcCell->rxRssi - rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION)
789 {
790
791 rcCell->probingTime -= ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK;
792 }
793
794
795 rcCell->rxRssi = (((rcCell->rxRssi*7) + rxRssi)+4) >> 3;
796 return;
797}
798
799
800#ifdef ZM_ENABLE_BA_RATECTRL
801u8_t HigherRate(u8_t Rate) {
802 if (Rate < 28) Rate++;
803 if (Rate > 28) Rate = 28;
804 while ((Rate >= 20) && (Rate <= 23)) {
805 Rate ++;
806 }
807 return Rate;
808}
809
810u8_t LowerRate(u8_t Rate) {
811 if (Rate > 1) Rate--;
812 while ((Rate >= 20) && (Rate <= 23)) {
813 Rate --;
814 }
815 return Rate;
816}
817
818u8_t RateMapToRateIndex(u8_t Rate, struct zsRcCell* rcCell) {
819 u8_t i;
820 for (i=0; i<rcCell->operationRateCount; i++) {
821 if (Rate == rcCell->operationRateSet[i]) {
822 return i;
823 }
824 }
825 return 0;
826}
827
828void zfRateCtrlAggrSta(zdev_t* dev) {
829 u8_t RateIndex, Rate;
830 u8_t HRate;
831 u8_t LRate;
832 u32_t RateCtrlTxMPDU, RateCtrlBAFail;
833 zmw_get_wlan_dev(dev);
834
835 RateIndex = wd->sta.oppositeInfo[0].rcCell.currentRateIndex;
836 Rate = wd->sta.oppositeInfo[0].rcCell.operationRateSet[RateIndex];
837
838 TxMPDU[Rate] = (TxMPDU[Rate] / 5) + (wd->commTally.RateCtrlTxMPDU * 4 / 5);
839 BAFail[Rate] = (BAFail[Rate] / 5) + (wd->commTally.RateCtrlBAFail * 4 / 5);
840 RateCtrlTxMPDU = wd->commTally.RateCtrlTxMPDU;
841 RateCtrlBAFail = wd->commTally.RateCtrlBAFail;
842 wd->commTally.RateCtrlTxMPDU = 0;
843 wd->commTally.RateCtrlBAFail = 0;
844 if (TxMPDU[Rate] > 0) {
845 BAPER[Rate] = BAFail[Rate] * 1000 / TxMPDU[Rate];
846 BAPER[Rate] = (BAPER[Rate]>0)? BAPER[Rate]:1;
847 }
848 else {
849 return;
850 }
851
852 HRate = HigherRate(Rate);
853 LRate = LowerRate(Rate);
854 if (BAPER[Rate]>200) {
855 if ((RateCtrlTxMPDU > 100) && (BAPER[Rate]<300) && (HRate != Rate) && BAPER[HRate] &&
856 (BAPER[HRate] < BAPER[Rate] + BADiff[Rate])) {
857 Rate = HRate;
858
859 }
860 else {
861 Rate = LRate;
862
863 }
864 }
865 else if (BAPER[Rate] && BAPER[Rate]<100) {
866 if (RateCtrlTxMPDU > 100) {
867 Rate = HRate;
868
869 }
870 }
871 wd->sta.oppositeInfo[0].rcCell.currentRate = Rate;
872 wd->sta.oppositeInfo[0].rcCell.currentRateIndex = RateMapToRateIndex(Rate, &wd->sta.oppositeInfo[0].rcCell);
873}
874#endif
875