cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dm.c (20501B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright(c) 2009-2012  Realtek Corporation.*/
      3
      4#include "../wifi.h"
      5#include "../base.h"
      6#include "../core.h"
      7#include "reg.h"
      8#include "def.h"
      9#include "phy.h"
     10#include "dm.h"
     11#include "fw.h"
     12
     13static const u32 edca_setting_dl[PEER_MAX] = {
     14	0xa44f,		/* 0 UNKNOWN */
     15	0x5ea44f,	/* 1 REALTEK_90 */
     16	0x5ea44f,	/* 2 REALTEK_92SE */
     17	0xa630,		/* 3 BROAD	*/
     18	0xa44f,		/* 4 RAL */
     19	0xa630,		/* 5 ATH */
     20	0xa630,		/* 6 CISCO */
     21	0xa42b,		/* 7 MARV */
     22};
     23
     24static const u32 edca_setting_dl_gmode[PEER_MAX] = {
     25	0x4322,		/* 0 UNKNOWN */
     26	0xa44f,		/* 1 REALTEK_90 */
     27	0x5ea44f,	/* 2 REALTEK_92SE */
     28	0xa42b,		/* 3 BROAD */
     29	0x5e4322,	/* 4 RAL */
     30	0x4322,		/* 5 ATH */
     31	0xa430,		/* 6 CISCO */
     32	0x5ea44f,	/* 7 MARV */
     33};
     34
     35static const u32 edca_setting_ul[PEER_MAX] = {
     36	0x5e4322,	/* 0 UNKNOWN */
     37	0xa44f,		/* 1 REALTEK_90 */
     38	0x5ea44f,	/* 2 REALTEK_92SE */
     39	0x5ea322,	/* 3 BROAD */
     40	0x5ea422,	/* 4 RAL */
     41	0x5ea322,	/* 5 ATH */
     42	0x3ea44f,	/* 6 CISCO */
     43	0x5ea44f,	/* 7 MARV */
     44};
     45
     46static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw)
     47{
     48	struct rtl_priv *rtlpriv = rtl_priv(hw);
     49	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
     50
     51	static u64 last_txok_cnt;
     52	static u64 last_rxok_cnt;
     53	u64 cur_txok_cnt = 0;
     54	u64 cur_rxok_cnt = 0;
     55
     56	u32 edca_be_ul = edca_setting_ul[mac->vendor];
     57	u32 edca_be_dl = edca_setting_dl[mac->vendor];
     58	u32 edca_gmode = edca_setting_dl_gmode[mac->vendor];
     59
     60	if (mac->link_state != MAC80211_LINKED) {
     61		rtlpriv->dm.current_turbo_edca = false;
     62		goto dm_checkedcaturbo_exit;
     63	}
     64
     65	if ((!rtlpriv->dm.is_any_nonbepkts) &&
     66	    (!rtlpriv->dm.disable_framebursting)) {
     67		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
     68		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
     69
     70		if (rtlpriv->phy.rf_type == RF_1T2R) {
     71			if (cur_txok_cnt > 4 * cur_rxok_cnt) {
     72				/* Uplink TP is present. */
     73				if (rtlpriv->dm.is_cur_rdlstate ||
     74					!rtlpriv->dm.current_turbo_edca) {
     75					rtl_write_dword(rtlpriv, EDCAPARA_BE,
     76							edca_be_ul);
     77					rtlpriv->dm.is_cur_rdlstate = false;
     78				}
     79			} else {/* Balance TP is present. */
     80				if (!rtlpriv->dm.is_cur_rdlstate ||
     81					!rtlpriv->dm.current_turbo_edca) {
     82					if (mac->mode == WIRELESS_MODE_G ||
     83					    mac->mode == WIRELESS_MODE_B)
     84						rtl_write_dword(rtlpriv,
     85								EDCAPARA_BE,
     86								edca_gmode);
     87					else
     88						rtl_write_dword(rtlpriv,
     89								EDCAPARA_BE,
     90								edca_be_dl);
     91					rtlpriv->dm.is_cur_rdlstate = true;
     92				}
     93			}
     94			rtlpriv->dm.current_turbo_edca = true;
     95		} else {
     96			if (cur_rxok_cnt > 4 * cur_txok_cnt) {
     97				if (!rtlpriv->dm.is_cur_rdlstate ||
     98					!rtlpriv->dm.current_turbo_edca) {
     99					if (mac->mode == WIRELESS_MODE_G ||
    100					    mac->mode == WIRELESS_MODE_B)
    101						rtl_write_dword(rtlpriv,
    102								EDCAPARA_BE,
    103								edca_gmode);
    104					else
    105						rtl_write_dword(rtlpriv,
    106								EDCAPARA_BE,
    107								edca_be_dl);
    108					rtlpriv->dm.is_cur_rdlstate = true;
    109				}
    110			} else {
    111				if (rtlpriv->dm.is_cur_rdlstate ||
    112					!rtlpriv->dm.current_turbo_edca) {
    113					rtl_write_dword(rtlpriv, EDCAPARA_BE,
    114							edca_be_ul);
    115					rtlpriv->dm.is_cur_rdlstate = false;
    116				}
    117			}
    118			rtlpriv->dm.current_turbo_edca = true;
    119		}
    120	} else {
    121		if (rtlpriv->dm.current_turbo_edca) {
    122			u8 tmp = AC0_BE;
    123			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
    124						      &tmp);
    125			rtlpriv->dm.current_turbo_edca = false;
    126		}
    127	}
    128
    129dm_checkedcaturbo_exit:
    130	rtlpriv->dm.is_any_nonbepkts = false;
    131	last_txok_cnt = rtlpriv->stats.txbytesunicast;
    132	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
    133}
    134
    135static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
    136					struct ieee80211_hw *hw)
    137{
    138	struct rtl_priv *rtlpriv = rtl_priv(hw);
    139	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
    140	u8 thermalvalue = 0;
    141	u32 fw_cmd = 0;
    142
    143	rtlpriv->dm.txpower_trackinginit = true;
    144
    145	thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
    146
    147	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
    148		"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n",
    149		thermalvalue,
    150		rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter);
    151
    152	if (thermalvalue) {
    153		rtlpriv->dm.thermalvalue = thermalvalue;
    154		if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
    155			rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
    156		} else {
    157			fw_cmd = (FW_TXPWR_TRACK_THERMAL |
    158				 (rtlpriv->efuse.thermalmeter[0] << 8) |
    159				 (thermalvalue << 16));
    160
    161			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
    162				"Write to FW Thermal Val = 0x%x\n", fw_cmd);
    163
    164			rtl_write_dword(rtlpriv, WFM5, fw_cmd);
    165			rtl92s_phy_chk_fwcmd_iodone(hw);
    166		}
    167	}
    168
    169	rtlpriv->dm.txpowercount = 0;
    170}
    171
    172static void _rtl92s_dm_check_txpowertracking_thermalmeter(
    173					struct ieee80211_hw *hw)
    174{
    175	struct rtl_priv *rtlpriv = rtl_priv(hw);
    176	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    177	u8 tx_power_checkcnt = 5;
    178
    179	/* 2T2R TP issue */
    180	if (rtlphy->rf_type == RF_2T2R)
    181		return;
    182
    183	if (!rtlpriv->dm.txpower_tracking)
    184		return;
    185
    186	if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) {
    187		rtlpriv->dm.txpowercount++;
    188		return;
    189	}
    190
    191	if (!rtlpriv->dm.tm_trigger) {
    192		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER,
    193			      RFREG_OFFSET_MASK, 0x60);
    194		rtlpriv->dm.tm_trigger = 1;
    195	} else {
    196		_rtl92s_dm_txpowertracking_callback_thermalmeter(hw);
    197		rtlpriv->dm.tm_trigger = 0;
    198	}
    199}
    200
    201static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
    202{
    203	struct rtl_priv *rtlpriv = rtl_priv(hw);
    204	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
    205	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
    206	struct rate_adaptive *ra = &(rtlpriv->ra);
    207	struct ieee80211_sta *sta = NULL;
    208	u32 low_rssi_thresh = 0;
    209	u32 middle_rssi_thresh = 0;
    210	u32 high_rssi_thresh = 0;
    211
    212	if (is_hal_stop(rtlhal))
    213		return;
    214
    215	if (!rtlpriv->dm.useramask)
    216		return;
    217
    218	if (hal_get_firmwareversion(rtlpriv) >= 61 &&
    219	    !rtlpriv->dm.inform_fw_driverctrldm) {
    220		rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
    221		rtlpriv->dm.inform_fw_driverctrldm = true;
    222	}
    223
    224	if ((mac->link_state == MAC80211_LINKED) &&
    225	    (mac->opmode == NL80211_IFTYPE_STATION)) {
    226		switch (ra->pre_ratr_state) {
    227		case DM_RATR_STA_HIGH:
    228			high_rssi_thresh = 40;
    229			middle_rssi_thresh = 30;
    230			low_rssi_thresh = 20;
    231			break;
    232		case DM_RATR_STA_MIDDLE:
    233			high_rssi_thresh = 44;
    234			middle_rssi_thresh = 30;
    235			low_rssi_thresh = 20;
    236			break;
    237		case DM_RATR_STA_LOW:
    238			high_rssi_thresh = 44;
    239			middle_rssi_thresh = 34;
    240			low_rssi_thresh = 20;
    241			break;
    242		case DM_RATR_STA_ULTRALOW:
    243			high_rssi_thresh = 44;
    244			middle_rssi_thresh = 34;
    245			low_rssi_thresh = 24;
    246			break;
    247		default:
    248			high_rssi_thresh = 44;
    249			middle_rssi_thresh = 34;
    250			low_rssi_thresh = 24;
    251			break;
    252		}
    253
    254		if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) {
    255			ra->ratr_state = DM_RATR_STA_HIGH;
    256		} else if (rtlpriv->dm.undec_sm_pwdb >
    257			   (long)middle_rssi_thresh) {
    258			ra->ratr_state = DM_RATR_STA_LOW;
    259		} else if (rtlpriv->dm.undec_sm_pwdb >
    260			   (long)low_rssi_thresh) {
    261			ra->ratr_state = DM_RATR_STA_LOW;
    262		} else {
    263			ra->ratr_state = DM_RATR_STA_ULTRALOW;
    264		}
    265
    266		if (ra->pre_ratr_state != ra->ratr_state) {
    267			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
    268				"RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
    269				rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
    270				ra->pre_ratr_state, ra->ratr_state);
    271
    272			rcu_read_lock();
    273			sta = rtl_find_sta(hw, mac->bssid);
    274			if (sta)
    275				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
    276							   ra->ratr_state,
    277							   true);
    278			rcu_read_unlock();
    279
    280			ra->pre_ratr_state = ra->ratr_state;
    281		}
    282	}
    283}
    284
    285static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
    286{
    287	struct rtl_priv *rtlpriv = rtl_priv(hw);
    288	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
    289	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    290	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
    291	bool current_mrc;
    292	bool enable_mrc = true;
    293	long tmpentry_maxpwdb = 0;
    294	u8 rssi_a = 0;
    295	u8 rssi_b = 0;
    296
    297	if (is_hal_stop(rtlhal))
    298		return;
    299
    300	if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R))
    301		return;
    302
    303	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
    304
    305	if (mac->link_state >= MAC80211_LINKED) {
    306		if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) {
    307			rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
    308			rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
    309		}
    310	}
    311
    312	/* MRC settings would NOT affect TP on Wireless B mode. */
    313	if (mac->mode != WIRELESS_MODE_B) {
    314		if ((rssi_a == 0) && (rssi_b == 0)) {
    315			enable_mrc = true;
    316		} else if (rssi_b > 30) {
    317			/* Turn on B-Path */
    318			enable_mrc = true;
    319		} else if (rssi_b < 5) {
    320			/* Turn off B-path  */
    321			enable_mrc = false;
    322		/* Take care of RSSI differentiation. */
    323		} else if (rssi_a > 15 && (rssi_a >= rssi_b)) {
    324			if ((rssi_a - rssi_b) > 15)
    325				/* Turn off B-path  */
    326				enable_mrc = false;
    327			else if ((rssi_a - rssi_b) < 10)
    328				/* Turn on B-Path */
    329				enable_mrc = true;
    330			else
    331				enable_mrc = current_mrc;
    332		} else {
    333			/* Turn on B-Path */
    334			enable_mrc = true;
    335		}
    336	}
    337
    338	/* Update MRC settings if needed. */
    339	if (enable_mrc != current_mrc)
    340		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC,
    341					      (u8 *)&enable_mrc);
    342
    343}
    344
    345void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw)
    346{
    347	struct rtl_priv *rtlpriv = rtl_priv(hw);
    348
    349	rtlpriv->dm.current_turbo_edca = false;
    350	rtlpriv->dm.is_any_nonbepkts = false;
    351	rtlpriv->dm.is_cur_rdlstate = false;
    352}
    353
    354static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
    355{
    356	struct rtl_priv *rtlpriv = rtl_priv(hw);
    357	struct rate_adaptive *ra = &(rtlpriv->ra);
    358
    359	ra->ratr_state = DM_RATR_STA_MAX;
    360	ra->pre_ratr_state = DM_RATR_STA_MAX;
    361
    362	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER &&
    363	    hal_get_firmwareversion(rtlpriv) >= 60)
    364		rtlpriv->dm.useramask = true;
    365	else
    366		rtlpriv->dm.useramask = false;
    367
    368	rtlpriv->dm.useramask = false;
    369	rtlpriv->dm.inform_fw_driverctrldm = false;
    370}
    371
    372static void _rtl92s_dm_init_txpowertracking_thermalmeter(
    373				struct ieee80211_hw *hw)
    374{
    375	struct rtl_priv *rtlpriv = rtl_priv(hw);
    376
    377	rtlpriv->dm.txpower_tracking = true;
    378	rtlpriv->dm.txpowercount = 0;
    379	rtlpriv->dm.txpower_trackinginit = false;
    380}
    381
    382static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
    383{
    384	struct rtl_priv *rtlpriv = rtl_priv(hw);
    385	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
    386	u32 ret_value;
    387
    388	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
    389	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
    390
    391	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
    392	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
    393	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
    394	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
    395	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
    396
    397	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
    398		falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail +
    399		falsealm_cnt->cnt_mcs_fail;
    400
    401	/* read CCK false alarm */
    402	ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD);
    403	falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff);
    404	falsealm_cnt->cnt_all =	falsealm_cnt->cnt_ofdm_fail +
    405		falsealm_cnt->cnt_cck_fail;
    406}
    407
    408static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
    409{
    410	struct rtl_priv *rtlpriv = rtl_priv(hw);
    411	struct dig_t *digtable = &rtlpriv->dm_digtable;
    412	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
    413
    414	if (falsealm_cnt->cnt_all > digtable->fa_highthresh) {
    415		if ((digtable->back_val - 6) <
    416			digtable->backoffval_range_min)
    417			digtable->back_val = digtable->backoffval_range_min;
    418		else
    419			digtable->back_val -= 6;
    420	} else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) {
    421		if ((digtable->back_val + 6) >
    422			digtable->backoffval_range_max)
    423			digtable->back_val =
    424				 digtable->backoffval_range_max;
    425		else
    426			digtable->back_val += 6;
    427	}
    428}
    429
    430static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
    431{
    432	struct rtl_priv *rtlpriv = rtl_priv(hw);
    433	struct dig_t *digtable = &rtlpriv->dm_digtable;
    434	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
    435	static u8 initialized, force_write;
    436	u8 initial_gain = 0;
    437
    438	if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) ||
    439	    (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) {
    440		if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) {
    441			if (rtlpriv->psc.rfpwr_state != ERFON)
    442				return;
    443
    444			if (digtable->backoff_enable_flag)
    445				rtl92s_backoff_enable_flag(hw);
    446			else
    447				digtable->back_val = DM_DIG_BACKOFF_MAX;
    448
    449			if ((digtable->rssi_val + 10 - digtable->back_val) >
    450				digtable->rx_gain_max)
    451				digtable->cur_igvalue =
    452						digtable->rx_gain_max;
    453			else if ((digtable->rssi_val + 10 - digtable->back_val)
    454				 < digtable->rx_gain_min)
    455				digtable->cur_igvalue =
    456						digtable->rx_gain_min;
    457			else
    458				digtable->cur_igvalue = digtable->rssi_val + 10
    459					- digtable->back_val;
    460
    461			if (falsealm_cnt->cnt_all > 10000)
    462				digtable->cur_igvalue =
    463					 (digtable->cur_igvalue > 0x33) ?
    464					 digtable->cur_igvalue : 0x33;
    465
    466			if (falsealm_cnt->cnt_all > 16000)
    467				digtable->cur_igvalue =
    468						 digtable->rx_gain_max;
    469		/* connected -> connected or disconnected -> disconnected  */
    470		} else {
    471			/* Firmware control DIG, do nothing in driver dm */
    472			return;
    473		}
    474		/* disconnected -> connected or connected ->
    475		 * disconnected or beforeconnect->(dis)connected */
    476	} else {
    477		/* Enable FW DIG */
    478		digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
    479		rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
    480
    481		digtable->back_val = DM_DIG_BACKOFF_MAX;
    482		digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0];
    483		digtable->pre_igvalue = 0;
    484		return;
    485	}
    486
    487	/* Forced writing to prevent from fw-dig overwriting. */
    488	if (digtable->pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
    489						  MASKBYTE0))
    490		force_write = 1;
    491
    492	if ((digtable->pre_igvalue != digtable->cur_igvalue) ||
    493	    !initialized || force_write) {
    494		/* Disable FW DIG */
    495		rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE);
    496
    497		initial_gain = (u8)digtable->cur_igvalue;
    498
    499		/* Set initial gain. */
    500		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain);
    501		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain);
    502		digtable->pre_igvalue = digtable->cur_igvalue;
    503		initialized = 1;
    504		force_write = 0;
    505	}
    506}
    507
    508static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
    509{
    510	struct rtl_priv *rtlpriv = rtl_priv(hw);
    511	struct dig_t *dig = &rtlpriv->dm_digtable;
    512
    513	if (rtlpriv->mac80211.act_scanning)
    514		return;
    515
    516	/* Decide the current status and if modify initial gain or not */
    517	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
    518	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
    519		dig->cur_sta_cstate = DIG_STA_CONNECT;
    520	else
    521		dig->cur_sta_cstate = DIG_STA_DISCONNECT;
    522
    523	dig->rssi_val = rtlpriv->dm.undec_sm_pwdb;
    524
    525	/* Change dig mode to rssi */
    526	if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) {
    527		if (dig->dig_twoport_algorithm ==
    528		    DIG_TWO_PORT_ALGO_FALSE_ALARM) {
    529			dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
    530			rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS);
    531		}
    532	}
    533
    534	_rtl92s_dm_false_alarm_counter_statistics(hw);
    535	_rtl92s_dm_initial_gain_sta_beforeconnect(hw);
    536
    537	dig->pre_sta_cstate = dig->cur_sta_cstate;
    538}
    539
    540static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
    541{
    542	struct rtl_priv *rtlpriv = rtl_priv(hw);
    543	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    544	struct dig_t *digtable = &rtlpriv->dm_digtable;
    545
    546	/* 2T2R TP issue */
    547	if (rtlphy->rf_type == RF_2T2R)
    548		return;
    549
    550	if (!rtlpriv->dm.dm_initialgain_enable)
    551		return;
    552
    553	if (digtable->dig_enable_flag == false)
    554		return;
    555
    556	_rtl92s_dm_ctrl_initgain_bytwoport(hw);
    557}
    558
    559static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
    560{
    561	struct rtl_priv *rtlpriv = rtl_priv(hw);
    562	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    563	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
    564	long undec_sm_pwdb;
    565	long txpwr_threshold_lv1, txpwr_threshold_lv2;
    566
    567	/* 2T2R TP issue */
    568	if (rtlphy->rf_type == RF_2T2R)
    569		return;
    570
    571	if (!rtlpriv->dm.dynamic_txpower_enable ||
    572	    rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
    573		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    574		return;
    575	}
    576
    577	if ((mac->link_state < MAC80211_LINKED) &&
    578	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
    579		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
    580			"Not connected to any\n");
    581
    582		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    583
    584		rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    585		return;
    586	}
    587
    588	if (mac->link_state >= MAC80211_LINKED) {
    589		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
    590			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
    591			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    592				"AP Client PWDB = 0x%lx\n",
    593				undec_sm_pwdb);
    594		} else {
    595			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
    596			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    597				"STA Default Port PWDB = 0x%lx\n",
    598				undec_sm_pwdb);
    599		}
    600	} else {
    601		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
    602
    603		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    604			"AP Ext Port PWDB = 0x%lx\n",
    605			undec_sm_pwdb);
    606	}
    607
    608	txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
    609	txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1;
    610
    611	if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
    612		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    613	else if (undec_sm_pwdb >= txpwr_threshold_lv2)
    614		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
    615	else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) &&
    616		(undec_sm_pwdb >= txpwr_threshold_lv1))
    617		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
    618	else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3))
    619		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    620
    621	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
    622		rtl92s_phy_set_txpower(hw, rtlphy->current_channel);
    623
    624	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
    625}
    626
    627static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
    628{
    629	struct rtl_priv *rtlpriv = rtl_priv(hw);
    630	struct dig_t *digtable = &rtlpriv->dm_digtable;
    631
    632	/* Disable DIG scheme now.*/
    633	digtable->dig_enable_flag = true;
    634	digtable->backoff_enable_flag = true;
    635
    636	if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) &&
    637	    (hal_get_firmwareversion(rtlpriv) >= 0x3c))
    638		digtable->dig_algorithm = DIG_ALGO_BY_TOW_PORT;
    639	else
    640		digtable->dig_algorithm =
    641			 DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM;
    642
    643	digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
    644	digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
    645	/* off=by real rssi value, on=by digtable->rssi_val for new dig */
    646	digtable->dig_dbgmode = DM_DBG_OFF;
    647	digtable->dig_slgorithm_switch = 0;
    648
    649	/* 2007/10/04 MH Define init gain threshol. */
    650	digtable->dig_state = DM_STA_DIG_MAX;
    651	digtable->dig_highpwrstate = DM_STA_DIG_MAX;
    652
    653	digtable->cur_sta_cstate = DIG_STA_DISCONNECT;
    654	digtable->pre_sta_cstate = DIG_STA_DISCONNECT;
    655	digtable->cur_ap_cstate = DIG_AP_DISCONNECT;
    656	digtable->pre_ap_cstate = DIG_AP_DISCONNECT;
    657
    658	digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
    659	digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
    660
    661	digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
    662	digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
    663
    664	digtable->rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
    665	digtable->rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
    666
    667	/* for dig debug rssi value */
    668	digtable->rssi_val = 50;
    669	digtable->back_val = DM_DIG_BACKOFF_MAX;
    670	digtable->rx_gain_max = DM_DIG_MAX;
    671
    672	digtable->rx_gain_min = DM_DIG_MIN;
    673
    674	digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX;
    675	digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN;
    676}
    677
    678static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
    679{
    680	struct rtl_priv *rtlpriv = rtl_priv(hw);
    681
    682	if ((hal_get_firmwareversion(rtlpriv) >= 60) &&
    683	    (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER))
    684		rtlpriv->dm.dynamic_txpower_enable = true;
    685	else
    686		rtlpriv->dm.dynamic_txpower_enable = false;
    687
    688	rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    689	rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
    690}
    691
    692void rtl92s_dm_init(struct ieee80211_hw *hw)
    693{
    694	struct rtl_priv *rtlpriv = rtl_priv(hw);
    695
    696	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
    697	rtlpriv->dm.undec_sm_pwdb = -1;
    698
    699	_rtl92s_dm_init_dynamic_txpower(hw);
    700	rtl92s_dm_init_edca_turbo(hw);
    701	_rtl92s_dm_init_rate_adaptive_mask(hw);
    702	_rtl92s_dm_init_txpowertracking_thermalmeter(hw);
    703	_rtl92s_dm_init_dig(hw);
    704
    705	rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE);
    706}
    707
    708void rtl92s_dm_watchdog(struct ieee80211_hw *hw)
    709{
    710	_rtl92s_dm_check_edca_turbo(hw);
    711	_rtl92s_dm_check_txpowertracking_thermalmeter(hw);
    712	_rtl92s_dm_ctrl_initgain_byrssi(hw);
    713	_rtl92s_dm_dynamic_txpower(hw);
    714	_rtl92s_dm_refresh_rateadaptive_mask(hw);
    715	_rtl92s_dm_switch_baseband_mrc(hw);
    716}
    717