• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/otus/80211core/
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
20const 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
41const 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
60const 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
79const 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
91const 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
103const 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
117u32_t TxMPDU[29];
118u32_t BAFail[29];
119u32_t BAPER[29];
120const 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/************************************************************************/
150void 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/************************************************************************/
362u8_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/************************************************************************/
387u8_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/************************************************************************/
420u8_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
449u32_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
456u8_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/************************************************************************/
491u16_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/************************************************************************/
628void 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/************************************************************************/
703void 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/************************************************************************/
786void 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
802u8_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
811u8_t LowerRate(u8_t Rate) {
812    if (Rate > 1) Rate--;
813    while ((Rate >= 20) && (Rate <= 23)) {
814        Rate --;
815    }
816    return Rate;
817}
818
819u8_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
829void 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
876