Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[sfrench/cifs-2.6.git] / drivers / staging / vt6656 / datarate.c
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * File: datarate.c
20  *
21  * Purpose: Handles the auto fallback & data rates functions
22  *
23  * Author: Lyndon Chen
24  *
25  * Date: July 17, 2002
26  *
27  * Functions:
28  *      RATEvParseMaxRate - Parsing the highest basic & support rate in rate field of frame
29  *      RATEvTxRateFallBack - Rate fallback Algorithm Implementaion
30  *      RATEuSetIE- Set rate IE field.
31  *
32  * Revision History:
33  *
34  */
35
36 #include "ttype.h"
37 #include "tmacro.h"
38 #include "mac.h"
39 #include "80211mgr.h"
40 #include "bssdb.h"
41 #include "datarate.h"
42 #include "card.h"
43 #include "baseband.h"
44 #include "srom.h"
45 #include "rf.h"
46
47 /*---------------------  Static Definitions -------------------------*/
48
49
50
51
52 /*---------------------  Static Classes  ----------------------------*/
53
54
55
56 /*---------------------  Static Variables  --------------------------*/
57 //static int          msglevel                =MSG_LEVEL_DEBUG;
58 static int          msglevel                =MSG_LEVEL_INFO;
59 const BYTE acbyIERate[MAX_RATE] =
60 {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
61
62 #define AUTORATE_TXOK_CNT       0x0400
63 #define AUTORATE_TXFAIL_CNT     0x0064
64 #define AUTORATE_TIMEOUT        10
65
66 /*---------------------  Static Functions  --------------------------*/
67
68 VOID s_vResetCounter (
69     IN PKnownNodeDB psNodeDBTable
70     );
71
72
73
74 VOID
75 s_vResetCounter (
76     IN PKnownNodeDB psNodeDBTable
77     )
78 {
79     BYTE            ii;
80
81     // clear statistic counter for auto_rate
82     for(ii=0;ii<=MAX_RATE;ii++) {
83         psNodeDBTable->uTxOk[ii] = 0;
84         psNodeDBTable->uTxFail[ii] = 0;
85     }
86 }
87
88 /*---------------------  Export Variables  --------------------------*/
89
90
91 /*---------------------  Export Functions  --------------------------*/
92
93
94 /*+
95  *
96  * Description:
97  *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
98  *
99  * Parameters:
100  *  In:
101  *      BYTE    - Rate value in SuppRates IE or ExtSuppRates IE
102  *  Out:
103  *      none
104  *
105  * Return Value: RateIdx
106  *
107 -*/
108 BYTE
109 DATARATEbyGetRateIdx (
110     IN BYTE byRate
111     )
112 {
113     BYTE    ii;
114
115     //Erase basicRate flag.
116     byRate = byRate & 0x7F;//0111 1111
117
118     for (ii = 0; ii < MAX_RATE; ii ++) {
119         if (acbyIERate[ii] == byRate)
120             return ii;
121     }
122     return 0;
123 }
124
125
126
127 /*+
128  *
129  * Routine Description:
130  *      Rate fallback Algorithm Implementaion
131  *
132  * Parameters:
133  *  In:
134  *      pDevice         - Pointer to the adapter
135  *      psNodeDBTable   - Pointer to Node Data Base
136  *  Out:
137  *      none
138  *
139  * Return Value: none
140  *
141 -*/
142 #define AUTORATE_TXCNT_THRESHOLD        20
143 #define AUTORATE_INC_THRESHOLD          30
144
145
146
147
148 /*+
149  *
150  * Description:
151  *      Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
152  *
153  * Parameters:
154  *  In:
155  *      BYTE    - Rate value in SuppRates IE or ExtSuppRates IE
156  *  Out:
157  *      none
158  *
159  * Return Value: RateIdx
160  *
161 -*/
162 WORD
163 RATEwGetRateIdx(
164     IN BYTE byRate
165     )
166 {
167     WORD    ii;
168
169     //Erase basicRate flag.
170     byRate = byRate & 0x7F;//0111 1111
171
172     for (ii = 0; ii < MAX_RATE; ii ++) {
173         if (acbyIERate[ii] == byRate)
174             return ii;
175     }
176     return 0;
177 }
178
179 /*+
180  *
181  * Description:
182  *      Parsing the highest basic & support rate in rate field of frame.
183  *
184  * Parameters:
185  *  In:
186  *      pDevice         - Pointer to the adapter
187  *      pItemRates      - Pointer to Rate field defined in 802.11 spec.
188  *      pItemExtRates      - Pointer to Extended Rate field defined in 802.11 spec.
189  *  Out:
190  *      pwMaxBasicRate  - Maximum Basic Rate
191  *      pwMaxSuppRate   - Maximum Supported Rate
192  *      pbyTopCCKRate   - Maximum Basic Rate in CCK mode
193  *      pbyTopOFDMRate  - Maximum Basic Rate in OFDM mode
194  *
195  * Return Value: none
196  *
197 -*/
198 VOID
199 RATEvParseMaxRate (
200     IN PVOID pDeviceHandler,
201     IN PWLAN_IE_SUPP_RATES pItemRates,
202     IN PWLAN_IE_SUPP_RATES pItemExtRates,
203     IN BOOL bUpdateBasicRate,
204     OUT PWORD pwMaxBasicRate,
205     OUT PWORD pwMaxSuppRate,
206     OUT PWORD pwSuppRate,
207     OUT PBYTE pbyTopCCKRate,
208     OUT PBYTE pbyTopOFDMRate
209     )
210 {
211 PSDevice  pDevice = (PSDevice) pDeviceHandler;
212 UINT  ii;
213 BYTE  byHighSuppRate = 0;
214 BYTE  byRate = 0;
215 WORD  wOldBasicRate = pDevice->wBasicRate;
216 UINT  uRateLen;
217
218
219     if (pItemRates == NULL)
220         return;
221
222     *pwSuppRate = 0;
223     uRateLen = pItemRates->len;
224
225     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen);
226     if (pDevice->byBBType != BB_TYPE_11B) {
227         if (uRateLen > WLAN_RATES_MAXLEN)
228             uRateLen = WLAN_RATES_MAXLEN;
229     } else {
230         if (uRateLen > WLAN_RATES_MAXLEN_11B)
231             uRateLen = WLAN_RATES_MAXLEN_11B;
232     }
233
234     for (ii = 0; ii < uRateLen; ii++) {
235         byRate = (BYTE)(pItemRates->abyRates[ii]);
236         if (WLAN_MGMT_IS_BASICRATE(byRate) &&
237             (bUpdateBasicRate == TRUE))  {
238             // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
239             CARDbAddBasicRate((PVOID)pDevice, RATEwGetRateIdx(byRate));
240             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
241         }
242         byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F);
243         if (byHighSuppRate == 0)
244             byHighSuppRate = byRate;
245         if (byRate > byHighSuppRate)
246             byHighSuppRate = byRate;
247         *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
248     }
249     if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
250         (pDevice->byBBType != BB_TYPE_11B)) {
251
252         UINT  uExtRateLen = pItemExtRates->len;
253
254         if (uExtRateLen > WLAN_RATES_MAXLEN)
255             uExtRateLen = WLAN_RATES_MAXLEN;
256
257         for (ii = 0; ii < uExtRateLen ; ii++) {
258             byRate = (BYTE)(pItemExtRates->abyRates[ii]);
259             // select highest basic rate
260             if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
261                 // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
262                 CARDbAddBasicRate((PVOID)pDevice, RATEwGetRateIdx(byRate));
263                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
264             }
265             byRate = (BYTE)(pItemExtRates->abyRates[ii]&0x7F);
266             if (byHighSuppRate == 0)
267                 byHighSuppRate = byRate;
268             if (byRate > byHighSuppRate)
269                 byHighSuppRate = byRate;
270             *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
271             //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", RATEwGetRateIdx(byRate), byRate));
272         }
273     } //if(pItemExtRates != NULL)
274
275     if ((pDevice->byPacketType == PK_TYPE_11GB) && CARDbIsOFDMinBasicRate((PVOID)pDevice)) {
276         pDevice->byPacketType = PK_TYPE_11GA;
277     }
278
279     *pbyTopCCKRate = pDevice->byTopCCKBasicRate;
280     *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
281     *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate);
282     if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB))
283        *pwMaxBasicRate = pDevice->byTopCCKBasicRate;
284     else
285        *pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
286     if (wOldBasicRate != pDevice->wBasicRate)
287         CARDvSetRSPINF((PVOID)pDevice, pDevice->byBBType);
288
289      DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
290 }
291
292
293 /*+
294  *
295  * Routine Description:
296  *      Rate fallback Algorithm Implementaion
297  *
298  * Parameters:
299  *  In:
300  *      pDevice         - Pointer to the adapter
301  *      psNodeDBTable   - Pointer to Node Data Base
302  *  Out:
303  *      none
304  *
305  * Return Value: none
306  *
307 -*/
308 #define AUTORATE_TXCNT_THRESHOLD        20
309 #define AUTORATE_INC_THRESHOLD          30
310
311 VOID
312 RATEvTxRateFallBack (
313     IN PVOID pDeviceHandler,
314     IN PKnownNodeDB psNodeDBTable
315     )
316 {
317 PSDevice        pDevice = (PSDevice) pDeviceHandler;
318 PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
319 #if 1  //mike fixed old: use packet lose ratio algorithm to control rate
320 WORD            wIdxDownRate = 0;
321 UINT            ii;
322 BOOL            bAutoRate[MAX_RATE]    = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE};
323 DWORD           dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
324 DWORD           dwThroughput = 0;
325 WORD            wIdxUpRate = 0;
326 DWORD           dwTxDiff = 0;
327
328     if (pMgmt->eScanState != WMAC_NO_SCANNING) {
329         // Don't do Fallback when scanning Channel
330         return;
331     }
332     psNodeDBTable->uTimeCount ++;
333
334     if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
335         dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
336
337     if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
338         (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
339         (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
340         return;
341     }
342
343     if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) {
344         psNodeDBTable->uTimeCount = 0;
345     }
346
347     for(ii=0;ii<MAX_RATE;ii++) {
348         if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
349             if (bAutoRate[ii] == TRUE) {
350                 wIdxUpRate = (WORD) ii;
351             }
352         } else {
353             bAutoRate[ii] = FALSE;
354         }
355     }
356
357     for(ii=0;ii<=psNodeDBTable->wTxDataRate;ii++) {
358         if ( (psNodeDBTable->uTxOk[ii] != 0) ||
359              (psNodeDBTable->uTxFail[ii] != 0) ) {
360             dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
361             if (ii < RATE_11M) {
362                 psNodeDBTable->uTxFail[ii] *= 4;
363             }
364             dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
365         }
366         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
367                        ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]);
368     }
369     dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
370
371     wIdxDownRate = psNodeDBTable->wTxDataRate;
372     for(ii = psNodeDBTable->wTxDataRate; ii > 0;) {
373         ii--;
374         if ( (dwThroughputTbl[ii] > dwThroughput) &&
375              (bAutoRate[ii]==TRUE) ) {
376             dwThroughput = dwThroughputTbl[ii];
377             wIdxDownRate = (WORD) ii;
378         }
379     }
380     psNodeDBTable->wTxDataRate = wIdxDownRate;
381     if (psNodeDBTable->uTxOk[MAX_RATE]) {
382         if (psNodeDBTable->uTxOk[MAX_RATE] >
383            (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) {
384             psNodeDBTable->wTxDataRate = wIdxUpRate;
385         }
386     }else { // adhoc, if uTxOk(total) =0 & uTxFail(total) = 0
387         if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
388             psNodeDBTable->wTxDataRate = wIdxUpRate;
389     }
390
391     if (pDevice->byBBType == BB_TYPE_11A) {
392         if (psNodeDBTable->wTxDataRate <= RATE_11M)
393             psNodeDBTable->wTxDataRate = RATE_6M;
394     }
395     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uTxOk[MAX_RATE] %d, uTxFail[MAX_RATE]:%d\n",(int)psNodeDBTable->uTxOk[MAX_RATE], (int)psNodeDBTable->uTxFail[MAX_RATE]);
396     s_vResetCounter(psNodeDBTable);
397     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate);
398     return;
399 #else  //mike fixed new: use differ-signal strength to control rate
400 WORD            wIdxUpRate = 0;
401 BOOL            bAutoRate[MAX_RATE]    = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE};
402 UINT            ii;
403 long  ldBm;
404
405     if (pMgmt->eScanState != WMAC_NO_SCANNING) {
406         // Don't do Fallback when scanning Channel
407         return;
408     }
409
410     for(ii=0;ii<MAX_RATE;ii++) {
411         if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
412             if (bAutoRate[ii] == TRUE) {
413                 wIdxUpRate = (WORD) ii;
414             }
415         } else {
416             bAutoRate[ii] = FALSE;
417         }
418     }
419
420          RFvRSSITodBm(pDevice, (BYTE)(pDevice->uCurrRSSI), &ldBm);
421
422         if (ldBm > -55) {
423                 if ( psNodeDBTable->wSuppRate & (0x0001<<RATE_54M) )  //11a/g
424                 {
425                         psNodeDBTable->wTxDataRate = RATE_54M;
426                 }
427                 else{ //11b
428                         psNodeDBTable->wTxDataRate = RATE_11M;
429                 }
430         }
431
432 if (wIdxUpRate == RATE_54M ) {     //11a/g
433                 if (ldBm > -56 )
434                         psNodeDBTable->wTxDataRate = RATE_54M;
435                 else if (ldBm > -61 )
436                         psNodeDBTable->wTxDataRate = RATE_48M;
437                 else if (ldBm > -66 )
438                         psNodeDBTable->wTxDataRate = RATE_36M;
439                 else if (ldBm > -72 )
440                         psNodeDBTable->wTxDataRate = RATE_24M;
441                 else if (ldBm > -80 )
442                         psNodeDBTable->wTxDataRate = RATE_5M;
443                 else {
444                         psNodeDBTable->wTxDataRate = RATE_1M;
445                         //increasingVGA = TRUE;
446                 }
447         }
448         else {  //11b
449                 if (ldBm > -65 )
450                         psNodeDBTable->wTxDataRate = RATE_11M;
451                 else if (ldBm > -75 )
452                         psNodeDBTable->wTxDataRate = RATE_5M;
453                 else
454                         psNodeDBTable->wTxDataRate = RATE_1M;
455         }
456
457    return;
458 #endif
459 }
460
461 /*+
462  *
463  * Description:
464  *    This routine is used to assemble available Rate IE.
465  *
466  * Parameters:
467  *  In:
468  *    pDevice
469  *  Out:
470  *
471  * Return Value: None
472  *
473 -*/
474 BYTE
475 RATEuSetIE (
476     IN PWLAN_IE_SUPP_RATES pSrcRates,
477     IN PWLAN_IE_SUPP_RATES pDstRates,
478     IN UINT                uRateLen
479     )
480 {
481     UINT ii, uu, uRateCnt = 0;
482
483     if ((pSrcRates == NULL) || (pDstRates == NULL))
484         return 0;
485
486     if (pSrcRates->len == 0)
487         return 0;
488
489     for (ii = 0; ii < uRateLen; ii++) {
490         for (uu = 0; uu < pSrcRates->len; uu++) {
491             if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
492                 pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu];
493                 break;
494             }
495         }
496     }
497     return (BYTE)uRateCnt;
498 }
499