Staging: otus: 80211core: Hoist assign from if
[safe/jmp/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             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