odm.c (28129B)
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2007 - 2011 Realtek Corporation. */ 3 4#include "../include/drv_types.h" 5 6/* avoid to warn in FreeBSD ==> To DO modify */ 7static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { 8 /* UL DL */ 9 {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */ 10 {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */ 11 {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */ 12 {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */ 13 {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */ 14 {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */ 15 {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */ 16 {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */ 17 {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP=> 92U AP */ 18 {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */ 19}; 20 21/* Global var */ 22u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D] = { 23 0x7f8001fe, /* 0, +6.0dB */ 24 0x788001e2, /* 1, +5.5dB */ 25 0x71c001c7, /* 2, +5.0dB */ 26 0x6b8001ae, /* 3, +4.5dB */ 27 0x65400195, /* 4, +4.0dB */ 28 0x5fc0017f, /* 5, +3.5dB */ 29 0x5a400169, /* 6, +3.0dB */ 30 0x55400155, /* 7, +2.5dB */ 31 0x50800142, /* 8, +2.0dB */ 32 0x4c000130, /* 9, +1.5dB */ 33 0x47c0011f, /* 10, +1.0dB */ 34 0x43c0010f, /* 11, +0.5dB */ 35 0x40000100, /* 12, +0dB */ 36 0x3c8000f2, /* 13, -0.5dB */ 37 0x390000e4, /* 14, -1.0dB */ 38 0x35c000d7, /* 15, -1.5dB */ 39 0x32c000cb, /* 16, -2.0dB */ 40 0x300000c0, /* 17, -2.5dB */ 41 0x2d4000b5, /* 18, -3.0dB */ 42 0x2ac000ab, /* 19, -3.5dB */ 43 0x288000a2, /* 20, -4.0dB */ 44 0x26000098, /* 21, -4.5dB */ 45 0x24000090, /* 22, -5.0dB */ 46 0x22000088, /* 23, -5.5dB */ 47 0x20000080, /* 24, -6.0dB */ 48 0x1e400079, /* 25, -6.5dB */ 49 0x1c800072, /* 26, -7.0dB */ 50 0x1b00006c, /* 27. -7.5dB */ 51 0x19800066, /* 28, -8.0dB */ 52 0x18000060, /* 29, -8.5dB */ 53 0x16c0005b, /* 30, -9.0dB */ 54 0x15800056, /* 31, -9.5dB */ 55 0x14400051, /* 32, -10.0dB */ 56 0x1300004c, /* 33, -10.5dB */ 57 0x12000048, /* 34, -11.0dB */ 58 0x11000044, /* 35, -11.5dB */ 59 0x10000040, /* 36, -12.0dB */ 60 0x0f00003c,/* 37, -12.5dB */ 61 0x0e400039,/* 38, -13.0dB */ 62 0x0d800036,/* 39, -13.5dB */ 63 0x0cc00033,/* 40, -14.0dB */ 64 0x0c000030,/* 41, -14.5dB */ 65 0x0b40002d,/* 42, -15.0dB */ 66}; 67 68u8 cck_swing_table[CCK_TABLE_SIZE][8] = { 69 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ 70 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ 71 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ 72 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ 73 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ 74 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ 75 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ 76 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ 77 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ 78 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ 79 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ 80 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ 81 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ 82 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ 83 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ 84 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ 85 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ 86 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ 87 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ 88 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ 89 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ 90 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ 91 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ 92 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ 93 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ 94 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ 95 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ 96 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ 97 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ 98 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ 99 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ 100 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ 101 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ 102}; 103 104#define RxDefaultAnt1 0x65a9 105#define RxDefaultAnt2 0x569a 106 107static void odm_DIGInit(struct odm_dm_struct *pDM_Odm) 108{ 109 struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; 110 struct adapter *adapter = pDM_Odm->Adapter; 111 112 pDM_DigTable->CurIGValue = (u8)rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N); 113 pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; 114 pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; 115 pDM_DigTable->CurCCK_CCAThres = 0x83; 116 pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC; 117 pDM_DigTable->LargeFAHit = 0; 118 pDM_DigTable->Recover_cnt = 0; 119 pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC; 120 pDM_DigTable->bMediaConnect_0 = false; 121 122 /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */ 123 pDM_Odm->bDMInitialGainEnable = true; 124} 125 126static void odm_DIG(struct odm_dm_struct *pDM_Odm) 127{ 128 struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; 129 struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; 130 u8 DIG_Dynamic_MIN; 131 u8 DIG_MaxOfMin; 132 bool FirstConnect, FirstDisConnect; 133 u8 dm_dig_max, dm_dig_min; 134 u8 CurrentIGI = pDM_DigTable->CurIGValue; 135 136 if (*pDM_Odm->pbScanInProcess) 137 return; 138 139 /* add by Neil Chen to avoid PSD is processing */ 140 if (!pDM_Odm->bDMInitialGainEnable) 141 return; 142 143 DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0; 144 FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0); 145 FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0); 146 147 /* 1 Boundary Decision */ 148 dm_dig_max = DM_DIG_MAX_NIC; 149 dm_dig_min = DM_DIG_MIN_NIC; 150 DIG_MaxOfMin = DM_DIG_MAX_AP; 151 152 if (pDM_Odm->bLinked) { 153 /* 2 8723A Series, offset need to be 10 */ 154 /* 2 Modify DIG upper bound */ 155 if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max) 156 pDM_DigTable->rx_gain_range_max = dm_dig_max; 157 else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min) 158 pDM_DigTable->rx_gain_range_max = dm_dig_min; 159 else 160 pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20; 161 /* 2 Modify DIG lower bound */ 162 if (pDM_Odm->bOneEntryOnly) { 163 if (pDM_Odm->RSSI_Min < dm_dig_min) 164 DIG_Dynamic_MIN = dm_dig_min; 165 else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin) 166 DIG_Dynamic_MIN = DIG_MaxOfMin; 167 else 168 DIG_Dynamic_MIN = pDM_Odm->RSSI_Min; 169 } else if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) { 170 /* 1 Lower Bound for 88E AntDiv */ 171 if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) 172 DIG_Dynamic_MIN = (u8)pDM_DigTable->AntDiv_RSSI_max; 173 } else { 174 DIG_Dynamic_MIN = dm_dig_min; 175 } 176 } else { 177 pDM_DigTable->rx_gain_range_max = dm_dig_max; 178 DIG_Dynamic_MIN = dm_dig_min; 179 } 180 181 /* 1 Modify DIG lower bound, deal with abnormally large false alarm */ 182 if (pFalseAlmCnt->Cnt_all > 10000) { 183 if (pDM_DigTable->LargeFAHit != 3) 184 pDM_DigTable->LargeFAHit++; 185 if (pDM_DigTable->ForbiddenIGI < CurrentIGI) { 186 pDM_DigTable->ForbiddenIGI = CurrentIGI; 187 pDM_DigTable->LargeFAHit = 1; 188 } 189 190 if (pDM_DigTable->LargeFAHit >= 3) { 191 if ((pDM_DigTable->ForbiddenIGI + 1) > pDM_DigTable->rx_gain_range_max) 192 pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max; 193 else 194 pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); 195 pDM_DigTable->Recover_cnt = 3600; /* 3600=2hr */ 196 } 197 198 } else { 199 /* Recovery mechanism for IGI lower bound */ 200 if (pDM_DigTable->Recover_cnt != 0) { 201 pDM_DigTable->Recover_cnt--; 202 } else { 203 if (pDM_DigTable->LargeFAHit < 3) { 204 if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */ 205 pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ 206 pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */ 207 } else { 208 pDM_DigTable->ForbiddenIGI--; 209 pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1); 210 } 211 } else { 212 pDM_DigTable->LargeFAHit = 0; 213 } 214 } 215 } 216 217 /* 1 Adjust initial gain by false alarm */ 218 if (pDM_Odm->bLinked) { 219 if (FirstConnect) { 220 CurrentIGI = pDM_Odm->RSSI_Min; 221 } else { 222 if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2) 223 CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ 224 else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1) 225 CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ 226 else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0) 227 CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */ 228 } 229 } else { 230 if (FirstDisConnect) { 231 CurrentIGI = pDM_DigTable->rx_gain_range_min; 232 } else { 233 /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */ 234 if (pFalseAlmCnt->Cnt_all > 10000) 235 CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */ 236 else if (pFalseAlmCnt->Cnt_all > 8000) 237 CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */ 238 else if (pFalseAlmCnt->Cnt_all < 500) 239 CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */ 240 } 241 } 242 /* 1 Check initial gain by upper/lower bound */ 243 if (CurrentIGI > pDM_DigTable->rx_gain_range_max) 244 CurrentIGI = pDM_DigTable->rx_gain_range_max; 245 if (CurrentIGI < pDM_DigTable->rx_gain_range_min) 246 CurrentIGI = pDM_DigTable->rx_gain_range_min; 247 248 /* 2 High power RSSI threshold */ 249 250 ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */ 251 pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked; 252 pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN; 253} 254 255static void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm) 256{ 257 struct adapter *adapter = pDM_Odm->Adapter; 258 259 pDM_Odm->bCckHighPower = (bool)rtl8188e_PHY_QueryBBReg(adapter, 0x824, BIT(9)); 260 pDM_Odm->RFPathRxEnable = (u8)rtl8188e_PHY_QueryBBReg(adapter, 0xc04, 0x0F); 261} 262 263static void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm) 264{ 265 u8 EntryCnt = 0; 266 u8 i; 267 struct sta_info *pEntry; 268 269 if (*pDM_Odm->pBandWidth == HT_CHANNEL_WIDTH_40) { 270 if (*pDM_Odm->pSecChOffset == 1) 271 pDM_Odm->ControlChannel = *pDM_Odm->pChannel - 2; 272 else if (*pDM_Odm->pSecChOffset == 2) 273 pDM_Odm->ControlChannel = *pDM_Odm->pChannel + 2; 274 } else { 275 pDM_Odm->ControlChannel = *pDM_Odm->pChannel; 276 } 277 278 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { 279 pEntry = pDM_Odm->pODM_StaInfo[i]; 280 if (IS_STA_VALID(pEntry)) 281 EntryCnt++; 282 } 283 if (EntryCnt == 1) 284 pDM_Odm->bOneEntryOnly = true; 285 else 286 pDM_Odm->bOneEntryOnly = false; 287} 288 289static void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm) 290{ 291 struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive; 292 293 pOdmRA->RATRState = DM_RATR_STA_INIT; 294 pOdmRA->HighRSSIThresh = 50; 295 pOdmRA->LowRSSIThresh = 20; 296} 297 298static void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm) 299{ 300 u8 i; 301 struct adapter *pAdapter = pDM_Odm->Adapter; 302 303 if (pAdapter->bDriverStopped) 304 return; 305 306 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { 307 struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i]; 308 309 if (IS_STA_VALID(pstat)) { 310 if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) 311 rtw_hal_update_ra_mask(pAdapter, i, pstat->rssi_level); 312 } 313 } 314} 315 316static void odm_DynamicBBPowerSavingInit(struct odm_dm_struct *pDM_Odm) 317{ 318 struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable; 319 320 pDM_PSTable->pre_rf_state = RF_MAX; 321 pDM_PSTable->cur_rf_state = RF_MAX; 322 pDM_PSTable->initialize = 0; 323} 324 325static void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm) 326{ 327 u32 ret_value; 328 struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; 329 struct adapter *adapter = pDM_Odm->Adapter; 330 331 /* hold ofdm counter */ 332 rtl8188e_PHY_SetBBReg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */ 333 rtl8188e_PHY_SetBBReg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */ 334 335 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord); 336 FalseAlmCnt->Cnt_Fast_Fsync = (ret_value & 0xffff); 337 FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value & 0xffff0000) >> 16); 338 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord); 339 FalseAlmCnt->Cnt_OFDM_CCA = (ret_value & 0xffff); 340 FalseAlmCnt->Cnt_Parity_Fail = ((ret_value & 0xffff0000) >> 16); 341 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord); 342 FalseAlmCnt->Cnt_Rate_Illegal = (ret_value & 0xffff); 343 FalseAlmCnt->Cnt_Crc8_fail = ((ret_value & 0xffff0000) >> 16); 344 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord); 345 FalseAlmCnt->Cnt_Mcs_fail = (ret_value & 0xffff); 346 347 FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal + 348 FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail + 349 FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail; 350 351 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_SC_CNT_11N, bMaskDWord); 352 FalseAlmCnt->Cnt_BW_LSC = (ret_value & 0xffff); 353 FalseAlmCnt->Cnt_BW_USC = ((ret_value & 0xffff0000) >> 16); 354 355 /* hold cck counter */ 356 rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(12), 1); 357 rtl8188e_PHY_SetBBReg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(14), 1); 358 359 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0); 360 FalseAlmCnt->Cnt_Cck_fail = ret_value; 361 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3); 362 FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff) << 8; 363 364 ret_value = rtl8188e_PHY_QueryBBReg(adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord); 365 FalseAlmCnt->Cnt_CCK_CCA = ((ret_value & 0xFF) << 8) | ((ret_value & 0xFF00) >> 8); 366 367 FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync + 368 FalseAlmCnt->Cnt_SB_Search_fail + 369 FalseAlmCnt->Cnt_Parity_Fail + 370 FalseAlmCnt->Cnt_Rate_Illegal + 371 FalseAlmCnt->Cnt_Crc8_fail + 372 FalseAlmCnt->Cnt_Mcs_fail + 373 FalseAlmCnt->Cnt_Cck_fail); 374 375 FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA; 376} 377 378static void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm) 379{ 380 u8 CurCCK_CCAThres; 381 struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt; 382 383 if (pDM_Odm->bLinked) { 384 if (pDM_Odm->RSSI_Min > 25) { 385 CurCCK_CCAThres = 0xcd; 386 } else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) { 387 CurCCK_CCAThres = 0x83; 388 } else { 389 if (FalseAlmCnt->Cnt_Cck_fail > 1000) 390 CurCCK_CCAThres = 0x83; 391 else 392 CurCCK_CCAThres = 0x40; 393 } 394 } else { 395 if (FalseAlmCnt->Cnt_Cck_fail > 1000) 396 CurCCK_CCAThres = 0x83; 397 else 398 CurCCK_CCAThres = 0x40; 399 } 400 ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres); 401} 402 403static void FindMinimumRSSI(struct adapter *pAdapter) 404{ 405 struct hal_data_8188e *pHalData = &pAdapter->haldata; 406 struct dm_priv *pdmpriv = &pHalData->dmpriv; 407 struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv; 408 409 /* 1 1.Determine the minimum RSSI */ 410 if (!check_fwstate(pmlmepriv, _FW_LINKED) && 411 pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0) 412 pdmpriv->MinUndecoratedPWDBForDM = 0; 413 414 pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; 415} 416 417static void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm) 418{ 419 struct adapter *Adapter = pDM_Odm->Adapter; 420 struct hal_data_8188e *pHalData = &Adapter->haldata; 421 struct dm_priv *pdmpriv = &pHalData->dmpriv; 422 int i; 423 int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; 424 u8 sta_cnt = 0; 425 u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ 426 struct sta_info *psta; 427 428 if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR)) 429 return; 430 431 if (!check_fwstate(&Adapter->mlmepriv, _FW_LINKED)) 432 return; 433 434 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { 435 psta = pDM_Odm->pODM_StaInfo[i]; 436 if (IS_STA_VALID(psta) && 437 (psta->state & WIFI_ASOC_STATE) && 438 !is_broadcast_ether_addr(psta->hwaddr) && 439 memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) { 440 if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB) 441 tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB; 442 443 if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB) 444 tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB; 445 if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1)) 446 PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB << 16)); 447 } 448 } 449 450 for (i = 0; i < sta_cnt; i++) { 451 if (PWDB_rssi[i] != (0)) { 452 if (pHalData->fw_ractrl) { 453 /* Report every sta's RSSI to FW */ 454 } else { 455 ODM_RA_SetRSSI_8188E( 456 &pHalData->odmpriv, (PWDB_rssi[i] & 0xFF), (u8)((PWDB_rssi[i] >> 16) & 0xFF)); 457 } 458 } 459 } 460 461 if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */ 462 pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB; 463 else 464 pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0; 465 466 FindMinimumRSSI(Adapter); 467 pHalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM; 468} 469 470static void odm_TXPowerTrackingThermalMeterInit(struct odm_dm_struct *pDM_Odm) 471{ 472 pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true; 473} 474 475static void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm) 476{ 477 if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) 478 return; 479 480 ODM_AntennaDiversityInit_88E(pDM_Odm); 481} 482 483static void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm) 484{ 485 if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) 486 return; 487 488 ODM_AntennaDiversity_88E(pDM_Odm); 489} 490 491static void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm) 492{ 493 struct adapter *Adapter = pDM_Odm->Adapter; 494 pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; 495 pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false; 496 Adapter->recvpriv.bIsAnyNonBEPkts = false; 497} 498 499static void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm) 500{ 501 struct adapter *Adapter = pDM_Odm->Adapter; 502 u32 trafficIndex; 503 u32 edca_param; 504 u64 cur_tx_bytes = 0; 505 u64 cur_rx_bytes = 0; 506 u8 bbtchange = false; 507 struct hal_data_8188e *pHalData = &Adapter->haldata; 508 struct xmit_priv *pxmitpriv = &Adapter->xmitpriv; 509 struct recv_priv *precvpriv = &Adapter->recvpriv; 510 struct registry_priv *pregpriv = &Adapter->registrypriv; 511 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; 512 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 513 514 if (pregpriv->wifi_spec == 1) 515 goto dm_CheckEdcaTurbo_EXIT; 516 517 if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX) 518 goto dm_CheckEdcaTurbo_EXIT; 519 520 /* Check if the status needs to be changed. */ 521 if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) { 522 cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes; 523 cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes; 524 525 /* traffic, TX or RX */ 526 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) || 527 (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) { 528 if (cur_tx_bytes > (cur_rx_bytes << 2)) { 529 /* Uplink TP is present. */ 530 trafficIndex = UP_LINK; 531 } else { 532 /* Balance TP is present. */ 533 trafficIndex = DOWN_LINK; 534 } 535 } else { 536 if (cur_rx_bytes > (cur_tx_bytes << 2)) { 537 /* Downlink TP is present. */ 538 trafficIndex = DOWN_LINK; 539 } else { 540 /* Balance TP is present. */ 541 trafficIndex = UP_LINK; 542 } 543 } 544 545 if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) { 546 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)) 547 edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex]; 548 else 549 edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex]; 550 551 rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param); 552 553 pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex; 554 } 555 556 pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true; 557 } else { 558 /* Turn Off EDCA turbo here. */ 559 /* Restore original EDCA according to the declaration of AP. */ 560 if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) { 561 rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE); 562 pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; 563 } 564 } 565 566dm_CheckEdcaTurbo_EXIT: 567 /* Set variables for next time. */ 568 precvpriv->bIsAnyNonBEPkts = false; 569 pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes; 570 precvpriv->last_rx_bytes = precvpriv->rx_bytes; 571} 572 573/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */ 574void ODM_DMInit(struct odm_dm_struct *pDM_Odm) 575{ 576 /* 2012.05.03 Luke: For all IC series */ 577 odm_CommonInfoSelfInit(pDM_Odm); 578 odm_DIGInit(pDM_Odm); 579 odm_RateAdaptiveMaskInit(pDM_Odm); 580 581 odm_DynamicBBPowerSavingInit(pDM_Odm); 582 odm_TXPowerTrackingThermalMeterInit(pDM_Odm); 583 ODM_EdcaTurboInit(pDM_Odm); 584 ODM_RAInfo_Init_all(pDM_Odm); 585 if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) || 586 (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) || 587 (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV)) 588 odm_InitHybridAntDiv(pDM_Odm); 589} 590 591/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */ 592/* You can not add any dummy function here, be care, you can only use DM structure */ 593/* to perform any new ODM_DM. */ 594void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm) 595{ 596 /* 2012.05.03 Luke: For all IC series */ 597 odm_CommonInfoSelfUpdate(pDM_Odm); 598 odm_FalseAlarmCounterStatistics(pDM_Odm); 599 odm_RSSIMonitorCheck(pDM_Odm); 600 601 odm_DIG(pDM_Odm); 602 odm_CCKPacketDetectionThresh(pDM_Odm); 603 604 if (*pDM_Odm->pbPowerSaving) 605 return; 606 607 odm_RefreshRateAdaptiveMask(pDM_Odm); 608 609 if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) || 610 (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) || 611 (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV)) 612 odm_HwAntDiv(pDM_Odm); 613 614 ODM_TXPowerTrackingCheck(pDM_Odm); 615 odm_EdcaTurboCheck(pDM_Odm); 616} 617 618/* Init /.. Fixed HW value. Only init time. */ 619void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u32 Value) 620{ 621 /* This section is used for init value */ 622 switch (CmnInfo) { 623 /* Fixed ODM value. */ 624 case ODM_CMNINFO_MP_TEST_CHIP: 625 pDM_Odm->bIsMPChip = (u8)Value; 626 break; 627 case ODM_CMNINFO_RF_ANTENNA_TYPE: 628 pDM_Odm->AntDivType = (u8)Value; 629 break; 630 default: 631 /* do nothing */ 632 break; 633 } 634 635 /* Tx power tracking BB swing table. */ 636 /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ 637 pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ 638 pDM_Odm->BbSwingIdxOfdmCurrent = 12; 639 pDM_Odm->BbSwingFlagOfdm = false; 640} 641 642void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI) 643{ 644 struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; 645 struct adapter *adapter = pDM_Odm->Adapter; 646 647 if (pDM_DigTable->CurIGValue != CurrentIGI) { 648 rtl8188e_PHY_SetBBReg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N, CurrentIGI); 649 pDM_DigTable->CurIGValue = CurrentIGI; 650 } 651} 652 653void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres) 654{ 655 struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable; 656 657 if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) /* modify by Guo.Mingzhi 2012-01-03 */ 658 rtw_write8(pDM_Odm->Adapter, ODM_REG_CCK_CCA_11N, CurCCK_CCAThres); 659 pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres; 660} 661 662void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal) 663{ 664 struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable; 665 struct adapter *adapter = pDM_Odm->Adapter; 666 u8 Rssi_Up_bound = 30; 667 u8 Rssi_Low_bound = 25; 668 669 if (pDM_PSTable->initialize == 0) { 670 pDM_PSTable->reg_874 = (rtl8188e_PHY_QueryBBReg(adapter, 0x874, bMaskDWord) & 0x1CC000) >> 14; 671 pDM_PSTable->reg_c70 = (rtl8188e_PHY_QueryBBReg(adapter, 0xc70, bMaskDWord) & BIT(3)) >> 3; 672 pDM_PSTable->reg_85c = (rtl8188e_PHY_QueryBBReg(adapter, 0x85c, bMaskDWord) & 0xFF000000) >> 24; 673 pDM_PSTable->reg_a74 = (rtl8188e_PHY_QueryBBReg(adapter, 0xa74, bMaskDWord) & 0xF000) >> 12; 674 pDM_PSTable->initialize = 1; 675 } 676 677 if (!bForceInNormal) { 678 if (pDM_Odm->RSSI_Min != 0xFF) { 679 if (pDM_PSTable->pre_rf_state == RF_Normal) { 680 if (pDM_Odm->RSSI_Min >= Rssi_Up_bound) 681 pDM_PSTable->cur_rf_state = RF_Save; 682 else 683 pDM_PSTable->cur_rf_state = RF_Normal; 684 } else { 685 if (pDM_Odm->RSSI_Min <= Rssi_Low_bound) 686 pDM_PSTable->cur_rf_state = RF_Normal; 687 else 688 pDM_PSTable->cur_rf_state = RF_Save; 689 } 690 } else { 691 pDM_PSTable->cur_rf_state = RF_MAX; 692 } 693 } else { 694 pDM_PSTable->cur_rf_state = RF_Normal; 695 } 696 697 if (pDM_PSTable->pre_rf_state != pDM_PSTable->cur_rf_state) { 698 if (pDM_PSTable->cur_rf_state == RF_Save) { 699 rtl8188e_PHY_SetBBReg(adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */ 700 rtl8188e_PHY_SetBBReg(adapter, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */ 701 rtl8188e_PHY_SetBBReg(adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */ 702 rtl8188e_PHY_SetBBReg(adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */ 703 rtl8188e_PHY_SetBBReg(adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */ 704 rtl8188e_PHY_SetBBReg(adapter, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */ 705 rtl8188e_PHY_SetBBReg(adapter, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */ 706 } else { 707 rtl8188e_PHY_SetBBReg(adapter, 0x874, 0x1CC000, pDM_PSTable->reg_874); 708 rtl8188e_PHY_SetBBReg(adapter, 0xc70, BIT(3), pDM_PSTable->reg_c70); 709 rtl8188e_PHY_SetBBReg(adapter, 0x85c, 0xFF000000, pDM_PSTable->reg_85c); 710 rtl8188e_PHY_SetBBReg(adapter, 0xa74, 0xF000, pDM_PSTable->reg_a74); 711 rtl8188e_PHY_SetBBReg(adapter, 0x818, BIT(28), 0x0); 712 } 713 pDM_PSTable->pre_rf_state = pDM_PSTable->cur_rf_state; 714 } 715} 716 717u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level) 718{ 719 struct sta_info *pEntry; 720 u32 rate_bitmap = 0x0fffffff; 721 u8 WirelessMode; 722 723 pEntry = pDM_Odm->pODM_StaInfo[macid]; 724 if (!IS_STA_VALID(pEntry)) 725 return ra_mask; 726 727 WirelessMode = pEntry->wireless_mode; 728 729 switch (WirelessMode) { 730 case ODM_WM_B: 731 if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */ 732 rate_bitmap = 0x0000000d; 733 else 734 rate_bitmap = 0x0000000f; 735 break; 736 case (ODM_WM_B | ODM_WM_G): 737 if (rssi_level == DM_RATR_STA_HIGH) 738 rate_bitmap = 0x00000f00; 739 else if (rssi_level == DM_RATR_STA_MIDDLE) 740 rate_bitmap = 0x00000ff0; 741 else 742 rate_bitmap = 0x00000ff5; 743 break; 744 case (ODM_WM_B | ODM_WM_G | ODM_WM_N24G): 745 if (rssi_level == DM_RATR_STA_HIGH) { 746 rate_bitmap = 0x000f0000; 747 } else if (rssi_level == DM_RATR_STA_MIDDLE) { 748 rate_bitmap = 0x000ff000; 749 } else { 750 if (*pDM_Odm->pBandWidth == HT_CHANNEL_WIDTH_40) 751 rate_bitmap = 0x000ff015; 752 else 753 rate_bitmap = 0x000ff005; 754 } 755 break; 756 default: 757 /* case WIRELESS_11_24N: */ 758 rate_bitmap = 0x0fffffff; 759 break; 760 } 761 762 return rate_bitmap; 763} 764 765/* Return Value: bool */ 766/* - true: RATRState is changed. */ 767bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate, u8 *pRATRState) 768{ 769 struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive; 770 const u8 GoUpGap = 5; 771 u8 HighRSSIThreshForRA = pRA->HighRSSIThresh; 772 u8 LowRSSIThreshForRA = pRA->LowRSSIThresh; 773 u8 RATRState; 774 775 /* Threshold Adjustment: */ 776 /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */ 777 /* Here GoUpGap is added to solve the boundary's level alternation issue. */ 778 switch (*pRATRState) { 779 case DM_RATR_STA_INIT: 780 case DM_RATR_STA_HIGH: 781 break; 782 case DM_RATR_STA_MIDDLE: 783 HighRSSIThreshForRA += GoUpGap; 784 break; 785 case DM_RATR_STA_LOW: 786 HighRSSIThreshForRA += GoUpGap; 787 LowRSSIThreshForRA += GoUpGap; 788 break; 789 default: 790 break; 791 } 792 793 /* Decide RATRState by RSSI. */ 794 if (RSSI > HighRSSIThreshForRA) 795 RATRState = DM_RATR_STA_HIGH; 796 else if (RSSI > LowRSSIThreshForRA) 797 RATRState = DM_RATR_STA_MIDDLE; 798 else 799 RATRState = DM_RATR_STA_LOW; 800 801 if (*pRATRState != RATRState || bForceUpdate) { 802 *pRATRState = RATRState; 803 return true; 804 } 805 return false; 806} 807 808void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm) 809{ 810 struct adapter *Adapter = pDM_Odm->Adapter; 811 812 if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */ 813 rtl8188e_PHY_SetRFReg(Adapter, RF_T_METER_88E, BIT(17) | BIT(16), 0x03); 814 815 pDM_Odm->RFCalibrateInfo.TM_Trigger = 1; 816 return; 817 } else { 818 odm_TXPowerTrackingCallback_ThermalMeter_8188E(Adapter); 819 pDM_Odm->RFCalibrateInfo.TM_Trigger = 0; 820 } 821}