1 /*
2 * Copyright (c) 2007-2008 Atheros Communications Inc.
3 *
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.
7 *
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.
15 */
16
17 #include "cprecomp.h"
18 #include "ratectrl.h"
19
20 const u32_t zcRateToPhyCtrl[] =
21 {
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
38 };
39
40
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*/
58 };
59
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 */
77 };
78
79 const u16_t zcRate[] =
80 {
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*/
89 };
90
91 const u16_t PERThreshold[] =
92 {
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*/
101 };
102
103 const u16_t FailDiff[] =
104 {
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*/
113 };
114
115
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[] =
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 /* 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)
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) //11g
162 {
163 for (i=0; i<4; i++) //1M 2M 5M 11M
164 {
165 rcCell->operationRateSet[i] = (u8_t)i;
166 }
167 for (i=4; i<10; i++) //12M 18M 24M 36M 48M 54M
168 {
169 rcCell->operationRateSet[i] = 2+i;
170 }
171 rcCell->operationRateCount = 10;
172 rcCell->currentRateIndex = 5; //18M
173 }
174 else if (type == 2) //11ng
175 {
176 if (wd->wlanMode == ZM_MODE_AP) //AP 11ng 40M
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 //STA
187 {
188 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M
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 //11ng 20M
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) //11ng one Tx stream
210 {
211 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M one Tx stream
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 //11ng 20M
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 //if (type == 0) //11b
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) //11na
251 {
252 if (wd->wlanMode == ZM_MODE_AP) //AP 11na 40M
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 //STA
262 {
263 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M
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 //11na 20M
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) //11na one Tx stream
284 {
285 if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M one Tx stream
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 //11ng 20M
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 //if (type == 1) //11a
313 {
314 for (i=0; i<8; i++) //6M 9M 12M 18M 24M 36M 48M 54M
315 {
316 rcCell->operationRateSet[i] = i+4;
317 }
318 rcCell->operationRateCount = 8;
319 rcCell->currentRateIndex = 4; //24M
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 /* 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)
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 /* 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)
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 //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;
401 }
402
403
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)
421 {
422 u16_t i;
423
424 /* Find retryRate in operationRateSet[] */
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 /* TODO : retry rate not in operation rate set */
444 zm_msg1_tx(ZM_LV_0, "Not in operation rate set:", retryRate);
445 return 1;
446
447 }
448
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;
454 }
455
456 u8_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 /* 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)
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) //probe 51, 52, 53 three packets every 50 packets
512 {
513 wd->probeInterval = 0;
514 }
515 newRate=zfRateCtrlGetHigherRate(rcCell);
516 *probing = 1;
517 wd->probeCount++;
518 rcCell->probingTime = wd->tick;
519 }
520 }
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))
525 {
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] ++;
534 }
535
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)))
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 //DbgPrint("Start Probing");
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 //DbgPrint("PER compare force raise rate to %d", highRate);
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 //DbgPrint("UDP Throughput compare force raise rate to %d", highRate);
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 /* FUNCTION DESCRIPTION zfRateCtrlTxFailEvent */
613 /* Tx fail event. Calculate PER and lower Tx rate if under */
614 /* PER under threshold. */
615 /* */
616 /* INPUTS */
617 /* rcCell : rate control cell */
618 /* retryRate : retry rate */
619 /* */
620 /* OUTPUTS */
621 /* None */
622 /* */
623 /* AUTHOR */
624 /* Stephen Chen Atheros Communications, INC. 2007.2 */
625 /* */
626 /************************************************************************/
627 void 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 //DbgPrint("aggRate=%d, retryRate=%d", aggRate, retryRate);
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) //legacy rate
643 {
644 retryRate*=2;
645 }
646 }
647 rcCell->failCount += retryRate;
648 wd->txFail[rcCell->currentRate] += retryRate;
649
650 //DbgPrint("failCount=%d", rcCell->failCount);
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 //zm_msg1_tx(ZM_LV_1, "PER=", per);
659 //DbgPrint("PER=%d, txFail=%d, txMPDU=%d", wd->PER[rcCell->currentRate], wd->txFail[rcCell->currentRate], wd->txMPDU[rcCell->currentRate]);
660 if (wd->PER[rcCell->currentRate] > PERThreshold[rcCell->currentRate])
661 {
662 /* Lower Tx Rate if PER < THRESHOLD */
663 zfRateCtrlNextLowerRate(dev, rcCell);
664 rcCell->flag |= ZM_RC_TRAINED_BIT;
665
666 // Resolve compatibility problem with Marvell
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 /* FUNCTION DESCRIPTION zfRateCtrlTxSuccessEvent */
689 /* Tx success event. Raise Tx rate because rate probing success. */
690 /* */
691 /* INPUTS */
692 /* rcCell : rate control cell */
693 /* successRate : success rate */
694 /* */
695 /* OUTPUTS */
696 /* None */
697 /* */
698 /* AUTHOR */
699 /* Stephen Chen Atheros Communications, INC. 2007.2 */
700 /* */
701 /************************************************************************/
702 void zfRateCtrlTxSuccessEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t successRate)
703 {
704 /* Raise Tx Rate */
705 u16_t i, PERProbe;
706 u16_t pcount;
707 zmw_get_wlan_dev(dev);
708
709 zmw_declare_for_critical_section();
710
711 //DbgPrint("Probing successRate=%d", successRate);
712 /* Find successRate in operationRateSet[] */
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 //DbgPrint("wd->probeCount=%d, wd->probeSuccessCount=%d", wd->probeCount, wd->probeSuccessCount);
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 /* Raise current Tx rate */
742 zm_msg1_tx(ZM_LV_0, "Raise Tx Rate=", successRate);
743 //DbgPrint("Raise Tx Rate=%d", successRate);
744
745 // Resolve compatibility problem with Marvell
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 /* FUNCTION DESCRIPTION zfRateCtrlRxRssiEvent */
771 /* Rx RSSI event. Calculate RSSI moving average, accelarate */
772 /* rate probing if RSSI variation over threshold. */
773 /* */
774 /* INPUTS */
775 /* rcCell : rate control cell */
776 /* successRate : success rate */
777 /* */
778 /* OUTPUTS */
779 /* None */
780 /* */
781 /* AUTHOR */
782 /* Stephen Chen Atheros Communications, INC. 2007.2 */
783 /* */
784 /************************************************************************/
785 void zfRateCtrlRxRssiEvent(struct zsRcCell* rcCell, u16_t rxRssi)
786 {
787 /* if delta(rcCell->rxRssi, rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION */
788 if ((rcCell->rxRssi - rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION)
789 {
790 /* Accelerate rate probing via decreaing rcCell->probingTime */
791 rcCell->probingTime -= ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK;
792 }
793
794 /* Update RSSI moving average */
795 rcCell->rxRssi = (((rcCell->rxRssi*7) + rxRssi)+4) >> 3;
796 return;
797 }
798
799
800 #ifdef ZM_ENABLE_BA_RATECTRL
801 u8_t HigherRate(u8_t Rate) {
802 if (Rate < 28) Rate++; //28=MCS15SG, 27=MCS15, 26=MCS14, 25=MCS13
803 if (Rate > 28) Rate = 28;
804 while ((Rate >= 20) && (Rate <= 23)) {
805 Rate ++;
806 }
807 return Rate;
808 }
809
810 u8_t LowerRate(u8_t Rate) {
811 if (Rate > 1) Rate--;
812 while ((Rate >= 20) && (Rate <= 23)) {
813 Rate --;
814 }
815 return Rate;
816 }
817
818 u8_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
828 void 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]; //PER*1000
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 //DbgPrint("Rate improved to %d", Rate);
859 }
860 else {
861 Rate = LRate;
862 //DbgPrint("Rate decreased to %d", Rate);
863 }
864 }
865 else if (BAPER[Rate] && BAPER[Rate]<100) {
866 if (RateCtrlTxMPDU > 100) {
867 Rate = HRate;
868 //DbgPrint("Rate improved to %d", Rate);
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
|
This page was automatically generated by the
LXR engine.
|