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.
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
120 const u16_t BADiff
[] =
133 /************************************************************************/
135 /* FUNCTION DESCRIPTION zfRateCtrlInitCell */
136 /* Initialize rate control cell. */
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 */
147 /* Stephen Chen Atheros Communications, INC. 2007.2 */
149 /************************************************************************/
150 void zfRateCtrlInitCell(zdev_t
* dev
, struct zsRcCell
* rcCell
, u8_t type
,
151 u8_t gBand
, u8_t SG40
)
155 zmw_get_wlan_dev(dev
);
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
180 rcCell
->operationRateSet
[i
] = zcHtRateTable
[i
][3];
182 if(!SG40
) rcCell
->operationRateSet
[13] = 27;
183 rcCell
->operationRateCount
= 14+SG40
;
184 rcCell
->currentRateIndex
= 10;
188 if (wd
->sta
.htCtrlBandwidth
== ZM_BANDWIDTH_40MHZ
) //11ng 40M
192 rcCell
->operationRateSet
[i
] = zcHtRateTable
[i
][3];
194 if(!SG40
) rcCell
->operationRateSet
[13] = 27;
195 rcCell
->operationRateCount
= 14+SG40
;
196 rcCell
->currentRateIndex
= 10;
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
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;
232 rcCell
->operationRateSet
[i
] = zcHtOneTxStreamRateTable
[i
][2];
234 rcCell
->operationRateCount
= i
;
235 rcCell
->currentRateIndex
= ((i
+1)*3)/4;
238 else //if (type == 0) //11b
242 rcCell
->operationRateSet
[i
] = (u8_t
)i
;
244 rcCell
->operationRateCount
= 4;
245 rcCell
->currentRateIndex
= rcCell
->operationRateCount
-1;
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;
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;
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
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;
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
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
++) {
332 wd
->txMPDU
[i
] = wd
->txFail
[i
] = 0;
335 wd
->probeInterval
= 0;
336 #ifdef ZM_ENABLE_BA_RATECTRL
337 for (i
=0; i
<29; i
++) {
347 /************************************************************************/
349 /* FUNCTION DESCRIPTION zfRateCtrlGetHigherRate */
350 /* Get a higher rate. */
353 /* rcCell : rate control cell */
359 /* Stephen Chen Atheros Communications, INC. 2007.2 */
361 /************************************************************************/
362 u8_t
zfRateCtrlGetHigherRate(struct zsRcCell
* rcCell
)
366 rateIndex
= rcCell
->currentRateIndex
367 + (((rcCell
->currentRateIndex
+1) < rcCell
->operationRateCount
)?1:0);
368 return rcCell
->operationRateSet
[rateIndex
];
372 /************************************************************************/
374 /* FUNCTION DESCRIPTION zfRateCtrlNextLowerRate */
375 /* Get a lower rate. */
378 /* rcCell : rate control cell */
384 /* Stephen Chen Atheros Communications, INC. 2007.2 */
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 /************************************************************************/
406 /* FUNCTION DESCRIPTION zfRateCtrlRateDiff */
407 /* Rate difference. */
410 /* rcCell : rate control cell */
411 /* retryRate : retry rate */
414 /* rate difference */
417 /* Stephen Chen Atheros Communications, INC. 2007.2 */
419 /************************************************************************/
420 u8_t
zfRateCtrlRateDiff(struct zsRcCell
* rcCell
, u8_t retryRate
)
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)
443 /* TODO : retry rate not in operation rate set */
444 zm_msg1_tx(ZM_LV_0
, "Not in operation rate set:", retryRate
);
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
)));
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
) {
472 return rcCell
->operationRateSet
[maxIndex
];
474 /************************************************************************/
476 /* FUNCTION DESCRIPTION zfRateCtrlGetTxRate */
477 /* Get transmission rate. */
480 /* dev : device pointer */
481 /* rcCell : rate control cell */
482 /* probing : rate probing flag */
488 /* Stephen Chen Atheros Communications, INC. 2007.2 */
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
);
500 newRate
= rcCell
->currentRate
;
502 if (wd
->probeCount
&& (wd
->probeCount
< wd
->success_probing
))
504 if (wd
->probeInterval
< 50)
511 if (wd
->probeInterval
> 52) //probe 51, 52, 53 three packets every 50 packets
513 wd
->probeInterval
= 0;
515 newRate
=zfRateCtrlGetHigherRate(rcCell
);
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 */
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
)
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
);
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
);
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;
604 rcCell
->lasttxCount
++;
605 wd
->txMPDU
[rcCell
->currentRate
]++;
606 zm_msg1_tx(ZM_LV_1
, "Get Tx Rate=", newRate
);
611 /************************************************************************/
613 /* FUNCTION DESCRIPTION zfRateCtrlTxFailEvent */
614 /* Tx fail event. Calculate PER and lower Tx rate if under */
615 /* PER under threshold. */
618 /* rcCell : rate control cell */
619 /* retryRate : retry rate */
625 /* Stephen Chen Atheros Communications, INC. 2007.2 */
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
;
642 retryRate
= (zfRateCtrlRateDiff(rcCell
, (u8_t
)retryRate
)+1)>>1;
643 if (rcCell
->currentRate
<12) //legacy rate
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;
687 /************************************************************************/
689 /* FUNCTION DESCRIPTION zfRateCtrlTxSuccessEvent */
690 /* Tx success event. Raise Tx rate because rate probing success. */
693 /* rcCell : rate control cell */
694 /* successRate : success rate */
700 /* Stephen Chen Atheros Communications, INC. 2007.2 */
702 /************************************************************************/
703 void zfRateCtrlTxSuccessEvent(zdev_t
* dev
, struct zsRcCell
* rcCell
, u8_t successRate
)
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
)
720 pcount
= wd
->probeCount
;
723 PERProbe
= wd
->probeSuccessCount
* 100 / pcount
;
730 if (PERProbe
< ((rcCell
->currentRate
< 16)? 80:100))
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;
769 /************************************************************************/
771 /* FUNCTION DESCRIPTION zfRateCtrlRxRssiEvent */
772 /* Rx RSSI event. Calculate RSSI moving average, accelarate */
773 /* rate probing if RSSI variation over threshold. */
776 /* rcCell : rate control cell */
777 /* successRate : success rate */
783 /* Stephen Chen Atheros Communications, INC. 2007.2 */
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;
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)) {
811 u8_t
LowerRate(u8_t Rate
) {
812 if (Rate
> 1) Rate
--;
813 while ((Rate
>= 20) && (Rate
<= 23)) {
819 u8_t
RateMapToRateIndex(u8_t Rate
, struct zsRcCell
* rcCell
) {
821 for (i
=0; i
<rcCell
->operationRateCount
; i
++) {
822 if (Rate
== rcCell
->operationRateSet
[i
]) {
829 void zfRateCtrlAggrSta(zdev_t
* dev
) {
830 u8_t RateIndex
, Rate
;
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;
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
])) {
859 //DbgPrint("Rate improved to %d", Rate);
863 //DbgPrint("Rate decreased to %d", Rate);
866 else if (BAPER
[Rate
] && BAPER
[Rate
]<100) {
867 if (RateCtrlTxMPDU
> 100) {
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
);