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