Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux-2.6] / 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             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