1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 5 * 6 ******************************************************************************/ 7 8 #include "odm_precomp.h" 9 10 #define ADAPTIVITY_VERSION "5.0" 11 12 void odm_NHMCounterStatisticsInit(void *pDM_VOID) 13 { 14 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 15 16 /* PHY parameters initialize for n series */ 17 rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710); /* 0x894[31:16]= 0x2710 Time duration for NHM unit: 4us, 0x2710 =40ms */ 18 /* rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20); 0x894[31:16]= 0x4e20 Time duration for NHM unit: 4us, 0x4e20 =80ms */ 19 rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff); /* 0x890[31:16]= 0xffff th_9, th_10 */ 20 /* rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c); 0x898 = 0xffffff5c th_3, th_2, th_1, th_0 */ 21 rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52); /* 0x898 = 0xffffff52 th_3, th_2, th_1, th_0 */ 22 rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff); /* 0x89c = 0xffffffff th_7, th_6, th_5, th_4 */ 23 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff); /* 0xe28[7:0]= 0xff th_8 */ 24 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7); /* 0x890[9:8]=3 enable CCX */ 25 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1); /* 0xc0c[7]= 1 max power among all RX ants */ 26 } 27 28 void odm_NHMCounterStatistics(void *pDM_VOID) 29 { 30 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 31 32 /* Get NHM report */ 33 odm_GetNHMCounterStatistics(pDM_Odm); 34 35 /* Reset NHM counter */ 36 odm_NHMCounterStatisticsReset(pDM_Odm); 37 } 38 39 void odm_GetNHMCounterStatistics(void *pDM_VOID) 40 { 41 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 42 u32 value32 = 0; 43 44 value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord); 45 46 pDM_Odm->NHM_cnt_0 = (u8)(value32 & bMaskByte0); 47 } 48 49 void odm_NHMCounterStatisticsReset(void *pDM_VOID) 50 { 51 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 52 53 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0); 54 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1); 55 } 56 57 void odm_NHMBBInit(void *pDM_VOID) 58 { 59 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 60 61 pDM_Odm->adaptivity_flag = 0; 62 pDM_Odm->tolerance_cnt = 3; 63 pDM_Odm->NHMLastTxOkcnt = 0; 64 pDM_Odm->NHMLastRxOkcnt = 0; 65 pDM_Odm->NHMCurTxOkcnt = 0; 66 pDM_Odm->NHMCurRxOkcnt = 0; 67 } 68 69 /* */ 70 void odm_NHMBB(void *pDM_VOID) 71 { 72 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 73 /* u8 test_status; */ 74 /* struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; */ 75 76 pDM_Odm->NHMCurTxOkcnt = 77 *(pDM_Odm->pNumTxBytesUnicast)-pDM_Odm->NHMLastTxOkcnt; 78 pDM_Odm->NHMCurRxOkcnt = 79 *(pDM_Odm->pNumRxBytesUnicast)-pDM_Odm->NHMLastRxOkcnt; 80 pDM_Odm->NHMLastTxOkcnt = 81 *(pDM_Odm->pNumTxBytesUnicast); 82 pDM_Odm->NHMLastRxOkcnt = 83 *(pDM_Odm->pNumRxBytesUnicast); 84 85 86 if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */ 87 if (pDM_Odm->NHM_cnt_0 >= 190 || pDM_Odm->adaptivity_flag == true) { 88 /* Enable EDCCA since it is possible running Adaptivity testing */ 89 /* test_status = 1; */ 90 pDM_Odm->adaptivity_flag = true; 91 pDM_Odm->tolerance_cnt = 0; 92 } else { 93 if (pDM_Odm->tolerance_cnt < 3) 94 pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1; 95 else 96 pDM_Odm->tolerance_cnt = 4; 97 /* test_status = 5; */ 98 if (pDM_Odm->tolerance_cnt > 3) { 99 /* test_status = 3; */ 100 pDM_Odm->adaptivity_flag = false; 101 } 102 } 103 } else { /* TX<RX */ 104 if (pDM_Odm->adaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200) { 105 /* test_status = 2; */ 106 pDM_Odm->tolerance_cnt = 0; 107 } else { 108 if (pDM_Odm->tolerance_cnt < 3) 109 pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1; 110 else 111 pDM_Odm->tolerance_cnt = 4; 112 /* test_status = 5; */ 113 if (pDM_Odm->tolerance_cnt > 3) { 114 /* test_status = 4; */ 115 pDM_Odm->adaptivity_flag = false; 116 } 117 } 118 } 119 } 120 121 void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target) 122 { 123 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 124 u32 value32 = 0; 125 u8 cnt, IGI; 126 bool bAdjust = true; 127 s8 TH_L2H_dmc, TH_H2L_dmc; 128 s8 Diff; 129 130 IGI = 0x50; /* find H2L, L2H lower bound */ 131 ODM_Write_DIG(pDM_Odm, IGI); 132 133 134 Diff = IGI_target-(s8)IGI; 135 TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff; 136 if (TH_L2H_dmc > 10) 137 TH_L2H_dmc = 10; 138 TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff; 139 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); 140 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); 141 142 mdelay(5); 143 144 while (bAdjust) { 145 for (cnt = 0; cnt < 20; cnt++) { 146 value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_RPT_11N, bMaskDWord); 147 148 if (value32 & BIT30) 149 pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1; 150 else if (value32 & BIT29) 151 pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1; 152 else 153 pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1; 154 } 155 156 if (pDM_Odm->txEdcca1 > 5) { 157 IGI = IGI-1; 158 TH_L2H_dmc = TH_L2H_dmc + 1; 159 if (TH_L2H_dmc > 10) 160 TH_L2H_dmc = 10; 161 TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff; 162 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); 163 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); 164 165 pDM_Odm->TxHangFlg = true; 166 pDM_Odm->txEdcca1 = 0; 167 pDM_Odm->txEdcca0 = 0; 168 169 if (TH_L2H_dmc == 10) { 170 bAdjust = false; 171 pDM_Odm->TxHangFlg = false; 172 pDM_Odm->txEdcca1 = 0; 173 pDM_Odm->txEdcca0 = 0; 174 pDM_Odm->H2L_lb = TH_H2L_dmc; 175 pDM_Odm->L2H_lb = TH_L2H_dmc; 176 pDM_Odm->Adaptivity_IGI_upper = IGI; 177 } 178 } else { 179 bAdjust = false; 180 pDM_Odm->TxHangFlg = false; 181 pDM_Odm->txEdcca1 = 0; 182 pDM_Odm->txEdcca0 = 0; 183 pDM_Odm->H2L_lb = TH_H2L_dmc; 184 pDM_Odm->L2H_lb = TH_L2H_dmc; 185 pDM_Odm->Adaptivity_IGI_upper = IGI; 186 } 187 } 188 } 189 190 void odm_AdaptivityInit(void *pDM_VOID) 191 { 192 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 193 194 if (pDM_Odm->Carrier_Sense_enable == false) 195 pDM_Odm->TH_L2H_ini = 0xf7; /* -7 */ 196 else 197 pDM_Odm->TH_L2H_ini = 0xa; 198 199 pDM_Odm->AdapEn_RSSI = 20; 200 pDM_Odm->TH_EDCCA_HL_diff = 7; 201 202 pDM_Odm->IGI_Base = 0x32; 203 pDM_Odm->IGI_target = 0x1c; 204 pDM_Odm->ForceEDCCA = 0; 205 pDM_Odm->NHM_disable = false; 206 pDM_Odm->TxHangFlg = true; 207 pDM_Odm->txEdcca0 = 0; 208 pDM_Odm->txEdcca1 = 0; 209 pDM_Odm->H2L_lb = 0; 210 pDM_Odm->L2H_lb = 0; 211 pDM_Odm->Adaptivity_IGI_upper = 0; 212 odm_NHMBBInit(pDM_Odm); 213 214 PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); /* stop counting if EDCCA is asserted */ 215 } 216 217 218 void odm_Adaptivity(void *pDM_VOID, u8 IGI) 219 { 220 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 221 s8 TH_L2H_dmc, TH_H2L_dmc; 222 s8 Diff, IGI_target; 223 bool EDCCA_State = false; 224 225 if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) { 226 return; 227 } 228 229 if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */ 230 IGI_target = pDM_Odm->IGI_Base; 231 else if (*pDM_Odm->pBandWidth == ODM_BW40M) 232 IGI_target = pDM_Odm->IGI_Base + 2; 233 else 234 IGI_target = pDM_Odm->IGI_Base; 235 pDM_Odm->IGI_target = (u8) IGI_target; 236 237 /* Search pwdB lower bound */ 238 if (pDM_Odm->TxHangFlg == true) { 239 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208); 240 odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target); 241 } 242 243 if ((!pDM_Odm->bLinked) || (*pDM_Odm->pChannel > 149)) { /* Band4 doesn't need adaptivity */ 244 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, 0x7f); 245 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, 0x7f); 246 return; 247 } 248 249 if (!pDM_Odm->ForceEDCCA) { 250 if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI) 251 EDCCA_State = true; 252 else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5)) 253 EDCCA_State = false; 254 } else 255 EDCCA_State = true; 256 257 if ( 258 pDM_Odm->bLinked && 259 pDM_Odm->Carrier_Sense_enable == false && 260 pDM_Odm->NHM_disable == false && 261 pDM_Odm->TxHangFlg == false 262 ) 263 odm_NHMBB(pDM_Odm); 264 265 if (EDCCA_State) { 266 Diff = IGI_target-(s8)IGI; 267 TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff; 268 if (TH_L2H_dmc > 10) 269 TH_L2H_dmc = 10; 270 271 TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff; 272 273 /* replace lower bound to prevent EDCCA always equal */ 274 if (TH_H2L_dmc < pDM_Odm->H2L_lb) 275 TH_H2L_dmc = pDM_Odm->H2L_lb; 276 if (TH_L2H_dmc < pDM_Odm->L2H_lb) 277 TH_L2H_dmc = pDM_Odm->L2H_lb; 278 } else { 279 TH_L2H_dmc = 0x7f; 280 TH_H2L_dmc = 0x7f; 281 } 282 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); 283 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); 284 } 285 286 void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI) 287 { 288 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 289 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; 290 291 if (pDM_DigTable->bStopDIG) { 292 return; 293 } 294 295 if (pDM_DigTable->CurIGValue != CurrentIGI) { 296 /* 1 Check initial gain by upper bound */ 297 if (!pDM_DigTable->bPSDInProgress) { 298 if (CurrentIGI > pDM_DigTable->rx_gain_range_max) { 299 CurrentIGI = pDM_DigTable->rx_gain_range_max; 300 } 301 302 } 303 304 /* 1 Set IGI value */ 305 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI); 306 307 if (pDM_Odm->RFType > ODM_1T1R) 308 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI); 309 310 pDM_DigTable->CurIGValue = CurrentIGI; 311 } 312 313 } 314 315 void odm_PauseDIG( 316 void *pDM_VOID, 317 enum ODM_Pause_DIG_TYPE PauseType, 318 u8 IGIValue 319 ) 320 { 321 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 322 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; 323 static bool bPaused; 324 325 if ( 326 (pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY) && 327 pDM_Odm->TxHangFlg == true 328 ) { 329 return; 330 } 331 332 if ( 333 !bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_DIG) || 334 !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) 335 ){ 336 return; 337 } 338 339 switch (PauseType) { 340 /* 1 Pause DIG */ 341 case ODM_PAUSE_DIG: 342 /* 2 Disable DIG */ 343 ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_DIG)); 344 345 /* 2 Backup IGI value */ 346 if (!bPaused) { 347 pDM_DigTable->IGIBackup = pDM_DigTable->CurIGValue; 348 bPaused = true; 349 } 350 351 /* 2 Write new IGI value */ 352 ODM_Write_DIG(pDM_Odm, IGIValue); 353 break; 354 355 /* 1 Resume DIG */ 356 case ODM_RESUME_DIG: 357 if (bPaused) { 358 /* 2 Write backup IGI value */ 359 ODM_Write_DIG(pDM_Odm, pDM_DigTable->IGIBackup); 360 bPaused = false; 361 362 /* 2 Enable DIG */ 363 ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_DIG); 364 } 365 break; 366 367 default: 368 break; 369 } 370 } 371 372 bool odm_DigAbort(void *pDM_VOID) 373 { 374 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 375 376 /* SupportAbility */ 377 if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) { 378 return true; 379 } 380 381 /* SupportAbility */ 382 if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) { 383 return true; 384 } 385 386 /* ScanInProcess */ 387 if (*(pDM_Odm->pbScanInProcess)) { 388 return true; 389 } 390 391 /* add by Neil Chen to avoid PSD is processing */ 392 if (pDM_Odm->bDMInitialGainEnable == false) { 393 return true; 394 } 395 396 return false; 397 } 398 399 void odm_DIGInit(void *pDM_VOID) 400 { 401 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 402 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; 403 404 pDM_DigTable->bStopDIG = false; 405 pDM_DigTable->bPSDInProgress = false; 406 pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm)); 407 pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW; 408 pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; 409 pDM_DigTable->FALowThresh = DMfalseALARM_THRESH_LOW; 410 pDM_DigTable->FAHighThresh = DMfalseALARM_THRESH_HIGH; 411 pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; 412 pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; 413 pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; 414 pDM_DigTable->PreCCK_CCAThres = 0xFF; 415 pDM_DigTable->CurCCK_CCAThres = 0x83; 416 pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC; 417 pDM_DigTable->LargeFAHit = 0; 418 pDM_DigTable->Recover_cnt = 0; 419 pDM_DigTable->bMediaConnect_0 = false; 420 pDM_DigTable->bMediaConnect_1 = false; 421 422 /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */ 423 pDM_Odm->bDMInitialGainEnable = true; 424 425 pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC; 426 pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC; 427 428 /* To Initi BT30 IGI */ 429 pDM_DigTable->BT30_CurIGI = 0x32; 430 431 pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; 432 pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; 433 434 } 435 436 437 void odm_DIG(void *pDM_VOID) 438 { 439 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 440 441 /* Common parameters */ 442 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; 443 struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; 444 bool FirstConnect, FirstDisConnect; 445 u8 DIG_MaxOfMin, DIG_Dynamic_MIN; 446 u8 dm_dig_max, dm_dig_min; 447 u8 CurrentIGI = pDM_DigTable->CurIGValue; 448 u8 offset; 449 u32 dm_FA_thres[3]; 450 u8 Adap_IGI_Upper = 0; 451 u32 TxTp = 0, RxTp = 0; 452 bool bDFSBand = false; 453 bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false; 454 455 if (odm_DigAbort(pDM_Odm)) 456 return; 457 458 if (pDM_Odm->adaptivity_flag == true) 459 Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper; 460 461 462 /* 1 Update status */ 463 DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; 464 FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false); 465 FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true); 466 467 /* 1 Boundary Decision */ 468 /* 2 For WIN\CE */ 469 dm_dig_max = 0x5A; 470 dm_dig_min = DM_DIG_MIN_NIC; 471 DIG_MaxOfMin = DM_DIG_MAX_AP; 472 473 /* 1 Adjust boundary by RSSI */ 474 if (pDM_Odm->bLinked && bPerformance) { 475 /* 2 Modify DIG upper bound */ 476 /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */ 477 if (pDM_Odm->bBtLimitedDig == 1) { 478 offset = 10; 479 } else 480 offset = 15; 481 482 if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max) 483 pDM_DigTable->rx_gain_range_max = dm_dig_max; 484 else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min) 485 pDM_DigTable->rx_gain_range_max = dm_dig_min; 486 else 487 pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset; 488 489 /* 2 Modify DIG lower bound */ 490 /* if (pDM_Odm->bOneEntryOnly) */ 491 { 492 if (pDM_Odm->RSSI_Min < dm_dig_min) 493 DIG_Dynamic_MIN = dm_dig_min; 494 else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin) 495 DIG_Dynamic_MIN = DIG_MaxOfMin; 496 else 497 DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; 498 } 499 } else { 500 pDM_DigTable->rx_gain_range_max = dm_dig_max; 501 DIG_Dynamic_MIN = dm_dig_min; 502 } 503 504 /* 1 Force Lower Bound for AntDiv */ 505 if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) { 506 if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { 507 if ( 508 pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV || 509 pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV || 510 pDM_Odm->AntDivType == S0S1_SW_ANTDIV 511 ) { 512 if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin) 513 DIG_Dynamic_MIN = DIG_MaxOfMin; 514 else 515 DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max; 516 } 517 } 518 } 519 520 /* 1 Modify DIG lower bound, deal with abnormal case */ 521 /* 2 Abnormal false alarm case */ 522 if (FirstDisConnect) { 523 pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; 524 pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; 525 } else 526 pDM_DigTable->rx_gain_range_min = 527 odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI); 528 529 if (pDM_Odm->bLinked && !FirstConnect) { 530 if ( 531 (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) && 532 pDM_Odm->bsta_state 533 ) { 534 pDM_DigTable->rx_gain_range_min = dm_dig_min; 535 } 536 } 537 538 /* 2 Abnormal lower bound case */ 539 if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) { 540 pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; 541 } 542 543 544 /* 1 False alarm threshold decision */ 545 odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres); 546 547 /* 1 Adjust initial gain by false alarm */ 548 if (pDM_Odm->bLinked && bPerformance) { 549 550 if (bFirstTpTarget || (FirstConnect && bPerformance)) { 551 pDM_DigTable->LargeFAHit = 0; 552 553 if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) { 554 if (CurrentIGI < pDM_Odm->RSSI_Min) 555 CurrentIGI = pDM_Odm->RSSI_Min; 556 } else { 557 if (CurrentIGI < DIG_MaxOfMin) 558 CurrentIGI = DIG_MaxOfMin; 559 } 560 561 } else { 562 if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2]) 563 CurrentIGI = CurrentIGI + 4; 564 else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1]) 565 CurrentIGI = CurrentIGI + 2; 566 else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0]) 567 CurrentIGI = CurrentIGI - 2; 568 569 if ( 570 (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) && 571 (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) && 572 (pDM_Odm->bsta_state) 573 ) { 574 CurrentIGI = pDM_DigTable->rx_gain_range_min; 575 } 576 } 577 } else { 578 579 if (FirstDisConnect || bFirstCoverage) { 580 CurrentIGI = dm_dig_min; 581 } else { 582 if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2]) 583 CurrentIGI = CurrentIGI + 4; 584 else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1]) 585 CurrentIGI = CurrentIGI + 2; 586 else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0]) 587 CurrentIGI = CurrentIGI - 2; 588 } 589 } 590 591 /* 1 Check initial gain by upper/lower bound */ 592 if (CurrentIGI < pDM_DigTable->rx_gain_range_min) 593 CurrentIGI = pDM_DigTable->rx_gain_range_min; 594 595 if (CurrentIGI > pDM_DigTable->rx_gain_range_max) 596 CurrentIGI = pDM_DigTable->rx_gain_range_max; 597 598 /* 1 Force upper bound and lower bound for adaptivity */ 599 if ( 600 pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY && 601 pDM_Odm->adaptivity_flag == true 602 ) { 603 if (CurrentIGI > Adap_IGI_Upper) 604 CurrentIGI = Adap_IGI_Upper; 605 606 if (pDM_Odm->IGI_LowerBound != 0) { 607 if (CurrentIGI < pDM_Odm->IGI_LowerBound) 608 CurrentIGI = pDM_Odm->IGI_LowerBound; 609 } 610 } 611 612 613 /* 1 Update status */ 614 if (pDM_Odm->bBtHsOperation) { 615 if (pDM_Odm->bLinked) { 616 if (pDM_DigTable->BT30_CurIGI > (CurrentIGI)) 617 ODM_Write_DIG(pDM_Odm, CurrentIGI); 618 else 619 ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI); 620 621 pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; 622 pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; 623 } else { 624 if (pDM_Odm->bLinkInProcess) 625 ODM_Write_DIG(pDM_Odm, 0x1c); 626 else if (pDM_Odm->bBtConnectProcess) 627 ODM_Write_DIG(pDM_Odm, 0x28); 628 else 629 ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ 630 } 631 } else { /* BT is not using */ 632 ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ 633 pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; 634 pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; 635 } 636 } 637 638 void odm_DIGbyRSSI_LPS(void *pDM_VOID) 639 { 640 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 641 struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; 642 643 u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */ 644 u8 CurrentIGI = pDM_Odm->RSSI_Min; 645 646 CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG; 647 648 /* Using FW PS mode to make IGI */ 649 /* Adjust by FA in LPS MODE */ 650 if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS) 651 CurrentIGI = CurrentIGI+4; 652 else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS) 653 CurrentIGI = CurrentIGI+2; 654 else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS) 655 CurrentIGI = CurrentIGI-2; 656 657 658 /* Lower bound checking */ 659 660 /* RSSI Lower bound check */ 661 if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC) 662 RSSI_Lower = pDM_Odm->RSSI_Min-10; 663 else 664 RSSI_Lower = DM_DIG_MIN_NIC; 665 666 /* Upper and Lower Bound checking */ 667 if (CurrentIGI > DM_DIG_MAX_NIC) 668 CurrentIGI = DM_DIG_MAX_NIC; 669 else if (CurrentIGI < RSSI_Lower) 670 CurrentIGI = RSSI_Lower; 671 672 ODM_Write_DIG(pDM_Odm, CurrentIGI); 673 /* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ 674 } 675 676 /* 3 ============================================================ */ 677 /* 3 FASLE ALARM CHECK */ 678 /* 3 ============================================================ */ 679 680 void odm_FalseAlarmCounterStatistics(void *pDM_VOID) 681 { 682 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 683 struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; 684 u32 ret_value; 685 686 if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) 687 return; 688 689 /* hold ofdm counter */ 690 /* hold page C counter */ 691 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); 692 /* hold page D counter */ 693 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); 694 695 ret_value = PHY_QueryBBReg( 696 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord 697 ); 698 FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff); 699 FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16); 700 701 ret_value = PHY_QueryBBReg( 702 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord 703 ); 704 FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff); 705 FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16); 706 707 ret_value = PHY_QueryBBReg( 708 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord 709 ); 710 FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff); 711 FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16); 712 713 ret_value = PHY_QueryBBReg( 714 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord 715 ); 716 FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff); 717 718 FalseAlmCnt->Cnt_Ofdm_fail = 719 FalseAlmCnt->Cnt_Parity_Fail + 720 FalseAlmCnt->Cnt_Rate_Illegal + 721 FalseAlmCnt->Cnt_Crc8_fail + 722 FalseAlmCnt->Cnt_Mcs_fail + 723 FalseAlmCnt->Cnt_Fast_Fsync + 724 FalseAlmCnt->Cnt_SB_Search_fail; 725 726 { 727 /* hold cck counter */ 728 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1); 729 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1); 730 731 ret_value = PHY_QueryBBReg( 732 pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0 733 ); 734 FalseAlmCnt->Cnt_Cck_fail = ret_value; 735 736 ret_value = PHY_QueryBBReg( 737 pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3 738 ); 739 FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8; 740 741 ret_value = PHY_QueryBBReg( 742 pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord 743 ); 744 FalseAlmCnt->Cnt_CCK_CCA = 745 ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8); 746 } 747 748 FalseAlmCnt->Cnt_all = ( 749 FalseAlmCnt->Cnt_Fast_Fsync + 750 FalseAlmCnt->Cnt_SB_Search_fail + 751 FalseAlmCnt->Cnt_Parity_Fail + 752 FalseAlmCnt->Cnt_Rate_Illegal + 753 FalseAlmCnt->Cnt_Crc8_fail + 754 FalseAlmCnt->Cnt_Mcs_fail + 755 FalseAlmCnt->Cnt_Cck_fail 756 ); 757 758 FalseAlmCnt->Cnt_CCA_all = 759 FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; 760 } 761 762 763 void odm_FAThresholdCheck( 764 void *pDM_VOID, 765 bool bDFSBand, 766 bool bPerformance, 767 u32 RxTp, 768 u32 TxTp, 769 u32 *dm_FA_thres 770 ) 771 { 772 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 773 774 if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) { 775 /* For NIC */ 776 dm_FA_thres[0] = DM_DIG_FA_TH0; 777 dm_FA_thres[1] = DM_DIG_FA_TH1; 778 dm_FA_thres[2] = DM_DIG_FA_TH2; 779 } else { 780 dm_FA_thres[0] = 2000; 781 dm_FA_thres[1] = 4000; 782 dm_FA_thres[2] = 5000; 783 } 784 } 785 786 u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI) 787 { 788 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 789 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; 790 struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; 791 u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min; 792 793 if (pFalseAlmCnt->Cnt_all > 10000) { 794 if (pDM_DigTable->LargeFAHit != 3) 795 pDM_DigTable->LargeFAHit++; 796 797 /* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */ 798 if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { 799 pDM_DigTable->ForbiddenIGI = CurrentIGI; 800 /* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */ 801 pDM_DigTable->LargeFAHit = 1; 802 } 803 804 if (pDM_DigTable->LargeFAHit >= 3) { 805 if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max) 806 rx_gain_range_min = pDM_DigTable->rx_gain_range_max; 807 else 808 rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2); 809 pDM_DigTable->Recover_cnt = 1800; 810 } 811 } else { 812 if (pDM_DigTable->Recover_cnt != 0) { 813 pDM_DigTable->Recover_cnt--; 814 } else { 815 if (pDM_DigTable->LargeFAHit < 3) { 816 if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */ 817 pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ 818 rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ 819 } else { 820 pDM_DigTable->ForbiddenIGI -= 2; 821 rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2); 822 } 823 } else 824 pDM_DigTable->LargeFAHit = 0; 825 } 826 } 827 828 return rx_gain_range_min; 829 830 } 831 832 /* 3 ============================================================ */ 833 /* 3 CCK Packet Detect Threshold */ 834 /* 3 ============================================================ */ 835 836 void odm_CCKPacketDetectionThresh(void *pDM_VOID) 837 { 838 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 839 struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; 840 u8 CurCCK_CCAThres; 841 842 843 if ( 844 !(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) || 845 !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT) 846 ) { 847 return; 848 } 849 850 if (pDM_Odm->ExtLNA) 851 return; 852 853 if (pDM_Odm->bLinked) { 854 if (pDM_Odm->RSSI_Min > 25) 855 CurCCK_CCAThres = 0xcd; 856 else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) 857 CurCCK_CCAThres = 0x83; 858 else { 859 if (FalseAlmCnt->Cnt_Cck_fail > 1000) 860 CurCCK_CCAThres = 0x83; 861 else 862 CurCCK_CCAThres = 0x40; 863 } 864 } else { 865 if (FalseAlmCnt->Cnt_Cck_fail > 1000) 866 CurCCK_CCAThres = 0x83; 867 else 868 CurCCK_CCAThres = 0x40; 869 } 870 871 ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres); 872 } 873 874 void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres) 875 { 876 struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; 877 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; 878 879 /* modify by Guo.Mingzhi 2012-01-03 */ 880 if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) 881 rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres); 882 883 pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres; 884 pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres; 885 } 886