// SPDX-License-Identifier: GPL-2.0 /****************************************************************************** * * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * ******************************************************************************/ #include "odm_precomp.h" void odm_NHMCounterStatisticsInit(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; /* PHY parameters initialize for n series */ rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710); /* 0x894[31:16]= 0x2710 Time duration for NHM unit: 4us, 0x2710 =40ms */ /* rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20); 0x894[31:16]= 0x4e20 Time duration for NHM unit: 4us, 0x4e20 =80ms */ rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff); /* 0x890[31:16]= 0xffff th_9, th_10 */ /* rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c); 0x898 = 0xffffff5c th_3, th_2, th_1, th_0 */ rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52); /* 0x898 = 0xffffff52 th_3, th_2, th_1, th_0 */ rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff); /* 0x89c = 0xffffffff th_7, th_6, th_5, th_4 */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff); /* 0xe28[7:0]= 0xff th_8 */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7); /* 0x890[9:8]=3 enable CCX */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1); /* 0xc0c[7]= 1 max power among all RX ants */ } void odm_NHMCounterStatistics(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; /* Get NHM report */ odm_GetNHMCounterStatistics(pDM_Odm); /* Reset NHM counter */ odm_NHMCounterStatisticsReset(pDM_Odm); } void odm_GetNHMCounterStatistics(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; u32 value32 = 0; value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord); pDM_Odm->NHM_cnt_0 = (u8)(value32 & bMaskByte0); } void odm_NHMCounterStatisticsReset(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0); PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1); } void odm_NHMBBInit(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; pDM_Odm->adaptivity_flag = 0; pDM_Odm->tolerance_cnt = 3; pDM_Odm->NHMLastTxOkcnt = 0; pDM_Odm->NHMLastRxOkcnt = 0; pDM_Odm->NHMCurTxOkcnt = 0; pDM_Odm->NHMCurRxOkcnt = 0; } /* */ void odm_NHMBB(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; /* u8 test_status; */ /* struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; */ pDM_Odm->NHMCurTxOkcnt = *(pDM_Odm->pNumTxBytesUnicast)-pDM_Odm->NHMLastTxOkcnt; pDM_Odm->NHMCurRxOkcnt = *(pDM_Odm->pNumRxBytesUnicast)-pDM_Odm->NHMLastRxOkcnt; pDM_Odm->NHMLastTxOkcnt = *(pDM_Odm->pNumTxBytesUnicast); pDM_Odm->NHMLastRxOkcnt = *(pDM_Odm->pNumRxBytesUnicast); if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */ if (pDM_Odm->NHM_cnt_0 >= 190 || pDM_Odm->adaptivity_flag == true) { /* Enable EDCCA since it is possible running Adaptivity testing */ /* test_status = 1; */ pDM_Odm->adaptivity_flag = true; pDM_Odm->tolerance_cnt = 0; } else { if (pDM_Odm->tolerance_cnt < 3) pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1; else pDM_Odm->tolerance_cnt = 4; /* test_status = 5; */ if (pDM_Odm->tolerance_cnt > 3) { /* test_status = 3; */ pDM_Odm->adaptivity_flag = false; } } } else { /* TXadaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200) { /* test_status = 2; */ pDM_Odm->tolerance_cnt = 0; } else { if (pDM_Odm->tolerance_cnt < 3) pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1; else pDM_Odm->tolerance_cnt = 4; /* test_status = 5; */ if (pDM_Odm->tolerance_cnt > 3) { /* test_status = 4; */ pDM_Odm->adaptivity_flag = false; } } } } void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; u32 value32 = 0; u8 cnt, IGI; bool bAdjust = true; s8 TH_L2H_dmc, TH_H2L_dmc; s8 Diff; IGI = 0x50; /* find H2L, L2H lower bound */ ODM_Write_DIG(pDM_Odm, IGI); Diff = IGI_target-(s8)IGI; TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff; if (TH_L2H_dmc > 10) TH_L2H_dmc = 10; TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff; PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); mdelay(5); while (bAdjust) { for (cnt = 0; cnt < 20; cnt++) { value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_RPT_11N, bMaskDWord); if (value32 & BIT30) pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1; else if (value32 & BIT29) pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1; else pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1; } if (pDM_Odm->txEdcca1 > 5) { IGI = IGI-1; TH_L2H_dmc = TH_L2H_dmc + 1; if (TH_L2H_dmc > 10) TH_L2H_dmc = 10; TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff; PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); pDM_Odm->TxHangFlg = true; pDM_Odm->txEdcca1 = 0; pDM_Odm->txEdcca0 = 0; if (TH_L2H_dmc == 10) { bAdjust = false; pDM_Odm->TxHangFlg = false; pDM_Odm->txEdcca1 = 0; pDM_Odm->txEdcca0 = 0; pDM_Odm->H2L_lb = TH_H2L_dmc; pDM_Odm->L2H_lb = TH_L2H_dmc; pDM_Odm->Adaptivity_IGI_upper = IGI; } } else { bAdjust = false; pDM_Odm->TxHangFlg = false; pDM_Odm->txEdcca1 = 0; pDM_Odm->txEdcca0 = 0; pDM_Odm->H2L_lb = TH_H2L_dmc; pDM_Odm->L2H_lb = TH_L2H_dmc; pDM_Odm->Adaptivity_IGI_upper = IGI; } } } void odm_AdaptivityInit(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; if (pDM_Odm->Carrier_Sense_enable == false) pDM_Odm->TH_L2H_ini = 0xf7; /* -7 */ else pDM_Odm->TH_L2H_ini = 0xa; pDM_Odm->AdapEn_RSSI = 20; pDM_Odm->TH_EDCCA_HL_diff = 7; pDM_Odm->IGI_Base = 0x32; pDM_Odm->IGI_target = 0x1c; pDM_Odm->ForceEDCCA = 0; pDM_Odm->NHM_disable = false; pDM_Odm->TxHangFlg = true; pDM_Odm->txEdcca0 = 0; pDM_Odm->txEdcca1 = 0; pDM_Odm->H2L_lb = 0; pDM_Odm->L2H_lb = 0; pDM_Odm->Adaptivity_IGI_upper = 0; odm_NHMBBInit(pDM_Odm); PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); /* stop counting if EDCCA is asserted */ } void odm_Adaptivity(void *pDM_VOID, u8 IGI) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; s8 TH_L2H_dmc, TH_H2L_dmc; s8 Diff, IGI_target; bool EDCCA_State = false; if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) { return; } if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */ IGI_target = pDM_Odm->IGI_Base; else if (*pDM_Odm->pBandWidth == ODM_BW40M) IGI_target = pDM_Odm->IGI_Base + 2; else IGI_target = pDM_Odm->IGI_Base; pDM_Odm->IGI_target = (u8) IGI_target; /* Search pwdB lower bound */ if (pDM_Odm->TxHangFlg == true) { PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208); odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target); } if ((!pDM_Odm->bLinked) || (*pDM_Odm->pChannel > 149)) { /* Band4 doesn't need adaptivity */ PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, 0x7f); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, 0x7f); return; } if (!pDM_Odm->ForceEDCCA) { if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI) EDCCA_State = true; else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5)) EDCCA_State = false; } else EDCCA_State = true; if ( pDM_Odm->bLinked && pDM_Odm->Carrier_Sense_enable == false && pDM_Odm->NHM_disable == false && pDM_Odm->TxHangFlg == false ) odm_NHMBB(pDM_Odm); if (EDCCA_State) { Diff = IGI_target-(s8)IGI; TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff; if (TH_L2H_dmc > 10) TH_L2H_dmc = 10; TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff; /* replace lower bound to prevent EDCCA always equal */ if (TH_H2L_dmc < pDM_Odm->H2L_lb) TH_H2L_dmc = pDM_Odm->H2L_lb; if (TH_L2H_dmc < pDM_Odm->L2H_lb) TH_L2H_dmc = pDM_Odm->L2H_lb; } else { TH_L2H_dmc = 0x7f; TH_H2L_dmc = 0x7f; } PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc); PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc); } void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; if (pDM_DigTable->bStopDIG) { return; } if (pDM_DigTable->CurIGValue != CurrentIGI) { /* 1 Check initial gain by upper bound */ if (!pDM_DigTable->bPSDInProgress) { if (CurrentIGI > pDM_DigTable->rx_gain_range_max) { CurrentIGI = pDM_DigTable->rx_gain_range_max; } } /* 1 Set IGI value */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI); PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI); pDM_DigTable->CurIGValue = CurrentIGI; } } void odm_PauseDIG( void *pDM_VOID, enum ODM_Pause_DIG_TYPE PauseType, u8 IGIValue ) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; static bool bPaused; if ( (pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY) && pDM_Odm->TxHangFlg == true ) { return; } if ( !bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_DIG) || !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) ){ return; } switch (PauseType) { /* 1 Pause DIG */ case ODM_PAUSE_DIG: /* 2 Disable DIG */ ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_DIG)); /* 2 Backup IGI value */ if (!bPaused) { pDM_DigTable->IGIBackup = pDM_DigTable->CurIGValue; bPaused = true; } /* 2 Write new IGI value */ ODM_Write_DIG(pDM_Odm, IGIValue); break; /* 1 Resume DIG */ case ODM_RESUME_DIG: if (bPaused) { /* 2 Write backup IGI value */ ODM_Write_DIG(pDM_Odm, pDM_DigTable->IGIBackup); bPaused = false; /* 2 Enable DIG */ ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_DIG); } break; default: break; } } bool odm_DigAbort(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; /* SupportAbility */ if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) { return true; } /* SupportAbility */ if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) { return true; } /* ScanInProcess */ if (*(pDM_Odm->pbScanInProcess)) { return true; } /* add by Neil Chen to avoid PSD is processing */ if (pDM_Odm->bDMInitialGainEnable == false) { return true; } return false; } void odm_DIGInit(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; pDM_DigTable->bStopDIG = false; pDM_DigTable->bPSDInProgress = false; pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm)); pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW; pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; pDM_DigTable->FALowThresh = DMfalseALARM_THRESH_LOW; pDM_DigTable->FAHighThresh = DMfalseALARM_THRESH_HIGH; pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; pDM_DigTable->PreCCK_CCAThres = 0xFF; pDM_DigTable->CurCCK_CCAThres = 0x83; pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC; pDM_DigTable->LargeFAHit = 0; pDM_DigTable->Recover_cnt = 0; pDM_DigTable->bMediaConnect_0 = false; pDM_DigTable->bMediaConnect_1 = false; /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */ pDM_Odm->bDMInitialGainEnable = true; pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC; pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC; /* To Initi BT30 IGI */ pDM_DigTable->BT30_CurIGI = 0x32; pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; } void odm_DIG(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; /* Common parameters */ struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; bool FirstConnect, FirstDisConnect; u8 DIG_MaxOfMin, DIG_Dynamic_MIN; u8 dm_dig_max, dm_dig_min; u8 CurrentIGI = pDM_DigTable->CurIGValue; u8 offset; u32 dm_FA_thres[3]; u8 Adap_IGI_Upper = 0; u32 TxTp = 0, RxTp = 0; bool bDFSBand = false; bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false; if (odm_DigAbort(pDM_Odm)) return; if (pDM_Odm->adaptivity_flag == true) Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper; /* 1 Update status */ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false); FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true); /* 1 Boundary Decision */ /* 2 For WIN\CE */ dm_dig_max = 0x5A; dm_dig_min = DM_DIG_MIN_NIC; DIG_MaxOfMin = DM_DIG_MAX_AP; /* 1 Adjust boundary by RSSI */ if (pDM_Odm->bLinked && bPerformance) { /* 2 Modify DIG upper bound */ /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */ if (pDM_Odm->bBtLimitedDig == 1) { offset = 10; } else offset = 15; if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max) pDM_DigTable->rx_gain_range_max = dm_dig_max; else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min) pDM_DigTable->rx_gain_range_max = dm_dig_min; else pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset; /* 2 Modify DIG lower bound */ /* if (pDM_Odm->bOneEntryOnly) */ { if (pDM_Odm->RSSI_Min < dm_dig_min) DIG_Dynamic_MIN = dm_dig_min; else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin) DIG_Dynamic_MIN = DIG_MaxOfMin; else DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; } } else { pDM_DigTable->rx_gain_range_max = dm_dig_max; DIG_Dynamic_MIN = dm_dig_min; } /* 1 Force Lower Bound for AntDiv */ if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) { if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { if ( pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV || pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV || pDM_Odm->AntDivType == S0S1_SW_ANTDIV ) { if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin) DIG_Dynamic_MIN = DIG_MaxOfMin; else DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max; } } } /* 1 Modify DIG lower bound, deal with abnormal case */ /* 2 Abnormal false alarm case */ if (FirstDisConnect) { pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; } else pDM_DigTable->rx_gain_range_min = odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI); if (pDM_Odm->bLinked && !FirstConnect) { if ( (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) && pDM_Odm->bsta_state ) { pDM_DigTable->rx_gain_range_min = dm_dig_min; } } /* 2 Abnormal lower bound case */ if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) { pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; } /* 1 False alarm threshold decision */ odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres); /* 1 Adjust initial gain by false alarm */ if (pDM_Odm->bLinked && bPerformance) { if (bFirstTpTarget || (FirstConnect && bPerformance)) { pDM_DigTable->LargeFAHit = 0; if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) { if (CurrentIGI < pDM_Odm->RSSI_Min) CurrentIGI = pDM_Odm->RSSI_Min; } else { if (CurrentIGI < DIG_MaxOfMin) CurrentIGI = DIG_MaxOfMin; } } else { if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2]) CurrentIGI = CurrentIGI + 4; else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1]) CurrentIGI = CurrentIGI + 2; else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0]) CurrentIGI = CurrentIGI - 2; if ( (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) && (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) && (pDM_Odm->bsta_state) ) { CurrentIGI = pDM_DigTable->rx_gain_range_min; } } } else { if (FirstDisConnect || bFirstCoverage) { CurrentIGI = dm_dig_min; } else { if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2]) CurrentIGI = CurrentIGI + 4; else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1]) CurrentIGI = CurrentIGI + 2; else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0]) CurrentIGI = CurrentIGI - 2; } } /* 1 Check initial gain by upper/lower bound */ if (CurrentIGI < pDM_DigTable->rx_gain_range_min) CurrentIGI = pDM_DigTable->rx_gain_range_min; if (CurrentIGI > pDM_DigTable->rx_gain_range_max) CurrentIGI = pDM_DigTable->rx_gain_range_max; /* 1 Force upper bound and lower bound for adaptivity */ if ( pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY && pDM_Odm->adaptivity_flag == true ) { if (CurrentIGI > Adap_IGI_Upper) CurrentIGI = Adap_IGI_Upper; if (pDM_Odm->IGI_LowerBound != 0) { if (CurrentIGI < pDM_Odm->IGI_LowerBound) CurrentIGI = pDM_Odm->IGI_LowerBound; } } /* 1 Update status */ if (pDM_Odm->bBtHsOperation) { if (pDM_Odm->bLinked) { if (pDM_DigTable->BT30_CurIGI > (CurrentIGI)) ODM_Write_DIG(pDM_Odm, CurrentIGI); else ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI); pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; } else { if (pDM_Odm->bLinkInProcess) ODM_Write_DIG(pDM_Odm, 0x1c); else if (pDM_Odm->bBtConnectProcess) ODM_Write_DIG(pDM_Odm, 0x28); else ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ } } else { /* BT is not using */ ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; } } void odm_DIGbyRSSI_LPS(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */ u8 CurrentIGI = pDM_Odm->RSSI_Min; CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG; /* Using FW PS mode to make IGI */ /* Adjust by FA in LPS MODE */ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS) CurrentIGI = CurrentIGI+4; else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS) CurrentIGI = CurrentIGI+2; else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS) CurrentIGI = CurrentIGI-2; /* Lower bound checking */ /* RSSI Lower bound check */ if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC) RSSI_Lower = pDM_Odm->RSSI_Min-10; else RSSI_Lower = DM_DIG_MIN_NIC; /* Upper and Lower Bound checking */ if (CurrentIGI > DM_DIG_MAX_NIC) CurrentIGI = DM_DIG_MAX_NIC; else if (CurrentIGI < RSSI_Lower) CurrentIGI = RSSI_Lower; ODM_Write_DIG(pDM_Odm, CurrentIGI); /* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ } /* 3 ============================================================ */ /* 3 FASLE ALARM CHECK */ /* 3 ============================================================ */ void odm_FalseAlarmCounterStatistics(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; u32 ret_value; if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) return; /* hold ofdm counter */ /* hold page C counter */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); /* hold page D counter */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord ); FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff); FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16); ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord ); FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff); FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16); ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord ); FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff); FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16); ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord ); FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff); FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal + FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail + FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail; { /* hold cck counter */ PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1); PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1); ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0 ); FalseAlmCnt->Cnt_Cck_fail = ret_value; ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3 ); FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8; ret_value = PHY_QueryBBReg( pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord ); FalseAlmCnt->Cnt_CCK_CCA = ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8); } FalseAlmCnt->Cnt_all = ( FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail + FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal + FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail + FalseAlmCnt->Cnt_Cck_fail ); FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; } void odm_FAThresholdCheck( void *pDM_VOID, bool bDFSBand, bool bPerformance, u32 RxTp, u32 TxTp, u32 *dm_FA_thres ) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) { /* For NIC */ dm_FA_thres[0] = DM_DIG_FA_TH0; dm_FA_thres[1] = DM_DIG_FA_TH1; dm_FA_thres[2] = DM_DIG_FA_TH2; } else { dm_FA_thres[0] = 2000; dm_FA_thres[1] = 4000; dm_FA_thres[2] = 5000; } } u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min; if (pFalseAlmCnt->Cnt_all > 10000) { if (pDM_DigTable->LargeFAHit != 3) pDM_DigTable->LargeFAHit++; /* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */ if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { pDM_DigTable->ForbiddenIGI = CurrentIGI; /* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */ pDM_DigTable->LargeFAHit = 1; } if (pDM_DigTable->LargeFAHit >= 3) { if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max) rx_gain_range_min = pDM_DigTable->rx_gain_range_max; else rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2); pDM_DigTable->Recover_cnt = 1800; } } else { if (pDM_DigTable->Recover_cnt != 0) { pDM_DigTable->Recover_cnt--; } else { if (pDM_DigTable->LargeFAHit < 3) { if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ } else { pDM_DigTable->ForbiddenIGI -= 2; rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2); } } else pDM_DigTable->LargeFAHit = 0; } } return rx_gain_range_min; } /* 3 ============================================================ */ /* 3 CCK Packet Detect Threshold */ /* 3 ============================================================ */ void odm_CCKPacketDetectionThresh(void *pDM_VOID) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; u8 CurCCK_CCAThres; if ( !(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) || !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT) ) { return; } if (pDM_Odm->ExtLNA) return; if (pDM_Odm->bLinked) { if (pDM_Odm->RSSI_Min > 25) CurCCK_CCAThres = 0xcd; else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) CurCCK_CCAThres = 0x83; else { if (FalseAlmCnt->Cnt_Cck_fail > 1000) CurCCK_CCAThres = 0x83; else CurCCK_CCAThres = 0x40; } } else { if (FalseAlmCnt->Cnt_Cck_fail > 1000) CurCCK_CCAThres = 0x83; else CurCCK_CCAThres = 0x40; } ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres); } void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres) { struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID; struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; /* modify by Guo.Mingzhi 2012-01-03 */ if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres); pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres; pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres; }