Commit | Line | Data |
---|---|---|
92b96797 FB |
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 | ||
92b96797 | 36 | #include "tmacro.h" |
92b96797 | 37 | #include "mac.h" |
92b96797 | 38 | #include "80211mgr.h" |
92b96797 | 39 | #include "bssdb.h" |
92b96797 | 40 | #include "datarate.h" |
92b96797 | 41 | #include "card.h" |
92b96797 | 42 | #include "baseband.h" |
92b96797 | 43 | #include "rf.h" |
9d26d60f | 44 | |
84cf5fcb | 45 | /* static int msglevel = MSG_LEVEL_DEBUG; */ |
3cef1a2e | 46 | static int msglevel = MSG_LEVEL_INFO; |
3b138851 | 47 | static const u8 acbyIERate[MAX_RATE] = {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, |
3cef1a2e | 48 | 0x24, 0x30, 0x48, 0x60, 0x6C}; |
92b96797 FB |
49 | |
50 | #define AUTORATE_TXOK_CNT 0x0400 | |
51 | #define AUTORATE_TXFAIL_CNT 0x0064 | |
52 | #define AUTORATE_TIMEOUT 10 | |
53 | ||
8611a29a | 54 | void s_vResetCounter(PKnownNodeDB psNodeDBTable); |
92b96797 | 55 | |
8611a29a | 56 | void s_vResetCounter(PKnownNodeDB psNodeDBTable) |
92b96797 | 57 | { |
3cef1a2e | 58 | u8 ii; |
92b96797 | 59 | |
3cef1a2e NH |
60 | /* clear statistics counter for auto_rate */ |
61 | for (ii = 0; ii <= MAX_RATE; ii++) { | |
62 | psNodeDBTable->uTxOk[ii] = 0; | |
63 | psNodeDBTable->uTxFail[ii] = 0; | |
64 | } | |
92b96797 FB |
65 | } |
66 | ||
92b96797 FB |
67 | /*+ |
68 | * | |
69 | * Routine Description: | |
70 | * Rate fallback Algorithm Implementaion | |
71 | * | |
72 | * Parameters: | |
73 | * In: | |
74 | * pDevice - Pointer to the adapter | |
75 | * psNodeDBTable - Pointer to Node Data Base | |
76 | * Out: | |
77 | * none | |
78 | * | |
79 | * Return Value: none | |
80 | * | |
81 | -*/ | |
82 | #define AUTORATE_TXCNT_THRESHOLD 20 | |
83 | #define AUTORATE_INC_THRESHOLD 30 | |
84 | ||
92b96797 FB |
85 | /*+ |
86 | * | |
87 | * Description: | |
88 | * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE | |
89 | * | |
90 | * Parameters: | |
91 | * In: | |
b902fbfe | 92 | * u8 - Rate value in SuppRates IE or ExtSuppRates IE |
92b96797 FB |
93 | * Out: |
94 | * none | |
95 | * | |
96 | * Return Value: RateIdx | |
97 | * | |
98 | -*/ | |
3cef1a2e | 99 | u16 RATEwGetRateIdx(u8 byRate) |
92b96797 | 100 | { |
3cef1a2e | 101 | u16 ii; |
92b96797 | 102 | |
3cef1a2e NH |
103 | /* erase BasicRate flag */ |
104 | byRate = byRate & 0x7F; | |
92b96797 | 105 | |
3cef1a2e NH |
106 | for (ii = 0; ii < MAX_RATE; ii++) { |
107 | if (acbyIERate[ii] == byRate) | |
108 | return ii; | |
109 | } | |
110 | return 0; | |
92b96797 FB |
111 | } |
112 | ||
113 | /*+ | |
114 | * | |
115 | * Description: | |
116 | * Parsing the highest basic & support rate in rate field of frame. | |
117 | * | |
118 | * Parameters: | |
119 | * In: | |
120 | * pDevice - Pointer to the adapter | |
121 | * pItemRates - Pointer to Rate field defined in 802.11 spec. | |
122 | * pItemExtRates - Pointer to Extended Rate field defined in 802.11 spec. | |
123 | * Out: | |
124 | * pwMaxBasicRate - Maximum Basic Rate | |
125 | * pwMaxSuppRate - Maximum Supported Rate | |
126 | * pbyTopCCKRate - Maximum Basic Rate in CCK mode | |
127 | * pbyTopOFDMRate - Maximum Basic Rate in OFDM mode | |
128 | * | |
129 | * Return Value: none | |
130 | * | |
131 | -*/ | |
92b96797 | 132 | |
45c73bb1 MP |
133 | void RATEvParseMaxRate(struct vnt_private *pDevice, |
134 | PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pItemExtRates, | |
135 | int bUpdateBasicRate, u16 *pwMaxBasicRate, u16 *pwMaxSuppRate, | |
136 | u16 *pwSuppRate, u8 *pbyTopCCKRate, u8 *pbyTopOFDMRate) | |
137 | { | |
3cef1a2e | 138 | int ii; |
45c73bb1 MP |
139 | u8 byHighSuppRate = 0, byRate = 0; |
140 | u16 wOldBasicRate = pDevice->wBasicRate; | |
141 | u32 uRateLen; | |
92b96797 | 142 | |
45c73bb1 MP |
143 | if (pItemRates == NULL) |
144 | return; | |
92b96797 | 145 | |
3cef1a2e NH |
146 | *pwSuppRate = 0; |
147 | uRateLen = pItemRates->len; | |
148 | ||
149 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen); | |
150 | if (pDevice->byBBType != BB_TYPE_11B) { | |
151 | if (uRateLen > WLAN_RATES_MAXLEN) | |
152 | uRateLen = WLAN_RATES_MAXLEN; | |
153 | } else { | |
154 | if (uRateLen > WLAN_RATES_MAXLEN_11B) | |
155 | uRateLen = WLAN_RATES_MAXLEN_11B; | |
156 | } | |
157 | ||
158 | for (ii = 0; ii < uRateLen; ii++) { | |
159 | byRate = (u8)(pItemRates->abyRates[ii]); | |
160 | if (WLAN_MGMT_IS_BASICRATE(byRate) && | |
161 | (bUpdateBasicRate == true)) { | |
162 | /* | |
163 | * add to basic rate set, update pDevice->byTopCCKBasicRate and | |
164 | * pDevice->byTopOFDMBasicRate | |
165 | */ | |
166 | CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate)); | |
167 | DBG_PRT(MSG_LEVEL_DEBUG, | |
168 | KERN_INFO"ParseMaxRate AddBasicRate: %d\n", | |
169 | RATEwGetRateIdx(byRate)); | |
170 | } | |
171 | byRate = (u8)(pItemRates->abyRates[ii]&0x7F); | |
172 | if (byHighSuppRate == 0) | |
173 | byHighSuppRate = byRate; | |
174 | if (byRate > byHighSuppRate) | |
175 | byHighSuppRate = byRate; | |
176 | *pwSuppRate |= (1<<RATEwGetRateIdx(byRate)); | |
177 | } | |
178 | if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) && | |
179 | (pDevice->byBBType != BB_TYPE_11B)) { | |
180 | ||
181 | unsigned int uExtRateLen = pItemExtRates->len; | |
182 | ||
183 | if (uExtRateLen > WLAN_RATES_MAXLEN) | |
184 | uExtRateLen = WLAN_RATES_MAXLEN; | |
185 | ||
186 | for (ii = 0; ii < uExtRateLen; ii++) { | |
187 | byRate = (u8)(pItemExtRates->abyRates[ii]); | |
188 | /* select highest basic rate */ | |
189 | if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) { | |
190 | /* | |
191 | * add to basic rate set, update pDevice->byTopCCKBasicRate and | |
192 | * pDevice->byTopOFDMBasicRate | |
193 | */ | |
194 | CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate)); | |
195 | DBG_PRT(MSG_LEVEL_DEBUG, | |
196 | KERN_INFO"ParseMaxRate AddBasicRate: %d\n", | |
197 | RATEwGetRateIdx(byRate)); | |
198 | } | |
199 | byRate = (u8)(pItemExtRates->abyRates[ii]&0x7F); | |
200 | if (byHighSuppRate == 0) | |
201 | byHighSuppRate = byRate; | |
202 | if (byRate > byHighSuppRate) | |
203 | byHighSuppRate = byRate; | |
204 | *pwSuppRate |= (1<<RATEwGetRateIdx(byRate)); | |
205 | ||
206 | /* DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", | |
207 | * RATEwGetRateIdx(byRate), byRate)); | |
208 | */ | |
209 | } | |
210 | } | |
211 | ||
212 | if ((pDevice->byPacketType == PK_TYPE_11GB) | |
213 | && CARDbIsOFDMinBasicRate((void *)pDevice)) { | |
214 | pDevice->byPacketType = PK_TYPE_11GA; | |
215 | } | |
216 | ||
217 | *pbyTopCCKRate = pDevice->byTopCCKBasicRate; | |
218 | *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate; | |
219 | *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate); | |
220 | if ((pDevice->byPacketType == PK_TYPE_11B) || (pDevice->byPacketType == PK_TYPE_11GB)) | |
221 | *pwMaxBasicRate = pDevice->byTopCCKBasicRate; | |
222 | else | |
223 | *pwMaxBasicRate = pDevice->byTopOFDMBasicRate; | |
224 | if (wOldBasicRate != pDevice->wBasicRate) | |
225 | CARDvSetRSPINF((void *)pDevice, pDevice->byBBType); | |
226 | ||
227 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n"); | |
92b96797 FB |
228 | } |
229 | ||
92b96797 FB |
230 | /*+ |
231 | * | |
232 | * Routine Description: | |
233 | * Rate fallback Algorithm Implementaion | |
234 | * | |
235 | * Parameters: | |
236 | * In: | |
237 | * pDevice - Pointer to the adapter | |
238 | * psNodeDBTable - Pointer to Node Data Base | |
239 | * Out: | |
240 | * none | |
241 | * | |
242 | * Return Value: none | |
243 | * | |
244 | -*/ | |
245 | #define AUTORATE_TXCNT_THRESHOLD 20 | |
246 | #define AUTORATE_INC_THRESHOLD 30 | |
247 | ||
45c73bb1 MP |
248 | void RATEvTxRateFallBack(struct vnt_private *pDevice, |
249 | PKnownNodeDB psNodeDBTable) | |
92b96797 | 250 | { |
45c73bb1 MP |
251 | struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; |
252 | u16 wIdxDownRate = 0; | |
253 | int ii; | |
4e9b5e2b AM |
254 | int bAutoRate[MAX_RATE] = {true, true, true, true, false, false, true, |
255 | true, true, true, true, true}; | |
45c73bb1 MP |
256 | u32 dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, |
257 | 240, 360, 480, 540}; | |
258 | u32 dwThroughput = 0; | |
259 | u16 wIdxUpRate = 0; | |
260 | u32 dwTxDiff = 0; | |
261 | ||
262 | if (pMgmt->eScanState != WMAC_NO_SCANNING) | |
263 | return; /* Don't do Fallback when scanning Channel */ | |
264 | ||
265 | psNodeDBTable->uTimeCount++; | |
92b96797 | 266 | |
3cef1a2e NH |
267 | if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE]) |
268 | dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE]; | |
269 | ||
270 | if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) && | |
271 | (dwTxDiff < AUTORATE_TXFAIL_CNT) && | |
272 | (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) { | |
273 | return; | |
274 | } | |
275 | ||
05aaf1ac | 276 | if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) |
3cef1a2e | 277 | psNodeDBTable->uTimeCount = 0; |
3cef1a2e NH |
278 | |
279 | for (ii = 0; ii < MAX_RATE; ii++) { | |
280 | if (psNodeDBTable->wSuppRate & (0x0001<<ii)) { | |
05aaf1ac | 281 | if (bAutoRate[ii] == true) |
3cef1a2e | 282 | wIdxUpRate = (u16) ii; |
3cef1a2e NH |
283 | } else { |
284 | bAutoRate[ii] = false; | |
285 | } | |
286 | } | |
287 | ||
288 | for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) { | |
289 | if ((psNodeDBTable->uTxOk[ii] != 0) || | |
290 | (psNodeDBTable->uTxFail[ii] != 0)) { | |
291 | dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii]; | |
05aaf1ac | 292 | if (ii < RATE_11M) |
3cef1a2e | 293 | psNodeDBTable->uTxFail[ii] *= 4; |
3cef1a2e NH |
294 | dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]); |
295 | } | |
296 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n", | |
297 | ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]); | |
298 | } | |
299 | dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate]; | |
300 | ||
301 | wIdxDownRate = psNodeDBTable->wTxDataRate; | |
302 | for (ii = psNodeDBTable->wTxDataRate; ii > 0;) { | |
303 | ii--; | |
304 | if ((dwThroughputTbl[ii] > dwThroughput) && | |
305 | (bAutoRate[ii] == true)) { | |
306 | dwThroughput = dwThroughputTbl[ii]; | |
307 | wIdxDownRate = (u16) ii; | |
308 | } | |
309 | } | |
310 | psNodeDBTable->wTxDataRate = wIdxDownRate; | |
311 | if (psNodeDBTable->uTxOk[MAX_RATE]) { | |
312 | if (psNodeDBTable->uTxOk[MAX_RATE] > | |
313 | (psNodeDBTable->uTxFail[MAX_RATE] * 4)) { | |
314 | psNodeDBTable->wTxDataRate = wIdxUpRate; | |
315 | } | |
316 | } else { /* adhoc, if uTxOk(total) == 0 & uTxFail(total) == 0 */ | |
317 | if (psNodeDBTable->uTxFail[MAX_RATE] == 0) | |
318 | psNodeDBTable->wTxDataRate = wIdxUpRate; | |
319 | } | |
320 | ||
321 | if (pDevice->byBBType == BB_TYPE_11A) { | |
322 | if (psNodeDBTable->wTxDataRate <= RATE_11M) | |
323 | psNodeDBTable->wTxDataRate = RATE_6M; | |
324 | } | |
325 | 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]); | |
326 | s_vResetCounter(psNodeDBTable); | |
327 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate); | |
328 | return; | |
92b96797 FB |
329 | } |
330 | ||
331 | /*+ | |
332 | * | |
333 | * Description: | |
334 | * This routine is used to assemble available Rate IE. | |
335 | * | |
336 | * Parameters: | |
337 | * In: | |
338 | * pDevice | |
339 | * Out: | |
340 | * | |
341 | * Return Value: None | |
342 | * | |
343 | -*/ | |
3cef1a2e NH |
344 | u8 RATEuSetIE(PWLAN_IE_SUPP_RATES pSrcRates, PWLAN_IE_SUPP_RATES pDstRates, |
345 | unsigned int uRateLen) | |
92b96797 | 346 | { |
3cef1a2e NH |
347 | unsigned int ii, uu, uRateCnt = 0; |
348 | ||
349 | if ((pSrcRates == NULL) || (pDstRates == NULL)) | |
350 | return 0; | |
351 | ||
352 | if (pSrcRates->len == 0) | |
353 | return 0; | |
354 | ||
355 | for (ii = 0; ii < uRateLen; ii++) { | |
356 | for (uu = 0; uu < pSrcRates->len; uu++) { | |
357 | if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) { | |
358 | pDstRates->abyRates[uRateCnt++] = pSrcRates->abyRates[uu]; | |
359 | break; | |
360 | } | |
361 | } | |
362 | } | |
363 | return (u8)uRateCnt; | |
92b96797 | 364 | } |