GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / otus / 80211core / ratectrl.c
bloba1abe2f4f342247571ac7a6a9a252583f7eb60cc
1 /*
2 * Copyright (c) 2007-2008 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "cprecomp.h"
18 #include "ratectrl.h"
20 const u32_t zcRateToPhyCtrl[] =
22 /* 1M, 2M, 5M, 11M , 0 1 2 3*/
23 0x00000, 0x10000, 0x20000, 0x30000,
24 /* 6M 9M 12M 18M , 4 5 6 7*/
25 0xb0001, 0xf0001, 0xa0001, 0xe0001,
26 /* 24M 36M 48M 54M , 8 9 10 11*/
27 0x90001, 0xd0001, 0x80001, 0xc0001,
28 /* MCS0 MCS1 MCS2 MCS3, 12 13 14 15*/
29 0x00002, 0x10002, 0x20002, 0x30002,
30 /* MCS4 MCS5 MCS6 MCS7, 16 17 18 19*/
31 0x40002, 0x50002, 0x60002, 0x70002,
32 /* MCS8 MCS9 MCS10 MCS11, 20 21 22 23*/
33 0x80002, 0x90002, 0xa0002, 0xb0002,
34 /* MCS12 MCS13 MCS14 MCS15, 24 25 26 27*/
35 0xc0002, 0xd0002, 0xe0002, 0xf0002,
36 /* MCS14SG, MCS15SG MCS7SG , 28 29, 30*/
37 0x800e0002, 0x800f0002, 0x80070002
41 const u8_t zcHtRateTable[15][4] =
42 { /*[5G 20MHz] [5G 40MHz] [2.4G 20MHz] [2.4G 40MHz]*/
43 { 4, 4, 0, 0}, /*OFDM6M OFDM6M CCK1M CCK1M */
44 { 5, 5, 1, 1}, /*OFDM9M OFDM9M CCK2M CCK2M */
45 { 13, 12, 2, 2}, /*MCS1 MCS0 CCK5M CCK5M */
46 { 14, 13, 3, 3}, /*MCS2 MCS1 CCK11M CCK11M */
47 { 15, 14, 13, 12}, /*MCS3 MCS2 MCS1 MCS0 */
48 { 16, 15, 14, 13}, /*MCS4 MCS3 MCS2 MCS1 */
49 { 23, 16, 15, 14}, /*MCS11 MCS4 MCS3 MCS2 */
50 { 24, 23, 16, 15}, /*MCS12 MCS11 MCS4 MCS3 */
51 { 25, 24, 23, 16}, /*MCS13 MCS12 MCS11 MCS4 */
52 { 26, 25, 24, 23}, /*MCS14 MCS13 MCS12 MCS11 */
53 { 27, 26, 25, 24}, /*MCS15 MCS14 MCS13 MCS12 */
54 { 0, 27, 26, 25}, /*0 MCS15 MCS14 MCS13 */
55 { 0, 29, 27, 26}, /*0 MCS15SG MCS15 MCS14 */
56 { 0, 0, 0, 28}, /*0 0 0 MCS14SG*/
57 { 0, 0, 0, 29} /*0 0 0 MCS15SG*/
60 const u8_t zcHtOneTxStreamRateTable[15][4] =
61 { /*[5G 20MHz] [5G 40MHz] [2.4G 20MHz] [2.4G 40MHz]*/
62 { 4, 4, 0, 0}, /*OFDM6M OFDM6M CCK1M CCK1M */
63 { 5, 5, 1, 1}, /*OFDM9M OFDM9M CCK2M CCK2M */
64 { 13, 12, 2, 2}, /*MCS1 MCS0 CCK5M CCK5M */
65 { 14, 13, 3, 3}, /*MCS2 MCS1 CCK11M CCK11M */
66 { 15, 14, 13, 12}, /*MCS3 MCS2 MCS1 MCS0 */
67 { 16, 15, 14, 13}, /*MCS4 MCS3 MCS2 MCS1 */
68 { 17, 16, 15, 14}, /*MCS5 MCS4 MCS3 MCS2 */
69 { 18, 17, 16, 15}, /*MCS6 MCS5 MCS4 MCS3 */
70 { 19, 18, 17, 16}, /*MCS7 MCS6 MCS5 MCS4 */
71 { 0, 19, 18, 17}, /*0 MCS7 MCS6 MCS5 */
72 { 0, 30, 19, 18}, /*0 MCS7SG MCS7 MCS6 */
73 { 0, 0, 0, 19}, /*0 0 0 MCS7 */
74 { 0, 0, 0, 30}, /*0 0 0 MCS7SG */
75 { 0, 0, 0, 0 }, /*0 0 0 0 */
76 { 0, 0, 0, 0 } /*0 0 0 0 */
79 const u16_t zcRate[] =
81 1, 2, 5, 11, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
82 6, 9, 12, 18, /* 6M 9M 12M 18M , 4 5 6 7*/
83 24, 36, 48, 54, /* 24M 36M 48M 54M , 8 9 10 11*/
84 13, 27, 40, 54, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
85 81, 108, 121, 135, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
86 27, 54, 81, 108, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
87 162, 216, 243, 270, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
88 270, 300, 150 /* MCS14SG, MCS15SG, MCS7SG , 28 29 30*/
91 const u16_t PERThreshold[] =
93 100, 50, 50, 50, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
94 50, 50, 30, 30, /* 6M 9M 12M 18M , 4 5 6 7*/
95 25, 25, 25, 20, /* 24M 36M 48M 54M , 8 9 10 11*/
96 50, 50, 50, 40, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
97 30, 30, 30, 30, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
98 30, 30, 25, 25, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
99 25, 25, 15, 15, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
100 15, 15, 10 /* MCS14SG, MCS15SG , 28 29*/
103 const u16_t FailDiff[] =
105 40, 46, 40, 0, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
106 24, 17, 22, 16, /* 6M 9M 12M 18M , 4 5 6 7*/
107 19, 13, 5, 0, /* 24M 36M 48M 54M , 8 9 10 11*/
108 36, 22, 15, 19, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
109 12, 5, 4, 7, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
110 0, 0, 0, 0, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
111 9, 4, 3, 3, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
112 3, 0, 0 /* MCS14SG, MCS15SG , 28 29*/
116 #ifdef ZM_ENABLE_BA_RATECTRL
117 u32_t TxMPDU[29];
118 u32_t BAFail[29];
119 u32_t BAPER[29];
120 const u16_t BADiff[] =
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,
131 #endif
133 /************************************************************************/
134 /* */
135 /* FUNCTION DESCRIPTION zfRateCtrlInitCell */
136 /* Initialize rate control cell. */
137 /* */
138 /* INPUTS */
139 /* dev : device pointer */
140 /* type : 0=>11b, 1=>11a/g, 2=>11n, 3=>11n one Tx stream */
141 /* gBand : 1=>2.4G, 0=>5G */
142 /* */
143 /* OUTPUTS */
144 /* None */
145 /* */
146 /* AUTHOR */
147 /* Stephen Chen Atheros Communications, INC. 2007.2 */
148 /* */
149 /************************************************************************/
150 void zfRateCtrlInitCell(zdev_t* dev, struct zsRcCell* rcCell, u8_t type,
151 u8_t gBand, u8_t SG40)
153 u8_t i;
154 u8_t maxrate;
155 zmw_get_wlan_dev(dev);
157 if (SG40) SG40 = 1;
159 if (gBand != 0)
161 if (type == 1) //11g
163 for (i=0; i<4; i++) //1M 2M 5M 11M
165 rcCell->operationRateSet[i] = (u8_t)i;
167 for (i=4; i<10; i++) //12M 18M 24M 36M 48M 54M
169 rcCell->operationRateSet[i] = 2+i;
171 rcCell->operationRateCount = 10;
172 rcCell->currentRateIndex = 5; //18M
174 else if (type == 2) //11ng
176 if (wd->wlanMode == ZM_MODE_AP) //AP 11ng 40M
178 for (i=0; i<15; i++)
180 rcCell->operationRateSet[i] = zcHtRateTable[i][3];
182 if(!SG40) rcCell->operationRateSet[13] = 27;
183 rcCell->operationRateCount = 14+SG40;
184 rcCell->currentRateIndex = 10;
186 else //STA
188 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M
190 for (i=0; i<15; i++)
192 rcCell->operationRateSet[i] = zcHtRateTable[i][3];
194 if(!SG40) rcCell->operationRateSet[13] = 27;
195 rcCell->operationRateCount = 14+SG40;
196 rcCell->currentRateIndex = 10;
198 else //11ng 20M
200 for (i=0; i<13; i++)
202 rcCell->operationRateSet[i] = zcHtRateTable[i][2];
204 rcCell->operationRateCount = 13;
205 rcCell->currentRateIndex = 9;
209 else if (type == 3) //11ng one Tx stream
211 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M one Tx stream
213 if(SG40 != 0)
215 maxrate = 13;
217 else
219 maxrate = 12;
221 for (i=0; i<maxrate; i++)
223 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][3];
225 rcCell->operationRateCount = i;
226 rcCell->currentRateIndex = ((i+1)*3)/4;
228 else //11ng 20M
230 for (i=0; i<11; i++)
232 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][2];
234 rcCell->operationRateCount = i;
235 rcCell->currentRateIndex = ((i+1)*3)/4;
238 else //if (type == 0) //11b
240 for (i=0; i<4; i++)
242 rcCell->operationRateSet[i] = (u8_t)i;
244 rcCell->operationRateCount = 4;
245 rcCell->currentRateIndex = rcCell->operationRateCount-1;
248 else
250 if (type == 2) //11na
252 if (wd->wlanMode == ZM_MODE_AP) //AP 11na 40M
254 for (i=0; i<(12+SG40); i++)
256 rcCell->operationRateSet[i] = zcHtRateTable[i][1];
258 rcCell->operationRateCount = 12+SG40;
259 rcCell->currentRateIndex = 8;
261 else //STA
263 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M
265 for (i=0; i<(12+SG40); i++)
267 rcCell->operationRateSet[i] = zcHtRateTable[i][1];
269 rcCell->operationRateCount = 12+SG40;
270 rcCell->currentRateIndex = 8;
272 else //11na 20M
274 for (i=0; i<11; i++)
276 rcCell->operationRateSet[i] = zcHtRateTable[i][0];
278 rcCell->operationRateCount = 11;
279 rcCell->currentRateIndex = 7;
283 else if (type == 3) //11na one Tx stream
285 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M one Tx stream
287 if(SG40 != 0)
289 maxrate = 11;
291 else
293 maxrate = 10;
295 for (i=0; i<maxrate; i++)
297 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][1];
299 rcCell->operationRateCount = i;
300 rcCell->currentRateIndex = ((i+1)*3)/4;
302 else //11ng 20M
304 for (i=0; i<9; i++)
306 rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][0];
308 rcCell->operationRateCount = i;
309 rcCell->currentRateIndex = ((i+1)*3)/4;
312 else //if (type == 1) //11a
314 for (i=0; i<8; i++) //6M 9M 12M 18M 24M 36M 48M 54M
316 rcCell->operationRateSet[i] = i+4;
318 rcCell->operationRateCount = 8;
319 rcCell->currentRateIndex = 4; //24M
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;
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;
342 #endif
343 return;
347 /************************************************************************/
348 /* */
349 /* FUNCTION DESCRIPTION zfRateCtrlGetHigherRate */
350 /* Get a higher rate. */
351 /* */
352 /* INPUTS */
353 /* rcCell : rate control cell */
354 /* */
355 /* OUTPUTS */
356 /* rate */
357 /* */
358 /* AUTHOR */
359 /* Stephen Chen Atheros Communications, INC. 2007.2 */
360 /* */
361 /************************************************************************/
362 u8_t zfRateCtrlGetHigherRate(struct zsRcCell* rcCell)
364 u8_t rateIndex;
366 rateIndex = rcCell->currentRateIndex
367 + (((rcCell->currentRateIndex+1) < rcCell->operationRateCount)?1:0);
368 return rcCell->operationRateSet[rateIndex];
372 /************************************************************************/
373 /* */
374 /* FUNCTION DESCRIPTION zfRateCtrlNextLowerRate */
375 /* Get a lower rate. */
376 /* */
377 /* INPUTS */
378 /* rcCell : rate control cell */
379 /* */
380 /* OUTPUTS */
381 /* rate */
382 /* */
383 /* AUTHOR */
384 /* Stephen Chen Atheros Communications, INC. 2007.2 */
385 /* */
386 /************************************************************************/
387 u8_t zfRateCtrlNextLowerRate(zdev_t* dev, struct zsRcCell* rcCell)
389 zmw_get_wlan_dev(dev);
390 if (rcCell->currentRateIndex > 0)
392 rcCell->currentRateIndex--;
393 rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
395 zm_msg1_tx(ZM_LV_0, "Lower Tx Rate=", rcCell->currentRate);
396 //DbgPrint("Lower Tx Rate=%d", rcCell->currentRate);
397 rcCell->failCount = rcCell->txCount = 0;
398 rcCell->lasttxCount = 0;
399 rcCell->lastTime = wd->tick;
400 return rcCell->currentRate;
404 /************************************************************************/
405 /* */
406 /* FUNCTION DESCRIPTION zfRateCtrlRateDiff */
407 /* Rate difference. */
408 /* */
409 /* INPUTS */
410 /* rcCell : rate control cell */
411 /* retryRate : retry rate */
412 /* */
413 /* OUTPUTS */
414 /* rate difference */
415 /* */
416 /* AUTHOR */
417 /* Stephen Chen Atheros Communications, INC. 2007.2 */
418 /* */
419 /************************************************************************/
420 u8_t zfRateCtrlRateDiff(struct zsRcCell* rcCell, u8_t retryRate)
422 u16_t i;
424 /* Find retryRate in operationRateSet[] */
425 for (i=0; i<rcCell->operationRateCount; i++)
427 if (retryRate == rcCell->operationRateSet[i])
429 if (i < rcCell->currentRateIndex)
431 return ((rcCell->currentRateIndex - i)+1)>>1;
433 else if (i == rcCell->currentRateIndex == 0)
435 return 1;
437 else
439 return 0;
443 /* TODO : retry rate not in operation rate set */
444 zm_msg1_tx(ZM_LV_0, "Not in operation rate set:", retryRate);
445 return 1;
449 u32_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;
456 u8_t zfRateCtrlFindMaxUDPTP(zdev_t* dev, struct zsRcCell* rcCell) {
457 u8_t i, maxIndex=0, rateIndex;
458 u32_t max=0, UDPThroughput;
460 zmw_get_wlan_dev(dev);
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;
472 return rcCell->operationRateSet[maxIndex];
474 /************************************************************************/
475 /* */
476 /* FUNCTION DESCRIPTION zfRateCtrlGetTxRate */
477 /* Get transmission rate. */
478 /* */
479 /* INPUTS */
480 /* dev : device pointer */
481 /* rcCell : rate control cell */
482 /* probing : rate probing flag */
483 /* */
484 /* OUTPUTS */
485 /* Tx rate */
486 /* */
487 /* AUTHOR */
488 /* Stephen Chen Atheros Communications, INC. 2007.2 */
489 /* */
490 /************************************************************************/
491 u16_t zfRateCtrlGetTxRate(zdev_t* dev, struct zsRcCell* rcCell, u16_t* probing)
493 u8_t newRate, highRate;
494 zmw_get_wlan_dev(dev);
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;
502 if (wd->probeCount && (wd->probeCount < wd->success_probing))
504 if (wd->probeInterval < 50)
506 wd->probeInterval++;
508 else
510 wd->probeInterval++;
511 if (wd->probeInterval > 52) //probe 51, 52, 53 three packets every 50 packets
513 wd->probeInterval = 0;
515 newRate=zfRateCtrlGetHigherRate(rcCell);
516 *probing = 1;
517 wd->probeCount++;
518 rcCell->probingTime = wd->tick;
521 /* Accumulate at least 1000ms and 8 packets or Accumulate over 1K packets */
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))
526 #ifndef ZM_DISABLE_RATE_CTRL
527 /* PER = fail/total */
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] ++;
536 /* if PER < threshold, do rate probing, return probing rate */
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)))
541 newRate = zfRateCtrlGetHigherRate(rcCell);
542 if (newRate != rcCell->currentRate)
544 *probing = 1;
545 wd->probeCount++;
546 wd->probeInterval = 0;
547 wd->success_probing =
548 (rcCell->currentRate <= 16)? (ZM_RATE_SUCCESS_PROBING/2) : ZM_RATE_SUCCESS_PROBING;
549 //DbgPrint("Start Probing");
550 zm_msg1_tx(ZM_LV_0, "Probing Rate=", newRate);
553 #endif
555 zm_msg0_tx(ZM_LV_1, "Diminish counter");
556 rcCell->failCount = rcCell->failCount>>1;
557 rcCell->txCount = rcCell->txCount>>1;
558 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
559 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
562 if (rcCell->currentRate > 15) {
563 highRate = zfRateCtrlGetHigherRate(rcCell);
564 if ((highRate != rcCell->currentRate) && wd->PER[highRate] &&
565 ((wd->PER[rcCell->currentRate] + FailDiff[rcCell->currentRate]) >
566 wd->PER[highRate])) {
567 //DbgPrint("PER compare force raise rate to %d", highRate);
568 wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
569 zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
572 else {
573 highRate = zfRateCtrlFindMaxUDPTP(dev, rcCell);
574 if (rcCell->currentRate < highRate) {
575 //DbgPrint("UDP Throughput compare force raise rate to %d", highRate);
576 wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
577 zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
580 rcCell->probingTime = wd->tick;
583 if( (wd->tick > 1000)
584 && ((wd->tick - rcCell->lastTime) > 3840) )
586 if (rcCell->lasttxCount < 70)
588 rcCell->failCount = rcCell->failCount>>1;
589 rcCell->txCount = rcCell->txCount>>1;
590 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
591 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
593 rcCell->failCount = (rcCell->failCount < rcCell->txCount)?
594 rcCell->failCount : rcCell->txCount;
595 wd->txFail[rcCell->currentRate] = (wd->txFail[rcCell->currentRate] < wd->txMPDU[rcCell->currentRate])?
596 wd->txFail[rcCell->currentRate] : wd->txMPDU[rcCell->currentRate];
599 rcCell->lastTime = wd->tick;
600 rcCell->lasttxCount = 0;
603 rcCell->txCount++;
604 rcCell->lasttxCount++;
605 wd->txMPDU[rcCell->currentRate]++;
606 zm_msg1_tx(ZM_LV_1, "Get Tx Rate=", newRate);
607 return newRate;
611 /************************************************************************/
612 /* */
613 /* FUNCTION DESCRIPTION zfRateCtrlTxFailEvent */
614 /* Tx fail event. Calculate PER and lower Tx rate if under */
615 /* PER under threshold. */
616 /* */
617 /* INPUTS */
618 /* rcCell : rate control cell */
619 /* retryRate : retry rate */
620 /* */
621 /* OUTPUTS */
622 /* None */
623 /* */
624 /* AUTHOR */
625 /* Stephen Chen Atheros Communications, INC. 2007.2 */
626 /* */
627 /************************************************************************/
628 void zfRateCtrlTxFailEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t aggRate, u32_t retryRate)
630 zmw_get_wlan_dev(dev);
632 zmw_declare_for_critical_section();
634 #ifndef ZM_DISABLE_RATE_CTRL
635 //DbgPrint("aggRate=%d, retryRate=%d", aggRate, retryRate);
636 if (aggRate && (aggRate != rcCell->currentRate)) {
637 wd->txFail[aggRate] += retryRate;
638 return;
641 if (!aggRate) {
642 retryRate = (zfRateCtrlRateDiff(rcCell, (u8_t)retryRate)+1)>>1;
643 if (rcCell->currentRate <12) //legacy rate
645 retryRate*=2;
648 rcCell->failCount += retryRate;
649 wd->txFail[rcCell->currentRate] += retryRate;
651 //DbgPrint("failCount=%d", rcCell->failCount);
652 if (rcCell->failCount > ZM_MIN_RATE_FAIL_COUNT)
654 if (wd->txMPDU[rcCell->currentRate] != 0) {
655 wd->PER[rcCell->currentRate] = zm_agg_min(100,
656 (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
657 if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
659 //zm_msg1_tx(ZM_LV_1, "PER=", per);
660 //DbgPrint("PER=%d, txFail=%d, txMPDU=%d", wd->PER[rcCell->currentRate], wd->txFail[rcCell->currentRate], wd->txMPDU[rcCell->currentRate]);
661 if (wd->PER[rcCell->currentRate] > PERThreshold[rcCell->currentRate])
663 /* Lower Tx Rate if PER < THRESHOLD */
664 zfRateCtrlNextLowerRate(dev, rcCell);
665 rcCell->flag |= ZM_RC_TRAINED_BIT;
667 // Resolve compatibility problem with Marvell
668 if(rcCell->currentRate == 15)
670 zmw_leave_critical_section(dev);
671 zfHpSetAggPktNum(dev, 8);
672 zmw_enter_critical_section(dev);
675 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
676 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
678 wd->probeCount = wd->probeSuccessCount = 0;
682 #endif
683 return;
687 /************************************************************************/
688 /* */
689 /* FUNCTION DESCRIPTION zfRateCtrlTxSuccessEvent */
690 /* Tx success event. Raise Tx rate because rate probing success. */
691 /* */
692 /* INPUTS */
693 /* rcCell : rate control cell */
694 /* successRate : success rate */
695 /* */
696 /* OUTPUTS */
697 /* None */
698 /* */
699 /* AUTHOR */
700 /* Stephen Chen Atheros Communications, INC. 2007.2 */
701 /* */
702 /************************************************************************/
703 void zfRateCtrlTxSuccessEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t successRate)
705 /* Raise Tx Rate */
706 u16_t i, PERProbe;
707 u16_t pcount;
708 zmw_get_wlan_dev(dev);
710 zmw_declare_for_critical_section();
712 //DbgPrint("Probing successRate=%d", successRate);
713 /* Find successRate in operationRateSet[] */
714 wd->probeSuccessCount++;
715 if (wd->probeCount < wd->success_probing)
717 return;
720 pcount = wd->probeCount;
721 if (pcount != 0)
723 PERProbe = wd->probeSuccessCount * 100 / pcount;
725 else
727 PERProbe = 1;
730 if (PERProbe < ((rcCell->currentRate < 16)? 80:100))
732 return;
734 //DbgPrint("wd->probeCount=%d, wd->probeSuccessCount=%d", wd->probeCount, wd->probeSuccessCount);
735 wd->probeCount = wd->probeSuccessCount = 0;
736 for (i=0; i<rcCell->operationRateCount; i++)
738 if (successRate == rcCell->operationRateSet[i])
740 if (i > rcCell->currentRateIndex)
742 /* Raise current Tx rate */
743 zm_msg1_tx(ZM_LV_0, "Raise Tx Rate=", successRate);
744 //DbgPrint("Raise Tx Rate=%d", successRate);
746 // Resolve compatibility problem with Marvell
747 if((rcCell->currentRate <= 15) && (successRate > 15))
749 zmw_leave_critical_section(dev);
750 zfHpSetAggPktNum(dev, 16);
751 zmw_enter_critical_section(dev);
754 rcCell->currentRate = successRate;
755 rcCell->currentRateIndex = (u8_t)i;
756 rcCell->failCount = rcCell->txCount = 0;
757 rcCell->lasttxCount = 0;
758 rcCell->lastTime = wd->tick;
759 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
760 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
765 return;
769 /************************************************************************/
770 /* */
771 /* FUNCTION DESCRIPTION zfRateCtrlRxRssiEvent */
772 /* Rx RSSI event. Calculate RSSI moving average, accelarate */
773 /* rate probing if RSSI variation over threshold. */
774 /* */
775 /* INPUTS */
776 /* rcCell : rate control cell */
777 /* successRate : success rate */
778 /* */
779 /* OUTPUTS */
780 /* None */
781 /* */
782 /* AUTHOR */
783 /* Stephen Chen Atheros Communications, INC. 2007.2 */
784 /* */
785 /************************************************************************/
786 void zfRateCtrlRxRssiEvent(struct zsRcCell* rcCell, u16_t rxRssi)
788 /* if delta(rcCell->rxRssi, rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION */
789 if ((rcCell->rxRssi - rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION)
791 /* Accelerate rate probing via decreaing rcCell->probingTime */
792 rcCell->probingTime -= ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK;
795 /* Update RSSI moving average */
796 rcCell->rxRssi = (((rcCell->rxRssi*7) + rxRssi)+4) >> 3;
797 return;
801 #ifdef ZM_ENABLE_BA_RATECTRL
802 u8_t HigherRate(u8_t Rate) {
803 if (Rate < 28) Rate++; //28=MCS15SG, 27=MCS15, 26=MCS14, 25=MCS13
804 if (Rate > 28) Rate = 28;
805 while ((Rate >= 20) && (Rate <= 23)) {
806 Rate ++;
808 return Rate;
811 u8_t LowerRate(u8_t Rate) {
812 if (Rate > 1) Rate--;
813 while ((Rate >= 20) && (Rate <= 23)) {
814 Rate --;
816 return Rate;
819 u8_t RateMapToRateIndex(u8_t Rate, struct zsRcCell* rcCell) {
820 u8_t i;
821 for (i=0; i<rcCell->operationRateCount; i++) {
822 if (Rate == rcCell->operationRateSet[i]) {
823 return i;
826 return 0;
829 void zfRateCtrlAggrSta(zdev_t* dev) {
830 u8_t RateIndex, Rate;
831 u8_t HRate;
832 u8_t LRate;
833 u32_t RateCtrlTxMPDU, RateCtrlBAFail;
834 zmw_get_wlan_dev(dev);
836 RateIndex = wd->sta.oppositeInfo[0].rcCell.currentRateIndex;
837 Rate = wd->sta.oppositeInfo[0].rcCell.operationRateSet[RateIndex];
839 TxMPDU[Rate] = (TxMPDU[Rate] / 5) + (wd->commTally.RateCtrlTxMPDU * 4 / 5);
840 BAFail[Rate] = (BAFail[Rate] / 5) + (wd->commTally.RateCtrlBAFail * 4 / 5);
841 RateCtrlTxMPDU = wd->commTally.RateCtrlTxMPDU;
842 RateCtrlBAFail = wd->commTally.RateCtrlBAFail;
843 wd->commTally.RateCtrlTxMPDU = 0;
844 wd->commTally.RateCtrlBAFail = 0;
845 if (TxMPDU[Rate] > 0) {
846 BAPER[Rate] = BAFail[Rate] * 1000 / TxMPDU[Rate]; //PER*1000
847 BAPER[Rate] = (BAPER[Rate]>0)? BAPER[Rate]:1;
849 else {
850 return;
853 HRate = HigherRate(Rate);
854 LRate = LowerRate(Rate);
855 if (BAPER[Rate]>200) {
856 if ((RateCtrlTxMPDU > 100) && (BAPER[Rate]<300) && (HRate != Rate) && BAPER[HRate] &&
857 (BAPER[HRate] < BAPER[Rate] + BADiff[Rate])) {
858 Rate = HRate;
859 //DbgPrint("Rate improved to %d", Rate);
861 else {
862 Rate = LRate;
863 //DbgPrint("Rate decreased to %d", Rate);
866 else if (BAPER[Rate] && BAPER[Rate]<100) {
867 if (RateCtrlTxMPDU > 100) {
868 Rate = HRate;
869 //DbgPrint("Rate improved to %d", Rate);
872 wd->sta.oppositeInfo[0].rcCell.currentRate = Rate;
873 wd->sta.oppositeInfo[0].rcCell.currentRateIndex = RateMapToRateIndex(Rate, &wd->sta.oppositeInfo[0].rcCell);
875 #endif