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