Merge branch 'for-linus' of git://www.jni.nu/cris
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / otus / 80211core / ratectrl.c
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 newRate = zfRateCtrlGetHigherRate(rcCell);
542 if (newRate != rcCell->currentRate)
543 {
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);
551 }
552 }
553 #endif
554
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;
560
561
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);
570 }
571 }
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);
578 }
579 }
580 rcCell->probingTime = wd->tick;
581 }
582
583 if( (wd->tick > 1000)
584 && ((wd->tick - rcCell->lastTime) > 3840) )
585 {
586 if (rcCell->lasttxCount < 70)
587 {
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;
592
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];
597 }
598
599 rcCell->lastTime = wd->tick;
600 rcCell->lasttxCount = 0;
601 }
602
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;
608 }
609
610
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)
629 {
630 zmw_get_wlan_dev(dev);
631
632 zmw_declare_for_critical_section();
633
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;
639 }
640
641 if (!aggRate) {
642 retryRate = (zfRateCtrlRateDiff(rcCell, (u8_t)retryRate)+1)>>1;
643 if (rcCell->currentRate <12) //legacy rate
644 {
645 retryRate*=2;
646 }
647 }
648 rcCell->failCount += retryRate;
649 wd->txFail[rcCell->currentRate] += retryRate;
650
651 //DbgPrint("failCount=%d", rcCell->failCount);
652 if (rcCell->failCount > ZM_MIN_RATE_FAIL_COUNT)
653 {
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] ++;
658 }
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])
662 {
663 /* Lower Tx Rate if PER < THRESHOLD */
664 zfRateCtrlNextLowerRate(dev, rcCell);
665 rcCell->flag |= ZM_RC_TRAINED_BIT;
666
667 // Resolve compatibility problem with Marvell
668 if(rcCell->currentRate == 15)
669 {
670 zmw_leave_critical_section(dev);
671 zfHpSetAggPktNum(dev, 8);
672 zmw_enter_critical_section(dev);
673 }
674
675 wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
676 wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
677
678 wd->probeCount = wd->probeSuccessCount = 0;
679 }
680 }
681
682 #endif
683 return;
684 }
685
686
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)
704 {
705 /* Raise Tx Rate */
706 u16_t i, PERProbe;
707 u16_t pcount;
708 zmw_get_wlan_dev(dev);
709
710 zmw_declare_for_critical_section();
711
712 //DbgPrint("Probing successRate=%d", successRate);
713 /* Find successRate in operationRateSet[] */
714 wd->probeSuccessCount++;
715 if (wd->probeCount < wd->success_probing)
716 {
717 return;
718 }
719
720 pcount = wd->probeCount;
721 if (pcount != 0)
722 {
723 PERProbe = wd->probeSuccessCount * 100 / pcount;
724 }
725 else
726 {
727 PERProbe = 1;
728 }
729
730 if (PERProbe < ((rcCell->currentRate < 16)? 80:100))
731 {
732 return;
733 }
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++)
737 {
738 if (successRate == rcCell->operationRateSet[i])
739 {
740 if (i > rcCell->currentRateIndex)
741 {
742 /* Raise current Tx rate */
743 zm_msg1_tx(ZM_LV_0, "Raise Tx Rate=", successRate);
744 //DbgPrint("Raise Tx Rate=%d", successRate);
745
746 // Resolve compatibility problem with Marvell
747 if((rcCell->currentRate <= 15) && (successRate > 15))
748 {
749 zmw_leave_critical_section(dev);
750 zfHpSetAggPktNum(dev, 16);
751 zmw_enter_critical_section(dev);
752 }
753
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;
761 }
762 }
763 }
764
765 return;
766 }
767
768
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)
787 {
788 /* if delta(rcCell->rxRssi, rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION */
789 if ((rcCell->rxRssi - rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION)
790 {
791 /* Accelerate rate probing via decreaing rcCell->probingTime */
792 rcCell->probingTime -= ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK;
793 }
794
795 /* Update RSSI moving average */
796 rcCell->rxRssi = (((rcCell->rxRssi*7) + rxRssi)+4) >> 3;
797 return;
798 }
799
800
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 ++;
807 }
808 return Rate;
809 }
810
811 u8_t LowerRate(u8_t Rate) {
812 if (Rate > 1) Rate--;
813 while ((Rate >= 20) && (Rate <= 23)) {
814 Rate --;
815 }
816 return Rate;
817 }
818
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;
824 }
825 }
826 return 0;
827 }
828
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);
835
836 RateIndex = wd->sta.oppositeInfo[0].rcCell.currentRateIndex;
837 Rate = wd->sta.oppositeInfo[0].rcCell.operationRateSet[RateIndex];
838
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;
848 }
849 else {
850 return;
851 }
852
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);
860 }
861 else {
862 Rate = LRate;
863 //DbgPrint("Rate decreased to %d", Rate);
864 }
865 }
866 else if (BAPER[Rate] && BAPER[Rate]<100) {
867 if (RateCtrlTxMPDU > 100) {
868 Rate = HRate;
869 //DbgPrint("Rate improved to %d", Rate);
870 }
871 }
872 wd->sta.oppositeInfo[0].rcCell.currentRate = Rate;
873 wd->sta.oppositeInfo[0].rcCell.currentRateIndex = RateMapToRateIndex(Rate, &wd->sta.oppositeInfo[0].rcCell);
874 }
875 #endif