Commit | Line | Data |
---|---|---|
4bd43f50 LR |
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 | { | |
92363b52 JP |
541 | newRate = zfRateCtrlGetHigherRate(rcCell); |
542 | if (newRate != rcCell->currentRate) | |
4bd43f50 LR |
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 |