Merge tag 'rtw-next-2025-03-13' of https://github.com/pkshih/rtw

Ping-Ke Shih says:
====================
rtw-next patches for v6.15

Some minor fixes and refinements of rtw89.

The only major change is rtw88:

 * support RTL8814AE/RTL8814AU
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg
2025-03-19 09:34:40 +01:00
48 changed files with 27595 additions and 351 deletions

View File

@@ -54,6 +54,9 @@ config RTW88_8812A
tristate
select RTW88_88XXA
config RTW88_8814A
tristate
config RTW88_8822BE
tristate "Realtek 8822BE PCI wireless network adapter"
depends on PCI
@@ -222,6 +225,28 @@ config RTW88_8812AU
802.11ac USB wireless network adapter
config RTW88_8814AE
tristate "Realtek 8814AE PCI wireless network adapter"
depends on PCI
select RTW88_CORE
select RTW88_PCI
select RTW88_8814A
help
Select this option will enable support for 8814AE chipset
802.11ac PCIe wireless network adapter
config RTW88_8814AU
tristate "Realtek 8814AU USB wireless network adapter"
depends on USB
select RTW88_CORE
select RTW88_USB
select RTW88_8814A
help
Select this option will enable support for 8814AU chipset
802.11ac USB wireless network adapter
config RTW88_DEBUG
bool "Realtek rtw88 debug support"
depends on RTW88_CORE

View File

@@ -94,6 +94,15 @@ rtw88_8821au-objs := rtw8821au.o
obj-$(CONFIG_RTW88_8812AU) += rtw88_8812au.o
rtw88_8812au-objs := rtw8812au.o
obj-$(CONFIG_RTW88_8814A) += rtw88_8814a.o
rtw88_8814a-objs := rtw8814a.o rtw8814a_table.o
obj-$(CONFIG_RTW88_8814AE) += rtw88_8814ae.o
rtw88_8814ae-objs := rtw8814ae.o
obj-$(CONFIG_RTW88_8814AU) += rtw88_8814au.o
rtw88_8814au-objs := rtw8814au.o
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
rtw88_pci-objs := pci.o

View File

@@ -654,10 +654,10 @@ static void rtw_print_rate(struct seq_file *m, u8 rate)
case DESC_RATE6M...DESC_RATE54M:
rtw_print_ofdm_rate_txt(m, rate);
break;
case DESC_RATEMCS0...DESC_RATEMCS15:
case DESC_RATEMCS0...DESC_RATEMCS31:
rtw_print_ht_rate_txt(m, rate);
break;
case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9:
case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT4SS_MCS9:
rtw_print_vht_rate_txt(m, rate);
break;
default:
@@ -692,9 +692,11 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
{
struct rtw_debugfs_priv *debugfs_priv = m->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw_hal *hal = &rtwdev->hal;
u8 path, rate, bw, ch, regd;
struct rtw_power_params pwr_param = {0};
struct rtw_hal *hal = &rtwdev->hal;
u8 nss = rtwdev->efuse.hw_cap.nss;
u8 path, rate, bw, ch, regd;
u8 max_ht_rate, max_rate;
mutex_lock(&rtwdev->mutex);
bw = hal->current_band_width;
@@ -707,19 +709,23 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
seq_printf(m, "%-4s %-10s %-9s %-9s (%-4s %-4s %-4s) %-4s\n",
"path", "rate", "pwr", "base", "byr", "lmt", "sar", "rem");
max_ht_rate = DESC_RATEMCS0 + nss * 8 - 1;
if (rtwdev->chip->vht_supported)
max_rate = DESC_RATEVHT1SS_MCS0 + nss * 10 - 1;
else
max_rate = max_ht_rate;
mutex_lock(&hal->tx_power_mutex);
for (path = RF_PATH_A; path <= RF_PATH_B; path++) {
for (path = RF_PATH_A; path < hal->rf_path_num; path++) {
/* there is no CCK rates used in 5G */
if (hal->current_band_type == RTW_BAND_5G)
rate = DESC_RATE6M;
else
rate = DESC_RATE1M;
/* now, not support vht 3ss and vht 4ss*/
for (; rate <= DESC_RATEVHT2SS_MCS9; rate++) {
/* now, not support ht 3ss and ht 4ss*/
if (rate > DESC_RATEMCS15 &&
rate < DESC_RATEVHT1SS_MCS0)
for (; rate <= max_rate; rate++) {
if (rate > max_ht_rate && rate <= DESC_RATEMCS31)
continue;
rtw_get_tx_power_params(rtwdev, path, rate, bw,
@@ -849,20 +855,28 @@ static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
last_cnt->num_qry_pkt[rate_id + 9]);
}
seq_printf(m, "[RSSI(dBm)] = {%d, %d}\n",
seq_printf(m, "[RSSI(dBm)] = {%d, %d, %d, %d}\n",
dm_info->rssi[RF_PATH_A] - 100,
dm_info->rssi[RF_PATH_B] - 100);
seq_printf(m, "[Rx EVM(dB)] = {-%d, -%d}\n",
dm_info->rssi[RF_PATH_B] - 100,
dm_info->rssi[RF_PATH_C] - 100,
dm_info->rssi[RF_PATH_D] - 100);
seq_printf(m, "[Rx EVM(dB)] = {-%d, -%d, -%d, -%d}\n",
dm_info->rx_evm_dbm[RF_PATH_A],
dm_info->rx_evm_dbm[RF_PATH_B]);
seq_printf(m, "[Rx SNR] = {%d, %d}\n",
dm_info->rx_evm_dbm[RF_PATH_B],
dm_info->rx_evm_dbm[RF_PATH_C],
dm_info->rx_evm_dbm[RF_PATH_D]);
seq_printf(m, "[Rx SNR] = {%d, %d, %d, %d}\n",
dm_info->rx_snr[RF_PATH_A],
dm_info->rx_snr[RF_PATH_B]);
seq_printf(m, "[CFO_tail(KHz)] = {%d, %d}\n",
dm_info->rx_snr[RF_PATH_B],
dm_info->rx_snr[RF_PATH_C],
dm_info->rx_snr[RF_PATH_D]);
seq_printf(m, "[CFO_tail(KHz)] = {%d, %d, %d, %d}\n",
dm_info->cfo_tail[RF_PATH_A],
dm_info->cfo_tail[RF_PATH_B]);
dm_info->cfo_tail[RF_PATH_B],
dm_info->cfo_tail[RF_PATH_C],
dm_info->cfo_tail[RF_PATH_D]);
if (dm_info->curr_rx_rate >= DESC_RATE11M) {
if (dm_info->curr_rx_rate >= DESC_RATE6M) {
seq_puts(m, "[Rx Average Status]:\n");
seq_printf(m, " * OFDM, EVM: {-%d}, SNR: {%d}\n",
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_OFDM]),
@@ -875,6 +889,13 @@ static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_B]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_A]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_B]));
seq_printf(m, " * 3SS, EVM: {-%d, -%d, -%d}, SNR: {%d, %d, %d}\n",
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_3SS_A]),
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_3SS_B]),
(u8)ewma_evm_read(&ewma_evm[RTW_EVM_3SS_C]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_3SS_A]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_3SS_B]),
(u8)ewma_snr_read(&ewma_snr[RTW_SNR_3SS_C]));
}
seq_puts(m, "[Rx Counter]:\n");

View File

@@ -291,6 +291,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
if (rtw_read8(rtwdev, REG_CR) == 0xea)
cur_pwr = false;
else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB &&
chip->id != RTW_CHIP_TYPE_8814A &&
(rtw_read8(rtwdev, REG_SYS_STATUS1 + 1) & BIT(0)))
cur_pwr = false;
else

View File

@@ -1565,6 +1565,7 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
{
const struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_efuse *efuse = &rtwdev->efuse;
int i;
ht_cap->ht_supported = true;
ht_cap->cap = 0;
@@ -1584,25 +1585,20 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_cap->ampdu_density = chip->ampdu_density;
ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
if (efuse->hw_cap.nss > 1) {
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_mask[1] = 0xFF;
ht_cap->mcs.rx_mask[4] = 0x01;
ht_cap->mcs.rx_highest = cpu_to_le16(300);
} else {
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_mask[1] = 0x00;
ht_cap->mcs.rx_mask[4] = 0x01;
ht_cap->mcs.rx_highest = cpu_to_le16(150);
}
for (i = 0; i < efuse->hw_cap.nss; i++)
ht_cap->mcs.rx_mask[i] = 0xFF;
ht_cap->mcs.rx_mask[4] = 0x01;
ht_cap->mcs.rx_highest = cpu_to_le16(150 * efuse->hw_cap.nss);
}
static void rtw_init_vht_cap(struct rtw_dev *rtwdev,
struct ieee80211_sta_vht_cap *vht_cap)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
u16 mcs_map;
u16 mcs_map = 0;
__le16 highest;
int i;
if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE &&
efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT)
@@ -1625,21 +1621,15 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev,
if (rtw_chip_has_rx_ldpc(rtwdev))
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
IEEE80211_VHT_MCS_NOT_SUPPORTED << 14;
if (efuse->hw_cap.nss > 1) {
highest = cpu_to_le16(780);
mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2;
} else {
highest = cpu_to_le16(390);
mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2;
for (i = 0; i < 8; i++) {
if (i < efuse->hw_cap.nss)
mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
else
mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
}
highest = cpu_to_le16(390 * efuse->hw_cap.nss);
vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
vht_cap->vht_mcs.rx_highest = highest;

View File

@@ -386,6 +386,9 @@ enum rtw_evm {
RTW_EVM_1SS,
RTW_EVM_2SS_A,
RTW_EVM_2SS_B,
RTW_EVM_3SS_A,
RTW_EVM_3SS_B,
RTW_EVM_3SS_C,
/* keep it last */
RTW_EVM_NUM
};
@@ -403,6 +406,10 @@ enum rtw_snr {
RTW_SNR_2SS_B,
RTW_SNR_2SS_C,
RTW_SNR_2SS_D,
RTW_SNR_3SS_A,
RTW_SNR_3SS_B,
RTW_SNR_3SS_C,
RTW_SNR_3SS_D,
/* keep it last */
RTW_SNR_NUM
};
@@ -828,7 +835,7 @@ struct rtw_vif {
};
struct rtw_regulatory {
char alpha2[2];
char alpha2[2] __nonstring;
u8 txpwr_regd_2g;
u8 txpwr_regd_5g;
};

View File

@@ -2458,32 +2458,56 @@ void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
swing_table->n[RF_PATH_A] = tbl->pwrtrk_2g_ccka_n;
swing_table->p[RF_PATH_B] = tbl->pwrtrk_2g_cckb_p;
swing_table->n[RF_PATH_B] = tbl->pwrtrk_2g_cckb_n;
swing_table->p[RF_PATH_C] = tbl->pwrtrk_2g_cckc_p;
swing_table->n[RF_PATH_C] = tbl->pwrtrk_2g_cckc_n;
swing_table->p[RF_PATH_D] = tbl->pwrtrk_2g_cckd_p;
swing_table->n[RF_PATH_D] = tbl->pwrtrk_2g_cckd_n;
} else {
swing_table->p[RF_PATH_A] = tbl->pwrtrk_2ga_p;
swing_table->n[RF_PATH_A] = tbl->pwrtrk_2ga_n;
swing_table->p[RF_PATH_B] = tbl->pwrtrk_2gb_p;
swing_table->n[RF_PATH_B] = tbl->pwrtrk_2gb_n;
swing_table->p[RF_PATH_C] = tbl->pwrtrk_2gc_p;
swing_table->n[RF_PATH_C] = tbl->pwrtrk_2gc_n;
swing_table->p[RF_PATH_D] = tbl->pwrtrk_2gd_p;
swing_table->n[RF_PATH_D] = tbl->pwrtrk_2gd_n;
}
} else if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel)) {
swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_1];
swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_1];
swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_1];
swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_1];
swing_table->p[RF_PATH_C] = tbl->pwrtrk_5gc_p[RTW_PWR_TRK_5G_1];
swing_table->n[RF_PATH_C] = tbl->pwrtrk_5gc_n[RTW_PWR_TRK_5G_1];
swing_table->p[RF_PATH_D] = tbl->pwrtrk_5gd_p[RTW_PWR_TRK_5G_1];
swing_table->n[RF_PATH_D] = tbl->pwrtrk_5gd_n[RTW_PWR_TRK_5G_1];
} else if (IS_CH_5G_BAND_3(channel)) {
swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_2];
swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_2];
swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_2];
swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_2];
swing_table->p[RF_PATH_C] = tbl->pwrtrk_5gc_p[RTW_PWR_TRK_5G_2];
swing_table->n[RF_PATH_C] = tbl->pwrtrk_5gc_n[RTW_PWR_TRK_5G_2];
swing_table->p[RF_PATH_D] = tbl->pwrtrk_5gd_p[RTW_PWR_TRK_5G_2];
swing_table->n[RF_PATH_D] = tbl->pwrtrk_5gd_n[RTW_PWR_TRK_5G_2];
} else if (IS_CH_5G_BAND_4(channel)) {
swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_3];
swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_3];
swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_3];
swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_3];
swing_table->p[RF_PATH_C] = tbl->pwrtrk_5gc_p[RTW_PWR_TRK_5G_3];
swing_table->n[RF_PATH_C] = tbl->pwrtrk_5gc_n[RTW_PWR_TRK_5G_3];
swing_table->p[RF_PATH_D] = tbl->pwrtrk_5gd_p[RTW_PWR_TRK_5G_3];
swing_table->n[RF_PATH_D] = tbl->pwrtrk_5gd_n[RTW_PWR_TRK_5G_3];
} else {
swing_table->p[RF_PATH_A] = tbl->pwrtrk_2ga_p;
swing_table->n[RF_PATH_A] = tbl->pwrtrk_2ga_n;
swing_table->p[RF_PATH_B] = tbl->pwrtrk_2gb_p;
swing_table->n[RF_PATH_B] = tbl->pwrtrk_2gb_n;
swing_table->p[RF_PATH_C] = tbl->pwrtrk_2gc_p;
swing_table->n[RF_PATH_C] = tbl->pwrtrk_2gc_n;
swing_table->p[RF_PATH_D] = tbl->pwrtrk_2gd_p;
swing_table->n[RF_PATH_D] = tbl->pwrtrk_2gd_n;
}
}
EXPORT_SYMBOL(rtw_phy_config_swing_table);

View File

@@ -8,6 +8,7 @@
#define REG_SYS_FUNC_EN 0x0002
#define BIT_FEN_EN_25_1 BIT(13)
#define BIT_FEN_ELDR BIT(12)
#define BIT_FEN_PCIEA BIT(6)
#define BIT_FEN_CPUEN BIT(2)
#define BIT_FEN_USBA BIT(2)
#define BIT_FEN_BB_GLB_RST BIT(1)
@@ -39,6 +40,9 @@
#define BIT_RF_RSTB BIT(1)
#define BIT_RF_EN BIT(0)
#define REG_RF_CTRL1 0x0020
#define REG_RF_CTRL2 0x0021
#define REG_AFE_CTRL1 0x0024
#define BIT_MAC_CLK_SEL (BIT(20) | BIT(21))
#define REG_EFUSE_CTRL 0x0030
@@ -73,6 +77,8 @@
#define BIT_BT_PTA_EN BIT(5)
#define BIT_WLRFE_4_5_EN BIT(2)
#define REG_GPIO_PIN_CTRL 0x0044
#define REG_LED_CFG 0x004C
#define BIT_LNAON_SEL_EN BIT(26)
#define BIT_PAPE_SEL_EN BIT(25)
@@ -110,6 +116,7 @@
#define BIT_SDIO_PAD_E5 BIT(18)
#define REG_RF_B_CTRL 0x76
#define REG_RF_CTRL3 0x0076
#define REG_AFE_CTRL_4 0x0078
#define BIT_CK320M_AFE_EN BIT(4)
@@ -603,15 +610,25 @@
#define REG_CCA2ND 0x0838
#define REG_L1PKTH 0x0848
#define REG_CLKTRK 0x0860
#define REG_CSI_MASK_SETTING1 0x0874
#define REG_NBI_SETTING 0x087c
#define BIT_NBI_ENABLE BIT(13)
#define REG_CSI_FIX_MASK0 0x0880
#define REG_CSI_FIX_MASK1 0x0884
#define REG_CSI_FIX_MASK6 0x0898
#define REG_CSI_FIX_MASK7 0x089c
#define REG_ADCCLK 0x08AC
#define REG_HSSI_READ 0x08B0
#define REG_FPGA0_XCD_RF_PARA 0x08B4
#define REG_RX_MCS_LIMIT 0x08BC
#define REG_ADC160 0x08C4
#define REG_DBGSEL 0x08fc
#define REG_ANTSEL_SW 0x0900
#define REG_DAC_RSTB 0x090c
#define REG_PSD 0x0910
#define BIT_PSD_INI GENMASK(23, 22)
#define REG_SINGLE_TONE_CONT_TX 0x0914
#define REG_AGC_TABLE 0x0958
#define REG_RFE_CTRL_E 0x0974
#define REG_2ND_CCA_CTRL 0x0976
#define REG_IQK_COM00 0x0978
@@ -621,10 +638,18 @@
#define REG_FAS 0x09a4
#define REG_RXSB 0x0a00
#define BIT_RXSB_ANA_DIV BIT(15)
#define REG_CCK_RX 0x0a04
#define REG_CCK_PD_TH 0x0a0a
#define REG_CCK0_FAREPORT 0xa2c
#define REG_PRECTRL 0x0a14
#define BIT_DIS_CO_PATHSEL BIT(7)
#define BIT_IQ_WGT GENMASK(9, 8)
#define REG_CCA_MF 0x0a20
#define BIT_MBC_WIN GENMASK(5, 4)
#define REG_CCK0_TX_FILTER1 0x0a20
#define REG_CCK0_TX_FILTER2 0x0a24
#define REG_CCK0_DEBUG_PORT 0x0a28
#define REG_CCK0_FAREPORT 0x0a2c
#define BIT_CCK0_2RX BIT(18)
#define BIT_CCK0_MRC BIT(22)
#define REG_FA_CCK 0x0a5c
@@ -643,10 +668,18 @@
#define DIS_DPD_RATEVHT2SS_MCS1 BIT(9)
#define DIS_DPD_RATEALL GENMASK(9, 0)
#define REG_CCA 0x0a70
#define BIT_CCA_CO BIT(7)
#define REG_ANTSEL 0x0a74
#define BIT_ANT_BYCO BIT(8)
#define REG_CCKTX 0x0a84
#define BIT_CMB_CCA_2R BIT(28)
#define REG_CNTRST 0x0b58
#define REG_3WIRE_SWA 0x0c00
#define REG_RX_IQC_AB_A 0x0c10
#define REG_RX_IQC_CD_A 0x0c14
#define REG_TXSCALE_A 0x0c1c
#define BB_SWING_MASK GENMASK(31, 21)
#define REG_TX_AGC_A_CCK_11_CCK_1 0xc20
@@ -674,7 +707,7 @@
#define REG_LSSI_WRITE_A 0x0c90
#define REG_PREDISTA 0x0c90
#define REG_TXAGCIDX 0x0c94
#define REG_TX_AGC_A 0x0c94
#define REG_RFE_PINMUX_A 0x0cb0
#define REG_RFE_INV_A 0x0cb4
#define REG_RFE_CTRL8 0x0cb4
@@ -683,6 +716,7 @@
#define DPDT_CTRL_PIN 0x77
#define RFE_INV_MASK 0x3ff00000
#define REG_RFECTL_A 0x0cb8
#define REG_RFE_INV0 0x0cbc
#define REG_RFE_INV8 0x0cbd
#define BIT_MASK_RFE_INV89 GENMASK(1, 0)
#define REG_RFE_INV16 0x0cbe
@@ -703,6 +737,7 @@
#define REG_3WIRE_SWB 0x0e00
#define REG_RX_IQC_AB_B 0x0e10
#define REG_RX_IQC_CD_B 0x0e14
#define REG_TXSCALE_B 0x0e1c
#define REG_TX_AGC_B_CCK_11_CCK_1 0xe20
#define REG_TX_AGC_B_OFDM18_OFDM6 0xe24
@@ -729,6 +764,7 @@
#define REG_LSSI_WRITE_B 0x0e90
#define REG_PREDISTB 0x0e90
#define REG_INIDLYB 0x0e94
#define REG_TX_AGC_B 0x0e94
#define REG_RFE_PINMUX_B 0x0eb0
#define REG_RFE_INV_B 0x0eb4
#define REG_RFECTL_B 0x0eb8
@@ -744,8 +780,11 @@
#define REG_CRC_HT 0x0f10
#define REG_CRC_OFDM 0x0f14
#define REG_FA_OFDM 0x0f48
#define REG_DBGRPT 0x0fa0
#define REG_CCA_CCK 0x0fcc
#define REG_SYS_CFG3_8814A 0x1000
#define REG_ANAPARSW_MAC_0 0x1010
#define BIT_CF_L_V2 GENMASK(29, 28)
@@ -863,9 +902,27 @@
#define LTECOEX_WRITE_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_WRITE_DATA_V1
#define LTECOEX_READ_DATA REG_WL2LTECOEX_INDIRECT_ACCESS_READ_DATA_V1
#define REG_RX_IQC_AB_C 0x1810
#define REG_RX_IQC_CD_C 0x1814
#define REG_TXSCALE_C 0x181c
#define REG_CK_MONHC 0x185c
#define REG_AFE_PWR1_C 0x1860
#define REG_IGN_GNT_BT1 0x1860
#define REG_TX_AGC_C 0x1894
#define REG_RFE_PINMUX_C 0x18b4
#define REG_RFESEL_CTRL 0x1990
#define REG_AGC_TBL 0x1998
#define REG_RX_IQC_AB_D 0x1a10
#define REG_RX_IQC_CD_D 0x1a14
#define REG_TXSCALE_D 0x1a1c
#define REG_CK_MONHD 0x1a5c
#define REG_AFE_PWR1_D 0x1a60
#define REG_TX_AGC_D 0x1a94
#define REG_RFE_PINMUX_D 0x1ab4
#define REG_RFE_INVSEL_D 0x1abc
#define BIT_RFE_SELSW0_D GENMASK(27, 20)
#define REG_NOMASK_TXBT 0x1ca7
#define REG_ANAPAR 0x1c30
@@ -906,6 +963,7 @@
#define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8))
#define RF18_CHANNEL_MASK (MASKBYTE0)
#define RF18_RFSI_MASK (BIT(18) | BIT(17))
#define RF_RCK1_V1 0x1c
#define RF_RCK 0x1d
#define RF_MODE_TABLE_ADDR 0x30
#define RF_MODE_TABLE_DATA0 0x31

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2025 Realtek Corporation
*/
#ifndef __RTW8814A_H__
#define __RTW8814A_H__
struct rtw8814au_efuse {
u8 vid[2]; /* 0xd0 */
u8 pid[2]; /* 0xd2 */
u8 res[4]; /* 0xd4 */
u8 mac_addr[ETH_ALEN]; /* 0xd8 */
} __packed;
struct rtw8814ae_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vid[2]; /* 0xd6 */
u8 did[2]; /* 0xd8 */
u8 svid[2]; /* 0xda */
u8 smid[2]; /* 0xdc */
} __packed;
struct rtw8814a_efuse {
__le16 rtl_id;
u8 res0[0x0c];
u8 usb_mode; /* 0x0e */
u8 res1;
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k; /* 0xb9 */
u8 thermal_meter; /* 0xba */
u8 iqk_lck; /* 0xbb */
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2]; /* 0xbf */
u8 rf_board_option; /* 0xc1 */
u8 res2;
u8 rf_bt_setting; /* 0xc3 */
u8 eeprom_version; /* 0xc4 */
u8 eeprom_customer_id; /* 0xc5 */
u8 tx_bb_swing_setting_2g; /* 0xc6 */
u8 tx_bb_swing_setting_5g; /* 0xc7 */
u8 res3;
u8 trx_antenna_option; /* 0xc9 */
u8 rfe_option; /* 0xca */
u8 country_code[2]; /* 0xcb */
u8 res4[3];
union {
struct rtw8814au_efuse u;
struct rtw8814ae_efuse e;
};
u8 res5[0x122]; /* 0xde */
} __packed;
static_assert(sizeof(struct rtw8814a_efuse) == 512);
extern const struct rtw_chip_info rtw8814a_hw_spec;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2025 Realtek Corporation
*/
#ifndef __RTW8814A_TABLE_H__
#define __RTW8814A_TABLE_H__
extern const struct rtw_table rtw8814a_mac_tbl;
extern const struct rtw_table rtw8814a_agc_tbl;
extern const struct rtw_table rtw8814a_bb_tbl;
extern const struct rtw_table rtw8814a_bb_pg_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type0_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type2_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type3_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type4_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type5_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type7_tbl;
extern const struct rtw_table rtw8814a_bb_pg_type8_tbl;
extern const struct rtw_table rtw8814a_rf_a_tbl;
extern const struct rtw_table rtw8814a_rf_b_tbl;
extern const struct rtw_table rtw8814a_rf_c_tbl;
extern const struct rtw_table rtw8814a_rf_d_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type0_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type1_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type2_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type3_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type5_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type7_tbl;
extern const struct rtw_table rtw8814a_txpwr_lmt_type8_tbl;
extern const struct rtw_pwr_track_tbl rtw8814a_rtw_pwrtrk_tbl;
extern const struct rtw_pwr_track_tbl rtw8814a_rtw_pwrtrk_type0_tbl;
extern const struct rtw_pwr_track_tbl rtw8814a_rtw_pwrtrk_type2_tbl;
extern const struct rtw_pwr_track_tbl rtw8814a_rtw_pwrtrk_type5_tbl;
extern const struct rtw_pwr_track_tbl rtw8814a_rtw_pwrtrk_type7_tbl;
extern const struct rtw_pwr_track_tbl rtw8814a_rtw_pwrtrk_type8_tbl;
extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8814a[];
extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8814a[];
#endif

View File

@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2025 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/pci.h>
#include "pci.h"
#include "rtw8814a.h"
static const struct pci_device_id rtw_8814ae_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8813),
.driver_data = (kernel_ulong_t)&rtw8814a_hw_spec
},
{}
};
MODULE_DEVICE_TABLE(pci, rtw_8814ae_id_table);
static struct pci_driver rtw_8814ae_driver = {
.name = "rtw_8814ae",
.id_table = rtw_8814ae_id_table,
.probe = rtw_pci_probe,
.remove = rtw_pci_remove,
.driver.pm = &rtw_pm_ops,
.shutdown = rtw_pci_shutdown,
};
module_pci_driver(rtw_8814ae_driver);
MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8814ae driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2025 Realtek Corporation
*/
#include <linux/module.h>
#include <linux/usb.h>
#include "main.h"
#include "rtw8814a.h"
#include "usb.h"
static const struct usb_device_id rtw_8814au_id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8813, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400d, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9054, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1817, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1852, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1853, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0026, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x809a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x809b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0106, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa834, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa833, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8814a_hw_spec) },
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8814au_id_table);
static struct usb_driver rtw_8814au_driver = {
.name = "rtw_8814au",
.id_table = rtw_8814au_id_table,
.probe = rtw_usb_probe,
.disconnect = rtw_usb_disconnect,
};
module_usb_driver(rtw_8814au_driver);
MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8814au driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@@ -73,6 +73,10 @@ static const struct usb_device_id rtw_8822bu_id_table[] = {
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ELECOM WDB-867DU3S */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0107, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30H */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x010a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30N */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3322, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* D-Link DWA-T185 rev. A1 */
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);

View File

@@ -73,6 +73,12 @@ static void rtw_rx_phy_stat(struct rtw_dev *rtwdev,
rate_ss_evm = 2;
evm_id = RTW_EVM_2SS_A;
break;
case DESC_RATEMCS16...DESC_RATEMCS23:
case DESC_RATEVHT3SS_MCS0...DESC_RATEVHT3SS_MCS9:
rate_ss = 3;
rate_ss_evm = 3;
evm_id = RTW_EVM_3SS_A;
break;
default:
rtw_warn(rtwdev, "unknown pkt rate = %d\n", pkt_stat->rate);
return;

View File

@@ -101,7 +101,8 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
*nss = 4;
*mcs = rate - DESC_RATEVHT4SS_MCS0;
} else if (rate >= DESC_RATEMCS0 &&
rate <= DESC_RATEMCS15) {
rate <= DESC_RATEMCS31) {
*nss = 0;
*mcs = rate - DESC_RATEMCS0;
}
}

View File

@@ -476,6 +476,12 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
case WLAN_CIPHER_SUITE_WEP104:
hw_key_type = RTW89_SEC_KEY_TYPE_WEP104;
break;
case WLAN_CIPHER_SUITE_TKIP:
if (!chip->hw_tkip_crypto)
return -EOPNOTSUPP;
hw_key_type = RTW89_SEC_KEY_TYPE_TKIP;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
break;
case WLAN_CIPHER_SUITE_CCMP:
hw_key_type = RTW89_SEC_KEY_TYPE_CCMP128;
if (!chip->hw_mgmt_tx_encrypt)

View File

@@ -8,6 +8,7 @@
#include "fw.h"
#include "mac.h"
#include "ps.h"
#include "sar.h"
#include "util.h"
static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
@@ -2673,6 +2674,7 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
struct rtw89_entity_weight w = {};
int ret;
rtwvif_link->chanctx_idx = cfg->idx;
rtwvif_link->chanctx_assigned = true;
@@ -2692,7 +2694,13 @@ int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
rtw89_swap_chanctx(rtwdev, cfg->idx, RTW89_CHANCTX_0);
out:
return rtw89_set_channel(rtwdev);
ret = rtw89_set_channel(rtwdev);
if (ret)
return ret;
rtw89_tas_reset(rtwdev, true);
return 0;
}
void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,

View File

@@ -10,7 +10,7 @@
#include "ps.h"
#include "reg.h"
#define RTW89_COEX_VERSION 0x07000313
#define RTW89_COEX_VERSION 0x07000413
#define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
#define BTC_E2G_LIMIT_DEF 80
@@ -132,6 +132,14 @@ static const u32 cxtbl[] = {
static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
/* firmware version must be in decreasing order for each chip */
{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0),
.fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
.fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
.fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
.fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
.fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
.max_role_num = 6,
},
{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
.fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
.fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
@@ -1372,11 +1380,9 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
} else if (ver->fcxbtcrpt == 8) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
break;
} else if (ver->fcxbtcrpt == 7) {
pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
break;
} else {
goto err;
}
@@ -1534,6 +1540,9 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
} else if (ver->fcxbtafh == 2) {
pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
} else if (ver->fcxbtafh == 7) {
pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7);
} else {
goto err;
}
@@ -8100,6 +8109,7 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
return;
func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
pfwinfo->cnt_c2h++;
switch (func) {
case BTF_EVNT_BUF_OVERFLOW:

View File

@@ -2382,6 +2382,49 @@ static void rtw89_core_validate_rx_signal(struct ieee80211_rx_status *rx_status)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
}
static void rtw89_core_update_rx_freq_from_ie(struct rtw89_dev *rtwdev,
struct sk_buff *skb,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
size_t hdr_len, ielen;
u8 *variable;
int chan;
if (!rtwdev->chip->rx_freq_frome_ie)
return;
if (!rtwdev->scanning)
return;
if (ieee80211_is_beacon(mgmt->frame_control)) {
variable = mgmt->u.beacon.variable;
hdr_len = offsetof(struct ieee80211_mgmt,
u.beacon.variable);
} else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
variable = mgmt->u.probe_resp.variable;
hdr_len = offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
} else {
return;
}
if (skb->len > hdr_len)
ielen = skb->len - hdr_len;
else
return;
/* The parsing code for both 2GHz and 5GHz bands is the same in this
* function.
*/
chan = cfg80211_get_ies_channel_number(variable, ielen, NL80211_BAND_2GHZ);
if (chan == -1)
return;
rx_status->band = chan > 14 ? RTW89_BAND_5G : RTW89_BAND_2G;
rx_status->freq = ieee80211_channel_to_frequency(chan, rx_status->band);
}
static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct rtw89_rx_desc_info *desc_info,
@@ -2399,6 +2442,7 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
rtw89_core_update_rx_status_by_ppdu(rtwdev, rx_status, phy_ppdu);
rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status);
rtw89_core_validate_rx_signal(rx_status);
rtw89_core_update_rx_freq_from_ie(rtwdev, skb_ppdu, rx_status);
/* In low power mode, it does RX in thread context. */
local_bh_disable();
@@ -4557,8 +4601,6 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
rtw89_mac_cfg_phy_rpt_bands(rtwdev, true);
rtw89_mac_update_rts_threshold(rtwdev);
rtw89_tas_reset(rtwdev);
ret = rtw89_hci_start(rtwdev);
if (ret) {
rtw89_err(rtwdev, "failed to start hci\n");
@@ -4912,6 +4954,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv
rtw89_chip_rfk_scan(rtwdev, rtwvif_link, true);
rtw89_hci_recalc_int_mit(rtwdev);
rtw89_phy_config_edcca(rtwdev, bb, true);
rtw89_tas_scan(rtwdev, true);
rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr);
}
@@ -4938,6 +4981,7 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx);
bb = rtw89_get_bb_ctx(rtwdev, rtwvif_link->phy_idx);
rtw89_phy_config_edcca(rtwdev, bb, false);
rtw89_tas_scan(rtwdev, false);
rtwdev->scanning = false;
rtw89_for_each_active_bb(rtwdev, bb)

View File

@@ -17,6 +17,7 @@ struct rtw89_dev;
struct rtw89_pci_info;
struct rtw89_mac_gen_def;
struct rtw89_phy_gen_def;
struct rtw89_fw_blacklist;
struct rtw89_efuse_block_cfg;
struct rtw89_h2c_rf_tssi;
struct rtw89_fw_txpwr_track_cfg;
@@ -3043,6 +3044,7 @@ struct rtw89_btc_rpt_cmn_info {
union rtw89_btc_fbtc_btafh_info {
struct rtw89_btc_fbtc_btafh v1;
struct rtw89_btc_fbtc_btafh_v2 v2;
struct rtw89_btc_fbtc_btafh_v7 v7;
};
struct rtw89_btc_report_ctrl_state {
@@ -3676,6 +3678,8 @@ struct rtw89_chip_ops {
int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
int (*h2c_txtime_cmac_tbl)(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link);
@@ -4237,6 +4241,7 @@ enum rtw89_chanctx_state {
enum rtw89_chanctx_callbacks {
RTW89_CHANCTX_CALLBACK_PLACEHOLDER,
RTW89_CHANCTX_CALLBACK_RFK,
RTW89_CHANCTX_CALLBACK_TAS,
NUM_OF_RTW89_CHANCTX_CALLBACKS,
};
@@ -4257,6 +4262,7 @@ struct rtw89_chip_info {
bool try_ce_fw;
u8 bbmcu_nr;
u32 needed_fw_elms;
const struct rtw89_fw_blacklist *fw_blacklist;
u32 fifo_size;
bool small_fifo_size;
u32 dle_scc_rsvd_size;
@@ -4277,10 +4283,13 @@ struct rtw89_chip_info {
bool support_unii4;
bool support_rnr;
bool support_ant_gain;
bool support_tas;
bool ul_tb_waveform_ctrl;
bool ul_tb_pwr_diff;
bool rx_freq_frome_ie;
bool hw_sec_hdr;
bool hw_mgmt_tx_encrypt;
bool hw_tkip_crypto;
u8 rf_path_num;
u8 tx_nss;
u8 rx_nss;
@@ -4484,6 +4493,7 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_CH_INFO_BE_V0,
RTW89_FW_FEATURE_LPS_CH_INFO,
RTW89_FW_FEATURE_NO_PHYCAP_P1,
RTW89_FW_FEATURE_NO_POWER_DIFFERENCE,
};
struct rtw89_fw_suit {
@@ -4658,6 +4668,7 @@ enum rtw89_ant_gain_domain_type {
struct rtw89_ant_gain_info {
s8 offset[RTW89_ANT_GAIN_CHAIN_NUM][RTW89_ANT_GAIN_SUBBAND_NR];
u32 regd_enabled;
bool block_country;
};
struct rtw89_6ghz_span {
@@ -4673,18 +4684,29 @@ struct rtw89_6ghz_span {
enum rtw89_tas_state {
RTW89_TAS_STATE_DPR_OFF,
RTW89_TAS_STATE_DPR_ON,
RTW89_TAS_STATE_DPR_FORBID,
RTW89_TAS_STATE_STATIC_SAR,
};
#define RTW89_TAS_MAX_WINDOW 50
#define RTW89_TAS_TX_RATIO_WINDOW 6
#define RTW89_TAS_TXPWR_WINDOW 180
struct rtw89_tas_info {
s16 txpwr_history[RTW89_TAS_MAX_WINDOW];
s32 total_txpwr;
u8 cur_idx;
s8 dpr_gap;
s8 delta;
u16 tx_ratio_history[RTW89_TAS_TX_RATIO_WINDOW];
u64 txpwr_history[RTW89_TAS_TXPWR_WINDOW];
u8 txpwr_head_idx;
u8 txpwr_tail_idx;
u8 tx_ratio_idx;
u16 total_tx_ratio;
u64 total_txpwr;
u64 instant_txpwr;
u32 window_size;
s8 dpr_on_threshold;
s8 dpr_off_threshold;
enum rtw89_tas_state backup_state;
enum rtw89_tas_state state;
bool keep_history;
bool block_regd;
bool enable;
bool pause;
};
struct rtw89_chanctx_cfg {
@@ -4742,6 +4764,7 @@ struct rtw89_edcca_bak {
enum rtw89_dm_type {
RTW89_DM_DYNAMIC_EDCCA,
RTW89_DM_THERMAL_PROTECT,
RTW89_DM_TAS,
};
#define RTW89_THERMAL_PROT_LV_MAX 5
@@ -5141,7 +5164,7 @@ struct rtw89_tssi_info {
u32 alignment_backup_by_ch[RF_PATH_MAX][TSSI_MAX_CH_NUM][TSSI_ALIMK_VALUE_NUM];
u32 alignment_value[RF_PATH_MAX][TSSI_ALIMK_MAX][TSSI_ALIMK_VALUE_NUM];
bool alignment_done[RF_PATH_MAX][TSSI_ALIMK_MAX];
u32 tssi_alimk_time;
u64 tssi_alimk_time;
};
struct rtw89_power_trim_info {

View File

@@ -4154,6 +4154,7 @@ static const struct rtw89_disabled_dm_info {
} rtw89_disabled_dm_infos[] = {
DM_INFO(DYNAMIC_EDCCA),
DM_INFO(THERMAL_PROTECT),
DM_INFO(TAS),
};
static ssize_t

View File

@@ -38,6 +38,16 @@ struct rtw89_arp_rsp {
static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C};
const struct rtw89_fw_blacklist rtw89_fw_blacklist_default = {
.ver = 0x00,
.list = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
},
};
EXPORT_SYMBOL(rtw89_fw_blacklist_default);
union rtw89_fw_element_arg {
size_t offset;
enum rtw89_rf_path rf_path;
@@ -314,7 +324,7 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
if (!sec->secure_boot)
goto out;
sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v);
sb_sel_ver = get_unaligned_le32(&section_content->sb_sel_ver.v);
if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn)
goto ignore;
@@ -344,6 +354,46 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
return 0;
}
static int __check_secure_blacklist(struct rtw89_dev *rtwdev,
struct rtw89_fw_bin_info *info,
struct rtw89_fw_hdr_section_info *section_info,
const void *content)
{
const struct rtw89_fw_blacklist *chip_blacklist = rtwdev->chip->fw_blacklist;
const union rtw89_fw_section_mssc_content *section_content = content;
struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
u8 byte_idx;
u8 bit_mask;
if (!sec->secure_boot)
return 0;
if (!info->secure_section_exist || section_info->ignore)
return 0;
if (!chip_blacklist) {
rtw89_warn(rtwdev, "chip no blacklist for secure firmware\n");
return -ENOENT;
}
byte_idx = section_content->blacklist.bit_in_chip_list >> 3;
bit_mask = BIT(section_content->blacklist.bit_in_chip_list & 0x7);
if (section_content->blacklist.ver > chip_blacklist->ver) {
rtw89_warn(rtwdev, "chip blacklist out of date (%u, %u)\n",
section_content->blacklist.ver, chip_blacklist->ver);
return -EINVAL;
}
if (chip_blacklist->list[byte_idx] & bit_mask) {
rtw89_warn(rtwdev, "firmware %u in chip blacklist\n",
section_content->blacklist.ver);
return -EPERM;
}
return 0;
}
static int __parse_security_section(struct rtw89_dev *rtwdev,
struct rtw89_fw_bin_info *info,
struct rtw89_fw_hdr_section_info *section_info,
@@ -364,8 +414,11 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
*mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
if (sec->secure_boot) {
if (sec->mss_idx >= section_info->mssc)
if (sec->mss_idx >= section_info->mssc) {
rtw89_err(rtwdev, "unexpected MSS %d >= %d\n",
sec->mss_idx, section_info->mssc);
return -EFAULT;
}
section_info->key_addr = content + section_info->len +
sec->mss_idx * FWDL_SECURITY_SIGLEN;
section_info->key_len = FWDL_SECURITY_SIGLEN;
@@ -374,6 +427,9 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
info->secure_section_exist = true;
}
ret = __check_secure_blacklist(rtwdev, info, section_info, content);
WARN_ONCE(ret, "Current firmware in blacklist. Please update firmware.\n");
return 0;
}
@@ -489,6 +545,23 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev,
}
}
static
const struct rtw89_mfw_hdr *rtw89_mfw_get_hdr_ptr(struct rtw89_dev *rtwdev,
const struct firmware *firmware)
{
const struct rtw89_mfw_hdr *mfw_hdr;
if (sizeof(*mfw_hdr) > firmware->size)
return NULL;
mfw_hdr = (const struct rtw89_mfw_hdr *)firmware->data;
if (mfw_hdr->sig != RTW89_MFW_SIG)
return NULL;
return mfw_hdr;
}
static int rtw89_mfw_validate_hdr(struct rtw89_dev *rtwdev,
const struct firmware *firmware,
const struct rtw89_mfw_hdr *mfw_hdr)
@@ -519,14 +592,15 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
{
struct rtw89_fw_info *fw_info = &rtwdev->fw;
const struct firmware *firmware = fw_info->req.firmware;
const struct rtw89_mfw_info *mfw_info = NULL, *tmp;
const struct rtw89_mfw_hdr *mfw_hdr;
const u8 *mfw = firmware->data;
u32 mfw_len = firmware->size;
const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw;
const struct rtw89_mfw_info *mfw_info = NULL, *tmp;
int ret;
int i;
if (mfw_hdr->sig != RTW89_MFW_SIG) {
mfw_hdr = rtw89_mfw_get_hdr_ptr(rtwdev, firmware);
if (!mfw_hdr) {
rtw89_debug(rtwdev, RTW89_DBG_FW, "use legacy firmware\n");
/* legacy firmware support normal type only */
if (type != RTW89_FW_NORMAL)
@@ -582,13 +656,13 @@ static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev)
{
struct rtw89_fw_info *fw_info = &rtwdev->fw;
const struct firmware *firmware = fw_info->req.firmware;
const struct rtw89_mfw_hdr *mfw_hdr =
(const struct rtw89_mfw_hdr *)firmware->data;
const struct rtw89_mfw_info *mfw_info;
const struct rtw89_mfw_hdr *mfw_hdr;
u32 size;
int ret;
if (mfw_hdr->sig != RTW89_MFW_SIG) {
mfw_hdr = rtw89_mfw_get_hdr_ptr(rtwdev, firmware);
if (!mfw_hdr) {
rtw89_warn(rtwdev, "not mfw format\n");
return 0;
}
@@ -775,6 +849,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE),
};
static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@@ -1028,7 +1103,7 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
bitmap = le32_to_cpu(elm->u.txpwr_trk.bitmap);
if ((bitmap & needed_bitmap) != needed_bitmap) {
rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %0x8x\n",
rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %08x\n",
needed_bitmap, bitmap);
return -ENOENT;
}
@@ -1460,7 +1535,6 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev,
ret = rtw89_h2c_tx(rtwdev, skb, false);
if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
ret = -1;
goto fail;
}
@@ -1547,7 +1621,6 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev,
ret = rtw89_h2c_tx(rtwdev, skb, true);
if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
ret = -1;
goto fail;
}
@@ -3435,9 +3508,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3 |
CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4);
h2c->w6 = le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0,
h2c->w6 = le32_encode_bits(vif->cfg.aid, CCTLINFO_G7_W6_AID12_PAID) |
le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0,
CCTLINFO_G7_W6_ULDL);
h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL);
h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_AID12_PAID | CCTLINFO_G7_W6_ULDL);
if (rtwsta_link) {
h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he,
@@ -3573,6 +3647,61 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
return ret;
}
EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl);
int rtw89_fw_h2c_txtime_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link)
{
struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for txtime_cmac_g7\n");
return -ENOMEM;
}
skb_put(skb, len);
h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, CCTLINFO_G7_C0_MACID) |
le32_encode_bits(1, CCTLINFO_G7_C0_OP);
if (rtwsta_link->cctl_tx_time) {
h2c->w3 |= le32_encode_bits(1, CCTLINFO_G7_W3_AMPDU_TIME_SEL);
h2c->m3 |= cpu_to_le32(CCTLINFO_G7_W3_AMPDU_TIME_SEL);
h2c->w2 |= le32_encode_bits(rtwsta_link->ampdu_max_time,
CCTLINFO_G7_W2_AMPDU_MAX_TIME);
h2c->m2 |= cpu_to_le32(CCTLINFO_G7_W2_AMPDU_MAX_TIME);
}
if (rtwsta_link->cctl_tx_retry_limit) {
h2c->w2 |= le32_encode_bits(1, CCTLINFO_G7_W2_DATA_TXCNT_LMT_SEL) |
le32_encode_bits(rtwsta_link->data_tx_cnt_lmt,
CCTLINFO_G7_W2_DATA_TX_CNT_LMT);
h2c->m2 |= cpu_to_le32(CCTLINFO_G7_W2_DATA_TXCNT_LMT_SEL |
CCTLINFO_G7_W2_DATA_TX_CNT_LMT);
}
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1,
len);
ret = rtw89_h2c_tx(rtwdev, skb, false);
if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
return 0;
fail:
dev_kfree_skb_any(skb);
return ret;
}
EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl_g7);
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link)
@@ -3776,14 +3905,15 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be);
#define H2C_ROLE_MAINTAIN_LEN 4
int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
enum rtw89_upd_mode upd_mode)
{
struct sk_buff *skb;
u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id;
struct rtw89_h2c_role_maintain *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
u8 self_role;
int ret;
@@ -3796,21 +3926,27 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
self_role = rtwvif_link->self_role;
}
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ROLE_MAINTAIN_LEN);
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for h2c join\n");
return -ENOMEM;
}
skb_put(skb, H2C_ROLE_MAINTAIN_LEN);
SET_FWROLE_MAINTAIN_MACID(skb->data, mac_id);
SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, self_role);
SET_FWROLE_MAINTAIN_UPD_MODE(skb->data, upd_mode);
SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif_link->wifi_role);
skb_put(skb, len);
h2c = (struct rtw89_h2c_role_maintain *)skb->data;
h2c->w0 = le32_encode_bits(mac_id, RTW89_H2C_ROLE_MAINTAIN_W0_MACID) |
le32_encode_bits(self_role, RTW89_H2C_ROLE_MAINTAIN_W0_SELF_ROLE) |
le32_encode_bits(upd_mode, RTW89_H2C_ROLE_MAINTAIN_W0_UPD_MODE) |
le32_encode_bits(rtwvif_link->wifi_role,
RTW89_H2C_ROLE_MAINTAIN_W0_WIFI_ROLE) |
le32_encode_bits(rtwvif_link->mac_idx,
RTW89_H2C_ROLE_MAINTAIN_W0_BAND) |
le32_encode_bits(rtwvif_link->port, RTW89_H2C_ROLE_MAINTAIN_W0_PORT);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
H2C_FUNC_MAC_FWROLE_MAINTAIN, 0, 1,
H2C_ROLE_MAINTAIN_LEN);
len);
ret = rtw89_h2c_tx(rtwdev, skb, false);
if (ret) {

View File

@@ -663,6 +663,11 @@ struct rtw89_fw_mss_pool_hdr {
} __packed;
union rtw89_fw_section_mssc_content {
struct {
u8 pad[0x20];
u8 bit_in_chip_list;
u8 ver;
} __packed blacklist;
struct {
u8 pad[58];
__le32 v;
@@ -673,6 +678,13 @@ union rtw89_fw_section_mssc_content {
} __packed key_sign_len;
} __packed;
struct rtw89_fw_blacklist {
u8 ver;
u8 list[32];
};
extern const struct rtw89_fw_blacklist rtw89_fw_blacklist_default;
static inline void SET_CTRL_INFO_MACID(void *table, u32 val)
{
le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0));
@@ -1579,25 +1591,17 @@ struct rtw89_h2c_bcn_upd_be {
#define RTW89_H2C_BCN_UPD_BE_W7_ECSA_OFST GENMASK(30, 16)
#define RTW89_H2C_BCN_UPD_BE_W7_PROTECTION_KEY_ID BIT(31)
static inline void SET_FWROLE_MAINTAIN_MACID(void *h2c, u32 val)
{
le32p_replace_bits((__le32 *)h2c, val, GENMASK(7, 0));
}
struct rtw89_h2c_role_maintain {
__le32 w0;
};
static inline void SET_FWROLE_MAINTAIN_SELF_ROLE(void *h2c, u32 val)
{
le32p_replace_bits((__le32 *)h2c, val, GENMASK(9, 8));
}
static inline void SET_FWROLE_MAINTAIN_UPD_MODE(void *h2c, u32 val)
{
le32p_replace_bits((__le32 *)h2c, val, GENMASK(12, 10));
}
static inline void SET_FWROLE_MAINTAIN_WIFI_ROLE(void *h2c, u32 val)
{
le32p_replace_bits((__le32 *)h2c, val, GENMASK(16, 13));
}
#define RTW89_H2C_ROLE_MAINTAIN_W0_MACID GENMASK(7, 0)
#define RTW89_H2C_ROLE_MAINTAIN_W0_SELF_ROLE GENMASK(9, 8)
#define RTW89_H2C_ROLE_MAINTAIN_W0_UPD_MODE GENMASK(12, 10)
#define RTW89_H2C_ROLE_MAINTAIN_W0_WIFI_ROLE GENMASK(16, 13)
#define RTW89_H2C_ROLE_MAINTAIN_W0_BAND GENMASK(18, 17)
#define RTW89_H2C_ROLE_MAINTAIN_W0_PORT GENMASK(21, 19)
#define RTW89_H2C_ROLE_MAINTAIN_W0_MACID_EXT GENMASK(31, 24)
enum rtw89_fw_sta_type { /* value of RTW89_H2C_JOININFO_W1_STA_TYPE */
RTW89_FW_N_AC_STA = 0,
@@ -4539,6 +4543,12 @@ struct rtw89_c2h_rfk_report {
u8 version;
} __packed;
struct rtw89_c2h_rf_tas_info {
struct rtw89_c2h_hdr hdr;
__le32 cur_idx;
__le16 txpwr_history[20];
} __packed;
#define RTW89_FW_RSVD_PLE_SIZE 0x800
#define RTW89_FW_BACKTRACE_INFO_SIZE 8
@@ -4588,6 +4598,8 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txtime_cmac_tbl_g7(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link);
int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
@@ -4869,6 +4881,15 @@ static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev,
return 0;
}
static inline
int rtw89_chip_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
return chip->ops->h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
}
static inline
int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
bool valid, struct ieee80211_ampdu_params *params)

View File

@@ -4837,6 +4837,32 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask);
}
void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
struct ieee80211_bss_conf *bss_conf;
bool set;
u32 reg;
if (rtwdev->chip->chip_gen != RTW89_CHIP_BE)
return;
rcu_read_lock();
bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
set = bss_conf->he_support && !bss_conf->eht_support;
rcu_read_unlock();
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CLIENT_OM_CTRL,
rtwvif_link->mac_idx);
if (set)
rtw89_write32_set(rtwdev, reg, B_BE_TRIG_DIS_EHTTB);
else
rtw89_write32_clr(rtwdev, reg, B_BE_TRIG_DIS_EHTTB);
}
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
{
rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link);
@@ -6433,6 +6459,7 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_
u32 tx_time)
{
#define MAC_AX_DFLT_TX_TIME 5280
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx;
u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time;
u32 reg;
@@ -6440,7 +6467,7 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_
if (rtwsta_link->cctl_tx_time) {
rtwsta_link->ampdu_max_time = (max_tx_time - 512) >> 9;
ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
ret = rtw89_chip_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
} else {
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
if (ret) {
@@ -6448,8 +6475,8 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_
return ret;
}
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AMPDU_AGG_LIMIT, mac_idx);
rtw89_write32_mask(rtwdev, reg, B_AX_AMPDU_MAX_TIME_MASK,
reg = rtw89_mac_reg_by_idx(rtwdev, mac->agg_limit.addr, mac_idx);
rtw89_write32_mask(rtwdev, reg, mac->agg_limit.mask,
max_tx_time >> 5);
}
@@ -6475,6 +6502,7 @@ int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwst
int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link,
u32 *tx_time)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx;
u32 reg;
int ret = 0;
@@ -6488,8 +6516,8 @@ int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwst
return ret;
}
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AMPDU_AGG_LIMIT, mac_idx);
*tx_time = rtw89_read32_mask(rtwdev, reg, B_AX_AMPDU_MAX_TIME_MASK) << 5;
reg = rtw89_mac_reg_by_idx(rtwdev, mac->agg_limit.addr, mac_idx);
*tx_time = rtw89_read32_mask(rtwdev, reg, mac->agg_limit.mask) << 5;
}
return ret;
@@ -6505,9 +6533,9 @@ int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev,
if (!resume) {
rtwsta_link->cctl_tx_retry_limit = true;
ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
ret = rtw89_chip_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
} else {
ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
ret = rtw89_chip_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
rtwsta_link->cctl_tx_retry_limit = false;
}
@@ -6517,6 +6545,7 @@ int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev,
int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link, u8 *tx_retry)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx;
u32 reg;
int ret = 0;
@@ -6530,8 +6559,8 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
return ret;
}
reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXCNT, mac_idx);
*tx_retry = rtw89_read32_mask(rtwdev, reg, B_AX_L_TXCNT_LMT_MASK);
reg = rtw89_mac_reg_by_idx(rtwdev, mac->txcnt_limit.addr, mac_idx);
*tx_retry = rtw89_read32_mask(rtwdev, reg, mac->txcnt_limit.mask);
}
return ret;
@@ -6809,6 +6838,8 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.mask = B_AX_RXTRIG_RU26_DIS,
},
.wow_ctrl = {.addr = R_AX_WOW_CTRL, .mask = B_AX_WOW_WOWEN,},
.agg_limit = {.addr = R_AX_AMPDU_AGG_LIMIT, .mask = B_AX_AMPDU_MAX_TIME_MASK,},
.txcnt_limit = {.addr = R_AX_TXCNT, .mask = B_AX_L_TXCNT_LMT_MASK,},
.check_mac_en = rtw89_mac_check_mac_en_ax,
.sys_init = sys_init_ax,

View File

@@ -964,6 +964,8 @@ struct rtw89_mac_gen_def {
struct rtw89_reg_def bfee_ctrl;
struct rtw89_reg_def narrow_bw_ru_dis;
struct rtw89_reg_def wow_ctrl;
struct rtw89_reg_def agg_limit;
struct rtw89_reg_def txcnt_limit;
int (*check_mac_en)(struct rtw89_dev *rtwdev, u8 band,
enum rtw89_mac_hwmod_sel sel);
@@ -1186,6 +1188,8 @@ void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, bool en);
void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link);
void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link);
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en);
int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif);

View File

@@ -656,6 +656,7 @@ static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev,
rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link);
rtw89_mac_port_update(rtwdev, rtwvif_link);
rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link);
rtw89_mac_set_he_tb(rtwdev, rtwvif_link);
}
static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev,

View File

@@ -708,8 +708,8 @@ static int sec_eng_init_be(struct rtw89_dev *rtwdev)
val32 |= B_BE_CLK_EN_CGCMP | B_BE_CLK_EN_WAPI | B_BE_CLK_EN_WEP_TKIP |
B_BE_SEC_TX_ENC | B_BE_SEC_RX_DEC |
B_BE_MC_DEC | B_BE_BC_DEC |
B_BE_BMC_MGNT_DEC | B_BE_UC_MGNT_DEC;
val32 &= ~B_BE_SEC_PRE_ENQUE_TX;
B_BE_BMC_MGNT_DEC | B_BE_UC_MGNT_DEC |
B_BE_SEC_PRE_ENQUE_TX;
rtw89_write32(rtwdev, R_BE_SEC_ENG_CTRL, val32);
rtw89_write32_set(rtwdev, R_BE_SEC_MPDU_PROC, B_BE_APPEND_ICV | B_BE_APPEND_MIC);
@@ -2585,6 +2585,8 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.mask = B_BE_RXTRIG_RU26_DIS,
},
.wow_ctrl = {.addr = R_BE_WOW_CTRL, .mask = B_BE_WOW_WOWEN,},
.agg_limit = {.addr = R_BE_AMPDU_AGG_LIMIT, .mask = B_BE_AMPDU_MAX_TIME_MASK,},
.txcnt_limit = {.addr = R_BE_TXCNT, .mask = B_BE_L_TXCNT_LMT_MASK,},
.check_mac_en = rtw89_mac_check_mac_en_be,
.sys_init = sys_init_be,

View File

@@ -455,34 +455,36 @@
#define B_BE_RX0DMA_INT_EN BIT(0)
#define R_BE_HAXI_HISR00 0xB0B4
#define B_BE_RDU_CH6_INT BIT(28)
#define B_BE_RDU_CH5_INT BIT(27)
#define B_BE_RDU_CH4_INT BIT(26)
#define B_BE_RDU_CH2_INT BIT(25)
#define B_BE_RDU_CH1_INT BIT(24)
#define B_BE_RDU_CH0_INT BIT(23)
#define B_BE_RXDMA_STUCK_INT BIT(22)
#define B_BE_TXDMA_STUCK_INT BIT(21)
#define B_BE_TXDMA_CH14_INT BIT(20)
#define B_BE_TXDMA_CH13_INT BIT(19)
#define B_BE_TXDMA_CH12_INT BIT(18)
#define B_BE_TXDMA_CH11_INT BIT(17)
#define B_BE_TXDMA_CH10_INT BIT(16)
#define B_BE_TXDMA_CH9_INT BIT(15)
#define B_BE_TXDMA_CH8_INT BIT(14)
#define B_BE_TXDMA_CH7_INT BIT(13)
#define B_BE_TXDMA_CH6_INT BIT(12)
#define B_BE_TXDMA_CH5_INT BIT(11)
#define B_BE_TXDMA_CH4_INT BIT(10)
#define B_BE_TXDMA_CH3_INT BIT(9)
#define B_BE_TXDMA_CH2_INT BIT(8)
#define B_BE_TXDMA_CH1_INT BIT(7)
#define B_BE_TXDMA_CH0_INT BIT(6)
#define B_BE_RPQ1DMA_INT BIT(5)
#define B_BE_RX1P1DMA_INT BIT(4)
#define B_BE_RDU_CH5_INT_V1 BIT(30)
#define B_BE_RDU_CH4_INT_V1 BIT(29)
#define B_BE_RDU_CH3_INT_V1 BIT(28)
#define B_BE_RDU_CH2_INT_V1 BIT(27)
#define B_BE_RDU_CH1_INT_V1 BIT(26)
#define B_BE_RDU_CH0_INT_V1 BIT(25)
#define B_BE_RXDMA_STUCK_INT_V1 BIT(24)
#define B_BE_TXDMA_STUCK_INT_V1 BIT(23)
#define B_BE_TXDMA_CH14_INT_V1 BIT(22)
#define B_BE_TXDMA_CH13_INT_V1 BIT(21)
#define B_BE_TXDMA_CH12_INT_V1 BIT(20)
#define B_BE_TXDMA_CH11_INT_V1 BIT(19)
#define B_BE_TXDMA_CH10_INT_V1 BIT(18)
#define B_BE_TXDMA_CH9_INT_V1 BIT(17)
#define B_BE_TXDMA_CH8_INT_V1 BIT(16)
#define B_BE_TXDMA_CH7_INT_V1 BIT(15)
#define B_BE_TXDMA_CH6_INT_V1 BIT(14)
#define B_BE_TXDMA_CH5_INT_V1 BIT(13)
#define B_BE_TXDMA_CH4_INT_V1 BIT(12)
#define B_BE_TXDMA_CH3_INT_V1 BIT(11)
#define B_BE_TXDMA_CH2_INT_V1 BIT(10)
#define B_BE_TXDMA_CH1_INT_V1 BIT(9)
#define B_BE_TXDMA_CH0_INT_V1 BIT(8)
#define B_BE_RX1P1DMA_INT_V1 BIT(7)
#define B_BE_RX0P1DMA_INT_V1 BIT(6)
#define B_BE_RO1DMA_INT BIT(5)
#define B_BE_RP1DMA_INT BIT(4)
#define B_BE_RX1DMA_INT BIT(3)
#define B_BE_RPQ0DMA_INT BIT(2)
#define B_BE_RX0P1DMA_INT BIT(1)
#define B_BE_RO0DMA_INT BIT(2)
#define B_BE_RP0DMA_INT BIT(1)
#define B_BE_RX0DMA_INT BIT(0)
/* TX/RX */

View File

@@ -666,7 +666,7 @@ SIMPLE_DEV_PM_OPS(rtw89_pm_ops_be, rtw89_pci_suspend_be, rtw89_pci_resume_be);
EXPORT_SYMBOL(rtw89_pm_ops_be);
const struct rtw89_pci_gen_def rtw89_pci_gen_be = {
.isr_rdu = B_BE_RDU_CH1_INT | B_BE_RDU_CH0_INT,
.isr_rdu = B_BE_RDU_CH1_INT_V1 | B_BE_RDU_CH0_INT_V1,
.isr_halt_c2h = B_BE_HALT_C2H_INT,
.isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT,
.isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1},

View File

@@ -2044,12 +2044,15 @@ static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 cente
if (!chip->support_ant_gain)
return 0;
if (!(ant_gain->regd_enabled & BIT(regd)))
if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
return 0;
offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, center_freq);
offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, center_freq);
if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
return min(offset_patha, offset_pathb);
return max(offset_patha, offset_pathb);
}
@@ -2057,10 +2060,17 @@ s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan)
{
struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
const struct rtw89_chip_info *chip = rtwdev->chip;
u8 regd = rtw89_regd_get(rtwdev, chan->band_type);
s8 offset_patha, offset_pathb;
if (!(ant_gain->regd_enabled & BIT(regd)))
if (!chip->support_ant_gain)
return 0;
if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
return 0;
if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
return 0;
offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq);
@@ -2079,7 +2089,8 @@ int rtw89_print_ant_gain(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
char *p = buf, *end = buf + bufsz;
s8 offset_patha, offset_pathb;
if (!chip->support_ant_gain || !(ant_gain->regd_enabled & BIT(regd))) {
if (!(chip->support_ant_gain && (ant_gain->regd_enabled & BIT(regd))) ||
ant_gain->block_country) {
p += scnprintf(p, end - p, "no DAG is applied\n");
goto out;
}
@@ -3459,6 +3470,30 @@ rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u3
static void
rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
const struct rtw89_c2h_rf_tas_info *rf_tas =
(const struct rtw89_c2h_rf_tas_info *)c2h->data;
const enum rtw89_sar_sources src = rtwdev->sar.src;
struct rtw89_tas_info *tas = &rtwdev->tas;
u64 linear = 0;
u32 i, cur_idx;
s16 txpwr;
if (!tas->enable || src == RTW89_SAR_SOURCE_NONE)
return;
cur_idx = le32_to_cpu(rf_tas->cur_idx);
for (i = 0; i < cur_idx; i++) {
txpwr = (s16)le16_to_cpu(rf_tas->txpwr_history[i]);
linear += rtw89_db_quarter_to_linear(txpwr);
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"tas: index: %u, txpwr: %d\n", i, txpwr);
}
if (cur_idx == 0)
tas->instant_txpwr = rtw89_db_to_linear(0);
else
tas->instant_txpwr = DIV_ROUND_DOWN_ULL(linear, cur_idx);
}
static

View File

@@ -914,6 +914,13 @@ static inline s8 rtw89_phy_txpwr_rf_to_bb(struct rtw89_dev *rtwdev, s8 txpwr_rf)
return txpwr_rf << (chip->txpwr_factor_bb - chip->txpwr_factor_rf);
}
static inline s8 rtw89_phy_txpwr_bb_to_rf(struct rtw89_dev *rtwdev, s8 txpwr_bb)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
return txpwr_bb >> (chip->txpwr_factor_bb - chip->txpwr_factor_rf);
}
static inline s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf)
{
const struct rtw89_chip_info *chip = rtwdev->chip;

View File

@@ -6618,6 +6618,13 @@
#define B_BE_RTS_LIMIT_IN_OFDM6 BIT(1)
#define B_BE_CHECK_CCK_EN BIT(0)
#define R_BE_TXCNT 0x1082C
#define R_BE_TXCNT_C1 0x1482C
#define B_BE_ADD_TXCNT_BY BIT(31)
#define B_BE_TOTAL_TC_OPT BIT(30)
#define B_BE_S_TXCNT_LMT_MASK GENMASK(29, 24)
#define B_BE_L_TXCNT_LMT_MASK GENMASK(21, 16)
#define R_BE_MBSSID_DROP_0 0x1083C
#define R_BE_MBSSID_DROP_0_C1 0x1483C
#define B_BE_GI_LTF_FB_SEL BIT(30)
@@ -7095,6 +7102,10 @@
#define B_BE_MACLBK_RDY_NUM_MASK GENMASK(7, 3)
#define B_BE_MACLBK_EN BIT(0)
#define R_BE_CLIENT_OM_CTRL 0x11040
#define R_BE_CLIENT_OM_CTRL_C1 0x15040
#define B_BE_TRIG_DIS_EHTTB BIT(24)
#define R_BE_WMAC_NAV_CTL 0x11080
#define R_BE_WMAC_NAV_CTL_C1 0x15080
#define B_BE_WMAC_NAV_UPPER_EN BIT(26)
@@ -9174,6 +9185,16 @@
#define B_IQKINF2_FCNT GENMASK(23, 16)
#define B_IQKINF2_KCNT GENMASK(15, 8)
#define B_IQKINF2_NCTLV GENMASK(7, 0)
#define R_TXAGC_REF_DBM_RF1_P0 0xBC04
#define B_TXAGC_OFDM_REF_DBM_RF1_P0 GENMASK(10, 2)
#define B_TXAGC_CCK_REF_DBM_RF1_P0 GENMASK(19, 11)
#define R_TSSI_K_RF1_P0 0xBC28
#define B_TSSI_K_OFDM_RF1_P0 GENMASK(9, 0)
#define R_TXAGC_REF_DBM_RF1_P1 0xBD04
#define B_TXAGC_OFDM_REF_DBM_RF1_P1 GENMASK(10, 2)
#define B_TXAGC_CCK_REF_DBM_RF1_P1 GENMASK(19, 11)
#define R_TSSI_K_RF1_P1 0xBD28
#define B_TSSI_K_OFDM_RF1_P1 GENMASK(9, 0)
#define R_RFK_ST 0xBFF8
#define R_DCOF0 0xC000
#define B_DCOF0_RST BIT(17)
@@ -9343,16 +9364,18 @@
#define R_TSSI_MAP_OFST_P1 0xE720
#define B_TSSI_MAP_OFST_OFDM GENMASK(17, 9)
#define B_TSSI_MAP_OFST_CCK GENMASK(26, 18)
#define R_TXAGC_REF0_P0 0xE628
#define R_TXAGC_REF0_P1 0xE728
#define B_TXAGC_REF0_OFDM_DBM GENMASK(8, 0)
#define B_TXAGC_REF0_CCK_DBM GENMASK(17, 9)
#define B_TXAGC_REF0_OFDM_CW GENMASK(26, 18)
#define R_TXAGC_REF1_P0 0xE62C
#define R_TXAGC_REF1_P1 0xE72C
#define B_TXAGC_REF1_CCK_CW GENMASK(8, 0)
#define R_TXAGC_REF_DBM_P0 0xE628
#define B_TXAGC_OFDM_REF_DBM_P0 GENMASK(8, 0)
#define B_TXAGC_CCK_REF_DBM_P0 GENMASK(17, 9)
#define R_TSSI_K_P0 0xE6A0
#define B_TSSI_K_OFDM_P0 GENMASK(29, 20)
#define R_TXPWR_RSTB 0xE70C
#define B_TXPWR_RSTB BIT(16)
#define R_TXAGC_REF_DBM_P1 0xE728
#define B_TXAGC_OFDM_REF_DBM_P1 GENMASK(8, 0)
#define B_TXAGC_CCK_REF_DBM_P1 GENMASK(17, 9)
#define R_TSSI_K_P1 0xE7A0
#define B_TSSI_K_OFDM_P1 GENMASK(29, 20)
/* WiFi CPU local domain */
#define R_AX_WDT_CTRL 0x0040

View File

@@ -721,6 +721,31 @@ static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
}
static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
const struct rtw89_regd *regd = regulatory->regd;
struct rtw89_tas_info *tas = &rtwdev->tas;
if (!tas->enable)
return;
tas->block_regd = !test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap);
}
static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
{
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_regd *regd = regulatory->regd;
if (!chip->support_ant_gain)
return;
ant_gain->block_country = !test_bit(RTW89_REGD_FUNC_DAG, regd->func_bitmap);
}
static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
struct wiphy *wiphy,
struct regulatory_request *request)
@@ -738,6 +763,8 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
rtw89_regd_apply_policy_tas(rtwdev);
rtw89_regd_apply_policy_ant_gain(rtwdev);
}
static

View File

@@ -2423,6 +2423,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
@@ -2458,6 +2459,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.try_ce_fw = true,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fw_blacklist = NULL,
.fifo_size = 196608,
.small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
@@ -2496,10 +2498,13 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
.support_ant_gain = false,
.support_tas = false,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.rx_freq_frome_ie = true,
.hw_sec_hdr = false,
.hw_mgmt_tx_encrypt = false,
.hw_tkip_crypto = false,
.rf_path_num = 1,
.tx_nss = 1,
.rx_nss = 1,

View File

@@ -2149,6 +2149,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
@@ -2175,6 +2176,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.try_ce_fw = false,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fw_blacklist = NULL,
.fifo_size = 458752,
.small_fifo_size = false,
.dle_scc_rsvd_size = 0,
@@ -2214,10 +2216,13 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = false,
.support_ant_gain = false,
.support_tas = false,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = false,
.rx_freq_frome_ie = true,
.hw_sec_hdr = false,
.hw_mgmt_tx_encrypt = false,
.hw_tkip_crypto = false,
.rf_path_num = 2,
.tx_nss = 2,
.rx_nss = 2,

View File

@@ -776,6 +776,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
@@ -811,6 +812,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.try_ce_fw = true,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fw_blacklist = &rtw89_fw_blacklist_default,
.fifo_size = 196608,
.small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
@@ -850,10 +852,13 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
.support_ant_gain = true,
.support_tas = false,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.rx_freq_frome_ie = true,
.hw_sec_hdr = false,
.hw_mgmt_tx_encrypt = false,
.hw_tkip_crypto = false,
.rf_path_num = 2,
.tx_nss = 2,
.rx_nss = 2,

View File

@@ -621,9 +621,9 @@ static void rtw8852bt_ext_loss_avg_update(struct rtw89_dev *rtwdev,
if (ext_loss_a == ext_loss_b) {
ext_loss_avg = ext_loss_a;
} else {
linear = rtw89_db_2_linear(abs(ext_loss_a - ext_loss_b)) + 1;
linear = DIV_ROUND_CLOSEST_ULL(linear / 2, 1 << RTW89_LINEAR_FRAC_BITS);
ext_loss_avg = rtw89_linear_2_db(linear);
linear = rtw89_db_to_linear(abs(ext_loss_a - ext_loss_b)) + 1;
linear /= 2;
ext_loss_avg = rtw89_linear_to_db(linear);
ext_loss_avg += min(ext_loss_a, ext_loss_b);
}

View File

@@ -3585,9 +3585,10 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
u8 ch_idx = _tssi_ch_to_idx(rtwdev, channel);
struct rtw8852bx_bb_tssi_bak tssi_bak;
s32 aliment_diff, tssi_cw_default;
u32 start_time, finish_time;
u32 bb_reg_backup[8] = {0};
ktime_t start_time;
const s16 *power;
s64 this_time;
u8 band;
bool ok;
u32 tmp;
@@ -3613,7 +3614,7 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
return;
}
start_time = ktime_get_ns();
start_time = ktime_get();
if (chan->band_type == RTW89_BAND_2G)
power = power_2g;
@@ -3738,12 +3739,12 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
rtw8852bx_bb_restore_tssi(rtwdev, phy, &tssi_bak);
rtw8852bx_bb_tx_mode_switch(rtwdev, phy, 0);
finish_time = ktime_get_ns();
tssi_info->tssi_alimk_time += finish_time - start_time;
this_time = ktime_us_delta(ktime_get(), start_time);
tssi_info->tssi_alimk_time += this_time;
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[TSSI PA K] %s processing time = %d ms\n", __func__,
tssi_info->tssi_alimk_time);
"[TSSI PA K] %s processing time = %lld us (acc = %llu us)\n",
__func__, this_time, tssi_info->tssi_alimk_time);
}
void rtw8852b_dpk_init(struct rtw89_dev *rtwdev)

View File

@@ -710,6 +710,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
@@ -745,6 +746,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.try_ce_fw = true,
.bbmcu_nr = 0,
.needed_fw_elms = RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ,
.fw_blacklist = &rtw89_fw_blacklist_default,
.fifo_size = 458752,
.small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
@@ -783,10 +785,13 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
.support_ant_gain = true,
.support_tas = false,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.rx_freq_frome_ie = true,
.hw_sec_hdr = false,
.hw_mgmt_tx_encrypt = false,
.hw_tkip_crypto = true,
.rf_path_num = 2,
.tx_nss = 2,
.rx_nss = 2,

View File

@@ -3663,9 +3663,10 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
u8 ch_idx = _tssi_ch_to_idx(rtwdev, channel);
struct rtw8852bx_bb_tssi_bak tssi_bak;
s32 aliment_diff, tssi_cw_default;
u32 start_time, finish_time;
u32 bb_reg_backup[8] = {};
ktime_t start_time;
const s16 *power;
s64 this_time;
u8 band;
bool ok;
u32 tmp;
@@ -3675,7 +3676,7 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
"======> %s channel=%d path=%d\n", __func__, channel,
path);
start_time = ktime_get_ns();
start_time = ktime_get();
if (chan->band_type == RTW89_BAND_2G)
power = power_2g;
@@ -3802,12 +3803,12 @@ static void _tssi_alimentk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
rtw8852bx_bb_restore_tssi(rtwdev, phy, &tssi_bak);
rtw8852bx_bb_tx_mode_switch(rtwdev, phy, 0);
finish_time = ktime_get_ns();
tssi_info->tssi_alimk_time += finish_time - start_time;
this_time = ktime_us_delta(ktime_get(), start_time);
tssi_info->tssi_alimk_time += this_time;
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[TSSI PA K] %s processing time = %d ms\n", __func__,
tssi_info->tssi_alimk_time);
"[TSSI PA K] %s processing time = %lld us (acc = %llu us)\n",
__func__, this_time, tssi_info->tssi_alimk_time);
}
void rtw8852bt_dpk_init(struct rtw89_dev *rtwdev)

View File

@@ -12,6 +12,7 @@
#include "rtw8852c.h"
#include "rtw8852c_rfk.h"
#include "rtw8852c_table.h"
#include "sar.h"
#include "util.h"
#define RTW8852C_FW_FORMAT_MAX 1
@@ -2880,6 +2881,7 @@ static int rtw8852c_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
static const struct rtw89_chanctx_listener rtw8852c_chanctx_listener = {
.callbacks[RTW89_CHANCTX_CALLBACK_RFK] = rtw8852c_rfk_chanctx_cb,
.callbacks[RTW89_CHANCTX_CALLBACK_TAS] = rtw89_tas_chanctx_cb,
};
#ifdef CONFIG_PM
@@ -2941,6 +2943,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl,
.h2c_ampdu_cmac_tbl = NULL,
.h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl,
.h2c_default_dmac_tbl = NULL,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam,
@@ -2967,6 +2970,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.try_ce_fw = false,
.bbmcu_nr = 0,
.needed_fw_elms = 0,
.fw_blacklist = &rtw89_fw_blacklist_default,
.fifo_size = 458752,
.small_fifo_size = false,
.dle_scc_rsvd_size = 0,
@@ -3009,10 +3013,13 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
BIT(NL80211_CHAN_WIDTH_160),
.support_unii4 = true,
.support_ant_gain = true,
.support_tas = true,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = true,
.rx_freq_frome_ie = false,
.hw_sec_hdr = true,
.hw_mgmt_tx_encrypt = true,
.hw_tkip_crypto = true,
.rf_path_num = 2,
.tx_nss = 2,
.rx_nss = 2,

View File

@@ -2156,6 +2156,56 @@ static void rtw8922a_set_txpwr_ref(struct rtw89_dev *rtwdev,
B_BE_PWR_REF_CTRL_CCK, ref_cck);
}
static const struct rtw89_reg_def rtw8922a_txpwr_ref[][3] = {
{{ .addr = R_TXAGC_REF_DBM_P0, .mask = B_TXAGC_OFDM_REF_DBM_P0},
{ .addr = R_TXAGC_REF_DBM_P0, .mask = B_TXAGC_CCK_REF_DBM_P0},
{ .addr = R_TSSI_K_P0, .mask = B_TSSI_K_OFDM_P0}
},
{{ .addr = R_TXAGC_REF_DBM_RF1_P0, .mask = B_TXAGC_OFDM_REF_DBM_RF1_P0},
{ .addr = R_TXAGC_REF_DBM_RF1_P0, .mask = B_TXAGC_CCK_REF_DBM_RF1_P0},
{ .addr = R_TSSI_K_RF1_P0, .mask = B_TSSI_K_OFDM_RF1_P0}
},
};
static void rtw8922a_set_txpwr_diff(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
s16 pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan);
const struct rtw89_chip_info *chip = rtwdev->chip;
static const u32 path_ofst[] = {0x0, 0x100};
const struct rtw89_reg_def *txpwr_ref;
static const s16 tssi_k_base = 0x12;
s16 tssi_k_ofst = abs(pwr_ofst) + tssi_k_base;
s16 ofst_dec[RF_PATH_NUM_8922A];
s16 tssi_k[RF_PATH_NUM_8922A];
s16 pwr_ref_ofst;
s16 pwr_ref = 0;
u8 i;
if (rtwdev->hal.cv == CHIP_CAV)
pwr_ref = 16;
pwr_ref <<= chip->txpwr_factor_rf;
pwr_ref_ofst = pwr_ref - rtw89_phy_txpwr_bb_to_rf(rtwdev, abs(pwr_ofst));
ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? pwr_ref : pwr_ref_ofst;
ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ref_ofst : pwr_ref;
tssi_k[RF_PATH_A] = pwr_ofst > 0 ? tssi_k_base : tssi_k_ofst;
tssi_k[RF_PATH_B] = pwr_ofst > 0 ? tssi_k_ofst : tssi_k_base;
for (i = 0; i < RF_PATH_NUM_8922A; i++) {
txpwr_ref = rtw8922a_txpwr_ref[phy_idx];
rtw89_phy_write32_mask(rtwdev, txpwr_ref[0].addr + path_ofst[i],
txpwr_ref[0].mask, ofst_dec[i]);
rtw89_phy_write32_mask(rtwdev, txpwr_ref[1].addr + path_ofst[i],
txpwr_ref[1].mask, ofst_dec[i]);
rtw89_phy_write32_mask(rtwdev, txpwr_ref[2].addr + path_ofst[i],
txpwr_ref[2].mask, tssi_k[i]);
}
}
static void rtw8922a_bb_tx_triangular(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
@@ -2192,6 +2242,8 @@ static void rtw8922a_set_txpwr(struct rtw89_dev *rtwdev,
rtw8922a_set_tx_shape(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
rtw8922a_set_txpwr_diff(rtwdev, chan, phy_idx);
rtw8922a_set_txpwr_ref(rtwdev, phy_idx);
}
static void rtw8922a_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
@@ -2702,6 +2754,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
.h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl_g7,
.h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl_g7,
.h2c_ampdu_cmac_tbl = rtw89_fw_h2c_ampdu_cmac_tbl_g7,
.h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl_g7,
.h2c_default_dmac_tbl = rtw89_fw_h2c_default_dmac_tbl_v2,
.h2c_update_beacon = rtw89_fw_h2c_update_beacon_be,
.h2c_ba_cam = rtw89_fw_h2c_ba_cam_v1,
@@ -2728,6 +2781,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.try_ce_fw = false,
.bbmcu_nr = 1,
.needed_fw_elms = RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS,
.fw_blacklist = &rtw89_fw_blacklist_default,
.fifo_size = 589824,
.small_fifo_size = false,
.dle_scc_rsvd_size = 0,
@@ -2767,11 +2821,14 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160),
.support_unii4 = true,
.support_ant_gain = false,
.support_ant_gain = true,
.support_tas = false,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = false,
.rx_freq_frome_ie = false,
.hw_sec_hdr = true,
.hw_mgmt_tx_encrypt = true,
.hw_tkip_crypto = true,
.rf_path_num = 2,
.tx_nss = 2,
.rx_nss = 2,

View File

@@ -7,10 +7,16 @@
#include "phy.h"
#include "reg.h"
#include "sar.h"
#include "util.h"
#define RTW89_TAS_FACTOR 2 /* unit: 0.25 dBm */
#define RTW89_TAS_SAR_GAP (1 << RTW89_TAS_FACTOR)
#define RTW89_TAS_DPR_GAP (1 << RTW89_TAS_FACTOR)
#define RTW89_TAS_DELTA (2 << RTW89_TAS_FACTOR)
#define RTW89_TAS_TX_RATIO_THRESHOLD 70
#define RTW89_TAS_DFLT_TX_RATIO 80
#define RTW89_TAS_DPR_ON_OFFSET (RTW89_TAS_DELTA + RTW89_TAS_SAR_GAP)
#define RTW89_TAS_DPR_OFF_OFFSET (4 << RTW89_TAS_FACTOR)
static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
u32 center_freq)
@@ -117,8 +123,8 @@ static s8 rtw89_txpwr_sar_to_mac(struct rtw89_dev *rtwdev, u8 fct, s32 cfg)
RTW89_SAR_TXPWR_MAC_MAX);
}
static s8 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl,
s8 cfg)
static s32 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl,
s32 cfg)
{
const u8 fct = sar_hdl->txpwr_factor_sar;
@@ -128,8 +134,8 @@ static s8 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl,
return cfg >> (RTW89_TAS_FACTOR - fct);
}
static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl,
s8 cfg)
static s32 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl,
s32 cfg)
{
const u8 fct = sar_hdl->txpwr_factor_sar;
@@ -139,13 +145,43 @@ static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl,
return cfg << (RTW89_TAS_FACTOR - fct);
}
static bool rtw89_tas_is_active(struct rtw89_dev *rtwdev)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
struct rtw89_vif *rtwvif;
if (!tas->enable)
return false;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
if (ieee80211_vif_is_mld(rtwvif_to_vif(rtwvif)))
return false;
}
return true;
}
static const char *rtw89_tas_state_str(enum rtw89_tas_state state)
{
switch (state) {
case RTW89_TAS_STATE_DPR_OFF:
return "DPR OFF";
case RTW89_TAS_STATE_DPR_ON:
return "DPR ON";
case RTW89_TAS_STATE_STATIC_SAR:
return "STATIC SAR";
default:
return NULL;
}
}
s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
{
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
struct rtw89_tas_info *tas = &rtwdev->tas;
s8 delta;
s32 offset;
int ret;
s32 cfg;
u8 fct;
@@ -159,15 +195,17 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
if (ret)
return RTW89_SAR_TXPWR_MAC_MAX;
if (tas->enable) {
if (rtw89_tas_is_active(rtwdev)) {
switch (tas->state) {
case RTW89_TAS_STATE_DPR_OFF:
return RTW89_SAR_TXPWR_MAC_MAX;
case RTW89_TAS_STATE_DPR_ON:
delta = rtw89_txpwr_tas_to_sar(sar_hdl, tas->delta);
cfg -= delta;
offset = rtw89_txpwr_tas_to_sar(sar_hdl, RTW89_TAS_DPR_OFF_OFFSET);
cfg += offset;
break;
case RTW89_TAS_STATE_DPR_FORBID:
case RTW89_TAS_STATE_DPR_ON:
offset = rtw89_txpwr_tas_to_sar(sar_hdl, RTW89_TAS_DPR_ON_OFFSET);
cfg -= offset;
break;
case RTW89_TAS_STATE_STATIC_SAR:
default:
break;
}
@@ -223,13 +261,23 @@ int rtw89_print_tas(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
struct rtw89_tas_info *tas = &rtwdev->tas;
char *p = buf, *end = buf + bufsz;
if (!tas->enable) {
if (!rtw89_tas_is_active(rtwdev)) {
p += scnprintf(p, end - p, "no TAS is applied\n");
goto out;
}
p += scnprintf(p, end - p, "DPR gap: %d\n", tas->dpr_gap);
p += scnprintf(p, end - p, "TAS delta: %d\n", tas->delta);
p += scnprintf(p, end - p, "State: %s\n",
rtw89_tas_state_str(tas->state));
p += scnprintf(p, end - p, "Average time: %d\n",
tas->window_size * 2);
p += scnprintf(p, end - p, "SAR gap: %d dBm\n",
RTW89_TAS_SAR_GAP >> RTW89_TAS_FACTOR);
p += scnprintf(p, end - p, "DPR gap: %d dBm\n",
RTW89_TAS_DPR_GAP >> RTW89_TAS_FACTOR);
p += scnprintf(p, end - p, "DPR ON offset: %d dBm\n",
RTW89_TAS_DPR_ON_OFFSET >> RTW89_TAS_FACTOR);
p += scnprintf(p, end - p, "DPR OFF offset: %d dBm\n",
RTW89_TAS_DPR_OFF_OFFSET >> RTW89_TAS_FACTOR);
out:
return p - buf;
@@ -250,6 +298,7 @@ static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar);
rtw89_core_set_chip_txpwr(rtwdev);
rtw89_tas_reset(rtwdev, false);
return 0;
}
@@ -314,65 +363,174 @@ int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
return rtw89_apply_sar_common(rtwdev, &sar_common);
}
static void rtw89_tas_state_update(struct rtw89_dev *rtwdev)
static bool rtw89_tas_query_sar_config(struct rtw89_dev *rtwdev, s32 *cfg)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
struct rtw89_tas_info *tas = &rtwdev->tas;
s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT;
s32 dpr_on_threshold, dpr_off_threshold, cfg;
enum rtw89_tas_state state = tas->state;
const struct rtw89_chan *chan;
int ret;
lockdep_assert_wiphy(rtwdev->hw->wiphy);
if (src == RTW89_SAR_SOURCE_NONE)
return;
return false;
chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg);
ret = sar_hdl->query_sar_config(rtwdev, chan->freq, cfg);
if (ret)
return;
return false;
cfg = rtw89_txpwr_sar_to_tas(sar_hdl, cfg);
*cfg = rtw89_txpwr_sar_to_tas(sar_hdl, *cfg);
if (tas->delta >= cfg) {
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"TAS delta exceed SAR limit\n");
state = RTW89_TAS_STATE_DPR_FORBID;
goto out;
}
return true;
}
dpr_on_threshold = cfg;
dpr_off_threshold = cfg - tas->dpr_gap;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"DPR_ON thold: %d, DPR_OFF thold: %d, txpwr_avg: %d\n",
dpr_on_threshold, dpr_off_threshold, txpwr_avg);
static void rtw89_tas_state_update(struct rtw89_dev *rtwdev,
enum rtw89_tas_state state)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
if (txpwr_avg >= dpr_on_threshold)
state = RTW89_TAS_STATE_DPR_ON;
else if (txpwr_avg < dpr_off_threshold)
state = RTW89_TAS_STATE_DPR_OFF;
out:
if (tas->state == state)
return;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"TAS old state: %d, new state: %d\n", tas->state, state);
rtw89_debug(rtwdev, RTW89_DBG_SAR, "tas: switch state: %s -> %s\n",
rtw89_tas_state_str(tas->state), rtw89_tas_state_str(state));
tas->state = state;
rtw89_core_set_chip_txpwr(rtwdev);
}
static u32 rtw89_tas_get_window_size(struct rtw89_dev *rtwdev)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
u8 band = chan->band_type;
u8 regd = rtw89_regd_get(rtwdev, band);
switch (regd) {
default:
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"tas: regd: %u is unhandled\n", regd);
fallthrough;
case RTW89_IC:
case RTW89_KCC:
return 180;
case RTW89_FCC:
switch (band) {
case RTW89_BAND_2G:
return 50;
case RTW89_BAND_5G:
return 30;
case RTW89_BAND_6G:
default:
return 15;
}
break;
}
}
static void rtw89_tas_window_update(struct rtw89_dev *rtwdev)
{
u32 window_size = rtw89_tas_get_window_size(rtwdev);
struct rtw89_tas_info *tas = &rtwdev->tas;
u64 total_txpwr = 0;
u8 head_idx;
u32 i, j;
WARN_ON_ONCE(tas->window_size > RTW89_TAS_TXPWR_WINDOW);
if (tas->window_size == window_size)
return;
rtw89_debug(rtwdev, RTW89_DBG_SAR, "tas: window update: %u -> %u\n",
tas->window_size, window_size);
head_idx = (tas->txpwr_tail_idx - window_size + 1 + RTW89_TAS_TXPWR_WINDOW) %
RTW89_TAS_TXPWR_WINDOW;
for (i = 0; i < window_size; i++) {
j = (head_idx + i) % RTW89_TAS_TXPWR_WINDOW;
total_txpwr += tas->txpwr_history[j];
}
tas->window_size = window_size;
tas->total_txpwr = total_txpwr;
tas->txpwr_head_idx = head_idx;
}
static void rtw89_tas_history_update(struct rtw89_dev *rtwdev)
{
struct rtw89_bb_ctx *bb = rtw89_get_bb_ctx(rtwdev, RTW89_PHY_0);
struct rtw89_env_monitor_info *env = &bb->env_monitor;
struct rtw89_tas_info *tas = &rtwdev->tas;
u8 tx_ratio = env->ifs_clm_tx_ratio;
u64 instant_txpwr, txpwr;
/* txpwr in unit of linear(mW) multiply by percentage */
if (tx_ratio == 0) {
/* special case: idle tx power
* use -40 dBm * 100 tx ratio
*/
instant_txpwr = rtw89_db_to_linear(-40);
txpwr = instant_txpwr * 100;
} else {
instant_txpwr = tas->instant_txpwr;
txpwr = instant_txpwr * tx_ratio;
}
tas->total_txpwr += txpwr - tas->txpwr_history[tas->txpwr_head_idx];
tas->total_tx_ratio += tx_ratio - tas->tx_ratio_history[tas->tx_ratio_idx];
tas->tx_ratio_history[tas->tx_ratio_idx] = tx_ratio;
tas->txpwr_head_idx = (tas->txpwr_head_idx + 1) % RTW89_TAS_TXPWR_WINDOW;
tas->txpwr_tail_idx = (tas->txpwr_tail_idx + 1) % RTW89_TAS_TXPWR_WINDOW;
tas->tx_ratio_idx = (tas->tx_ratio_idx + 1) % RTW89_TAS_TX_RATIO_WINDOW;
tas->txpwr_history[tas->txpwr_tail_idx] = txpwr;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"tas: instant_txpwr: %d, tx_ratio: %u, txpwr: %d\n",
rtw89_linear_to_db_quarter(instant_txpwr), tx_ratio,
rtw89_linear_to_db_quarter(div_u64(txpwr, PERCENT)));
}
static void rtw89_tas_rolling_average(struct rtw89_dev *rtwdev)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
s32 dpr_on_threshold, dpr_off_threshold;
enum rtw89_tas_state state;
u16 tx_ratio_avg;
s32 txpwr_avg;
u64 linear;
linear = DIV_ROUND_DOWN_ULL(tas->total_txpwr, tas->window_size * PERCENT);
txpwr_avg = rtw89_linear_to_db_quarter(linear);
tx_ratio_avg = tas->total_tx_ratio / RTW89_TAS_TX_RATIO_WINDOW;
dpr_on_threshold = tas->dpr_on_threshold;
dpr_off_threshold = tas->dpr_off_threshold;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"tas: DPR_ON: %d, DPR_OFF: %d, txpwr_avg: %d, tx_ratio_avg: %u\n",
dpr_on_threshold, dpr_off_threshold, txpwr_avg, tx_ratio_avg);
if (tx_ratio_avg >= RTW89_TAS_TX_RATIO_THRESHOLD)
state = RTW89_TAS_STATE_STATIC_SAR;
else if (txpwr_avg >= dpr_on_threshold)
state = RTW89_TAS_STATE_DPR_ON;
else if (txpwr_avg < dpr_off_threshold)
state = RTW89_TAS_STATE_DPR_OFF;
else
return;
rtw89_tas_state_update(rtwdev, state);
}
void rtw89_tas_init(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_tas_info *tas = &rtwdev->tas;
struct rtw89_acpi_dsm_result res = {};
int ret;
u8 val;
if (!chip->support_tas)
return;
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_TAS_EN, &res);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_SAR,
@@ -396,65 +554,116 @@ void rtw89_tas_init(struct rtw89_dev *rtwdev)
rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n");
return;
}
tas->dpr_gap = RTW89_TAS_DPR_GAP;
tas->delta = RTW89_TAS_DELTA;
}
void rtw89_tas_reset(struct rtw89_dev *rtwdev)
void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force)
{
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
struct rtw89_tas_info *tas = &rtwdev->tas;
u64 linear;
s32 cfg;
int i;
if (!tas->enable)
if (!rtw89_tas_is_active(rtwdev))
return;
memset(&tas->txpwr_history, 0, sizeof(tas->txpwr_history));
tas->total_txpwr = 0;
tas->cur_idx = 0;
tas->state = RTW89_TAS_STATE_DPR_OFF;
}
if (!rtw89_tas_query_sar_config(rtwdev, &cfg))
return;
static const struct rtw89_reg_def txpwr_regs[] = {
{R_PATH0_TXPWR, B_PATH0_TXPWR},
{R_PATH1_TXPWR, B_PATH1_TXPWR},
};
tas->dpr_on_threshold = cfg - RTW89_TAS_SAR_GAP;
tas->dpr_off_threshold = cfg - RTW89_TAS_SAR_GAP - RTW89_TAS_DPR_GAP;
/* avoid history reset after new SAR apply */
if (!force && tas->keep_history)
return;
linear = rtw89_db_quarter_to_linear(cfg) * RTW89_TAS_DFLT_TX_RATIO;
for (i = 0; i < RTW89_TAS_TXPWR_WINDOW; i++)
tas->txpwr_history[i] = linear;
for (i = 0; i < RTW89_TAS_TX_RATIO_WINDOW; i++)
tas->tx_ratio_history[i] = RTW89_TAS_DFLT_TX_RATIO;
tas->total_tx_ratio = RTW89_TAS_DFLT_TX_RATIO * RTW89_TAS_TX_RATIO_WINDOW;
tas->total_txpwr = linear * RTW89_TAS_TXPWR_WINDOW;
tas->window_size = RTW89_TAS_TXPWR_WINDOW;
tas->txpwr_head_idx = 0;
tas->txpwr_tail_idx = RTW89_TAS_TXPWR_WINDOW - 1;
tas->tx_ratio_idx = 0;
tas->state = RTW89_TAS_STATE_DPR_OFF;
tas->backup_state = RTW89_TAS_STATE_DPR_OFF;
tas->keep_history = true;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"tas: band: %u, freq: %u\n", chan->band_type, chan->freq);
}
void rtw89_tas_track(struct rtw89_dev *rtwdev)
{
struct rtw89_bb_ctx *bb = rtw89_get_bb_ctx(rtwdev, RTW89_PHY_0);
struct rtw89_env_monitor_info *env = &bb->env_monitor;
const enum rtw89_sar_sources src = rtwdev->sar.src;
u8 max_nss_num = rtwdev->chip->rf_path_num;
struct rtw89_tas_info *tas = &rtwdev->tas;
s16 tmp, txpwr, instant_txpwr = 0;
u32 val;
int i;
struct rtw89_hal *hal = &rtwdev->hal;
s32 cfg;
if (!tas->enable || src == RTW89_SAR_SOURCE_NONE)
if (hal->disabled_dm_bitmap & BIT(RTW89_DM_TAS))
return;
if (env->ccx_watchdog_result != RTW89_PHY_ENV_MON_IFS_CLM)
if (!rtw89_tas_is_active(rtwdev))
return;
for (i = 0; i < max_nss_num; i++) {
val = rtw89_phy_read32_mask(rtwdev, txpwr_regs[i].addr,
txpwr_regs[i].mask);
tmp = sign_extend32(val, 8);
if (tmp <= 0)
return;
instant_txpwr += tmp;
if (!rtw89_tas_query_sar_config(rtwdev, &cfg) || tas->block_regd) {
rtw89_tas_state_update(rtwdev, RTW89_TAS_STATE_STATIC_SAR);
return;
}
instant_txpwr /= max_nss_num;
/* in unit of 0.25 dBm multiply by percentage */
txpwr = instant_txpwr * env->ifs_clm_tx_ratio;
tas->total_txpwr += txpwr - tas->txpwr_history[tas->cur_idx];
tas->txpwr_history[tas->cur_idx] = txpwr;
rtw89_debug(rtwdev, RTW89_DBG_SAR,
"instant_txpwr: %d, tx_ratio: %d, txpwr: %d\n",
instant_txpwr, env->ifs_clm_tx_ratio, txpwr);
if (tas->pause)
return;
tas->cur_idx = (tas->cur_idx + 1) % RTW89_TAS_MAX_WINDOW;
rtw89_tas_state_update(rtwdev);
rtw89_tas_window_update(rtwdev);
rtw89_tas_history_update(rtwdev);
rtw89_tas_rolling_average(rtwdev);
}
void rtw89_tas_scan(struct rtw89_dev *rtwdev, bool start)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
s32 cfg;
if (!rtw89_tas_is_active(rtwdev))
return;
if (!rtw89_tas_query_sar_config(rtwdev, &cfg))
return;
if (start) {
tas->backup_state = tas->state;
rtw89_tas_state_update(rtwdev, RTW89_TAS_STATE_STATIC_SAR);
} else {
rtw89_tas_state_update(rtwdev, tas->backup_state);
}
}
void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_state state)
{
struct rtw89_tas_info *tas = &rtwdev->tas;
s32 cfg;
if (!rtw89_tas_is_active(rtwdev))
return;
if (!rtw89_tas_query_sar_config(rtwdev, &cfg))
return;
switch (state) {
case RTW89_CHANCTX_STATE_MCC_START:
tas->pause = true;
rtw89_tas_state_update(rtwdev, RTW89_TAS_STATE_STATIC_SAR);
break;
case RTW89_CHANCTX_STATE_MCC_STOP:
tas->pause = false;
break;
default:
break;
}
}
EXPORT_SYMBOL(rtw89_tas_chanctx_cb);

View File

@@ -25,7 +25,10 @@ int rtw89_print_tas(struct rtw89_dev *rtwdev, char *buf, size_t bufsz);
int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
void rtw89_tas_init(struct rtw89_dev *rtwdev);
void rtw89_tas_reset(struct rtw89_dev *rtwdev);
void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force);
void rtw89_tas_track(struct rtw89_dev *rtwdev);
void rtw89_tas_scan(struct rtw89_dev *rtwdev, bool start);
void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_state state);
#endif

View File

@@ -4,106 +4,151 @@
#include "util.h"
#define FRAC_ROWS 3
#define FRAC_ROW_MAX (FRAC_ROWS - 1)
#define NORM_ROW_MIN FRAC_ROWS
#define RTW89_DBM_QUARTER_FACTOR 2
#define RTW89_MIN_DBM (-41.25 * (1 << RTW89_DBM_QUARTER_FACTOR))
#define RTW89_MAX_DBM (96 * (1 << RTW89_DBM_QUARTER_FACTOR))
#define RTW89_DB_INVERT_TABLE_OFFSET (-RTW89_MIN_DBM)
static const u32 db_invert_table[12][8] = {
/* rows 0~2 in unit of U(32,3) */
{10, 13, 16, 20, 25, 32, 40, 50},
{64, 80, 101, 128, 160, 201, 256, 318},
{401, 505, 635, 800, 1007, 1268, 1596, 2010},
/* rows 3~11 in unit of U(32,0) */
{316, 398, 501, 631, 794, 1000, 1259, 1585},
{1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000},
{12589, 15849, 19953, 25119, 31623, 39811, 50119, 63098},
{79433, 100000, 125893, 158489, 199526, 251189, 316228, 398107},
{501187, 630957, 794328, 1000000, 1258925, 1584893, 1995262, 2511886},
{3162278, 3981072, 5011872, 6309573, 7943282, 1000000, 12589254,
15848932},
{19952623, 25118864, 31622777, 39810717, 50118723, 63095734, 79432823,
100000000},
{125892541, 158489319, 199526232, 251188643, 316227766, 398107171,
501187234, 630957345},
{794328235, 1000000000, 1258925412, 1584893192, 1995262315, 2511886432U,
3162277660U, 3981071706U},
static const u64 db_invert_table[] = {
/* in unit of 0.000001 */
75, 79, 84, 89, 94, 100, 106, 112, 119, 126, 133, 141, 150, 158, 168, 178, 188,
200, 211, 224, 237, 251, 266, 282, 299, 316, 335, 355, 376, 398, 422, 447, 473,
501, 531, 562, 596, 631, 668, 708, 750, 794, 841, 891, 944, 1000, 1059, 1122, 1189,
1259, 1334, 1413, 1496, 1585, 1679, 1778, 1884, 1995, 2113, 2239, 2371, 2512, 2661,
2818, 2985, 3162, 3350, 3548, 3758, 3981, 4217, 4467, 4732, 5012, 5309, 5623, 5957,
6310, 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, 10593, 11220, 11885, 12589,
13335, 14125, 14962, 15849, 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, 42170, 44668, 47315, 50119,
53088, 56234, 59566, 63096, 66834, 70795, 74989, 79433, 84140, 89125, 94406, 100000,
105925, 112202, 118850, 125893, 133352, 141254, 149624, 158489, 167880, 177828,
188365, 199526, 211349, 223872, 237137, 251189, 266073, 281838, 298538, 316228,
334965, 354813, 375837, 398107, 421697, 446684, 473151, 501187, 530884, 562341,
595662, 630957, 668344, 707946, 749894, 794328, 841395, 891251, 944061, 1000000,
1059254, 1122018, 1188502, 1258925, 1333521, 1412538, 1496236, 1584893, 1678804,
1778279, 1883649, 1995262, 2113489, 2238721, 2371374, 2511886, 2660725, 2818383,
2985383, 3162278, 3349654, 3548134, 3758374, 3981072, 4216965, 4466836, 4731513,
5011872, 5308844, 5623413, 5956621, 6309573, 6683439, 7079458, 7498942, 7943282,
8413951, 8912509, 9440609, 10000000, 10592537, 11220185, 11885022, 12589254,
13335214, 14125375, 14962357, 15848932, 16788040, 17782794, 18836491, 19952623,
21134890, 22387211, 23713737, 25118864, 26607251, 28183829, 29853826, 31622777,
33496544, 35481339, 37583740, 39810717, 42169650, 44668359, 47315126, 50118723,
53088444, 56234133, 59566214, 63095734, 66834392, 70794578, 74989421, 79432823,
84139514, 89125094, 94406088, 100000000, 105925373, 112201845, 118850223, 125892541,
133352143, 141253754, 149623566, 158489319, 167880402, 177827941, 188364909, 199526231,
211348904, 223872114, 237137371, 251188643, 266072506, 281838293, 298538262, 316227766,
334965439, 354813389, 375837404, 398107171, 421696503, 446683592, 473151259, 501187234,
530884444, 562341325, 595662144, 630957344, 668343918, 707945784, 749894209, 794328235,
841395142, 891250938, 944060876, 1000000000, 1059253725, 1122018454, 1188502227,
1258925412, 1333521432, 1412537545, 1496235656, 1584893192, 1678804018, 1778279410,
1883649089, 1995262315, 2113489040, 2238721139, 2371373706, 2511886432, 2660725060,
2818382931, 2985382619, 3162277660, 3349654392, 3548133892, 3758374043, 3981071706,
4216965034, 4466835922ULL, 4731512590ULL, 5011872336ULL, 5308844442ULL, 5623413252ULL,
5956621435ULL, 6309573445ULL, 6683439176ULL, 7079457844ULL, 7498942093ULL,
7943282347ULL, 8413951416ULL, 8912509381ULL, 9440608763ULL, 10000000000ULL,
10592537252ULL, 11220184543ULL, 11885022274ULL, 12589254118ULL, 13335214322ULL,
14125375446ULL, 14962356561ULL, 15848931925ULL, 16788040181ULL, 17782794100ULL,
18836490895ULL, 19952623150ULL, 21134890398ULL, 22387211386ULL, 23713737057ULL,
25118864315ULL, 26607250598ULL, 28183829313ULL, 29853826189ULL, 31622776602ULL,
33496543916ULL, 35481338923ULL, 37583740429ULL, 39810717055ULL, 42169650343ULL,
44668359215ULL, 47315125896ULL, 50118723363ULL, 53088444423ULL, 56234132519ULL,
59566214353ULL, 63095734448ULL, 66834391757ULL, 70794578438ULL, 74989420933ULL,
79432823472ULL, 84139514165ULL, 89125093813ULL, 94406087629ULL, 100000000000ULL,
105925372518ULL, 112201845430ULL, 118850222744ULL, 125892541179ULL, 133352143216ULL,
141253754462ULL, 149623565609ULL, 158489319246ULL, 167880401812ULL, 177827941004ULL,
188364908949ULL, 199526231497ULL, 211348903984ULL, 223872113857ULL, 237137370566ULL,
251188643151ULL, 266072505980ULL, 281838293126ULL, 298538261892ULL, 316227766017ULL,
334965439158ULL, 354813389234ULL, 375837404288ULL, 398107170553ULL, 421696503429ULL,
446683592151ULL, 473151258961ULL, 501187233627ULL, 530884444231ULL, 562341325190ULL,
595662143529ULL, 630957344480ULL, 668343917569ULL, 707945784384ULL, 749894209332ULL,
794328234724ULL, 841395141645ULL, 891250938134ULL, 944060876286ULL, 1000000000000ULL,
1059253725177ULL, 1122018454302ULL, 1188502227437ULL, 1258925411794ULL,
1333521432163ULL, 1412537544623ULL, 1496235656094ULL, 1584893192461ULL,
1678804018123ULL, 1778279410039ULL, 1883649089490ULL, 1995262314969ULL,
2113489039837ULL, 2238721138568ULL, 2371373705662ULL, 2511886431510ULL,
2660725059799ULL, 2818382931264ULL, 2985382618918ULL, 3162277660168ULL,
3349654391578ULL, 3548133892336ULL, 3758374042884ULL, 3981071705535ULL,
4216965034286ULL, 4466835921510ULL, 4731512589615ULL, 5011872336273ULL,
5308844442310ULL, 5623413251904ULL, 5956621435290ULL, 6309573444802ULL,
6683439175686ULL, 7079457843841ULL, 7498942093325ULL, 7943282347243ULL,
8413951416452ULL, 8912509381337ULL, 9440608762859ULL, 10000000000000ULL,
10592537251773ULL, 11220184543020ULL, 11885022274370ULL, 12589254117942ULL,
13335214321633ULL, 14125375446228ULL, 14962356560944ULL, 15848931924611ULL,
16788040181226ULL, 17782794100389ULL, 18836490894898ULL, 19952623149689ULL,
21134890398367ULL, 22387211385683ULL, 23713737056617ULL, 25118864315096ULL,
26607250597988ULL, 28183829312645ULL, 29853826189180ULL, 31622776601684ULL,
33496543915783ULL, 35481338923358ULL, 37583740428845ULL, 39810717055350ULL,
42169650342858ULL, 44668359215096ULL, 47315125896148ULL, 50118723362727ULL,
53088444423099ULL, 56234132519035ULL, 59566214352901ULL, 63095734448019ULL,
66834391756862ULL, 70794578438414ULL, 74989420933246ULL, 79432823472428ULL,
84139514164520ULL, 89125093813375ULL, 94406087628593ULL, 100000000000000ULL,
105925372517729ULL, 112201845430197ULL, 118850222743702ULL, 125892541179417ULL,
133352143216332ULL, 141253754462276ULL, 149623565609444ULL, 158489319246111ULL,
167880401812256ULL, 177827941003893ULL, 188364908948981ULL, 199526231496888ULL,
211348903983664ULL, 223872113856834ULL, 237137370566166ULL, 251188643150958ULL,
266072505979882ULL, 281838293126446ULL, 298538261891796ULL, 316227766016838ULL,
334965439157829ULL, 354813389233577ULL, 375837404288444ULL, 398107170553497ULL,
421696503428583ULL, 446683592150964ULL, 473151258961482ULL, 501187233627272ULL,
530884444230989ULL, 562341325190350ULL, 595662143529011ULL, 630957344480196ULL,
668343917568615ULL, 707945784384138ULL, 749894209332456ULL, 794328234724284ULL,
841395141645198ULL, 891250938133745ULL, 944060876285923ULL, 1000000000000000ULL,
1059253725177290ULL, 1122018454301970ULL, 1188502227437020ULL, 1258925411794170ULL,
1333521432163330ULL, 1412537544622760ULL, 1496235656094440ULL, 1584893192461110ULL,
1678804018122560ULL, 1778279410038920ULL, 1883649089489810ULL, 1995262314968890ULL,
2113489039836650ULL, 2238721138568340ULL, 2371373705661660ULL, 2511886431509590ULL,
2660725059798820ULL, 2818382931264460ULL, 2985382618917960ULL, 3162277660168380ULL,
3349654391578280ULL, 3548133892335770ULL, 3758374042884440ULL, 3981071705534970ULL
};
u32 rtw89_linear_2_db(u64 val)
s32 rtw89_linear_to_db_quarter(u64 val)
{
u8 i, j;
u32 dB;
int r = ARRAY_SIZE(db_invert_table) - 1;
int l = 0;
int m;
for (i = 0; i < 12; i++) {
for (j = 0; j < 8; j++) {
if (i <= FRAC_ROW_MAX &&
(val << RTW89_LINEAR_FRAC_BITS) <= db_invert_table[i][j])
goto cnt;
else if (i > FRAC_ROW_MAX && val <= db_invert_table[i][j])
goto cnt;
}
while (l <= r) {
m = l + (r - l) / 2;
if (db_invert_table[m] == val)
return m - (s32)RTW89_DB_INVERT_TABLE_OFFSET;
if (db_invert_table[m] > val)
r = m - 1;
else
l = m + 1;
}
return 96; /* maximum 96 dB */
cnt:
/* special cases */
if (j == 0 && i == 0)
goto end;
if (i == NORM_ROW_MIN && j == 0) {
if (db_invert_table[NORM_ROW_MIN][0] - val >
val - (db_invert_table[FRAC_ROW_MAX][7] >> RTW89_LINEAR_FRAC_BITS)) {
i = FRAC_ROW_MAX;
j = 7;
}
goto end;
}
if (i <= FRAC_ROW_MAX)
val <<= RTW89_LINEAR_FRAC_BITS;
/* compare difference to get precise dB */
if (j == 0) {
if (db_invert_table[i][j] - val >
val - db_invert_table[i - 1][7]) {
i--;
j = 7;
}
} else {
if (db_invert_table[i][j] - val >
val - db_invert_table[i][j - 1]) {
j--;
}
}
end:
dB = (i << 3) + j + 1;
return dB;
if (l >= ARRAY_SIZE(db_invert_table))
return RTW89_MAX_DBM;
else if (r < 0)
return RTW89_MIN_DBM;
else if (val - db_invert_table[r] <= db_invert_table[l] - val)
return r - (s32)RTW89_DB_INVERT_TABLE_OFFSET;
else
return l - (s32)RTW89_DB_INVERT_TABLE_OFFSET;
}
EXPORT_SYMBOL(rtw89_linear_2_db);
EXPORT_SYMBOL(rtw89_linear_to_db_quarter);
u64 rtw89_db_2_linear(u32 db)
s32 rtw89_linear_to_db(u64 val)
{
u64 linear;
u8 i, j;
if (db > 96)
db = 96;
else if (db < 1)
return 1;
i = (db - 1) >> 3;
j = (db - 1) & 0x7;
linear = db_invert_table[i][j];
if (i >= NORM_ROW_MIN)
linear = linear << RTW89_LINEAR_FRAC_BITS;
return linear;
return rtw89_linear_to_db_quarter(val) >> RTW89_DBM_QUARTER_FACTOR;
}
EXPORT_SYMBOL(rtw89_db_2_linear);
EXPORT_SYMBOL(rtw89_linear_to_db);
u64 rtw89_db_quarter_to_linear(s32 db)
{
/* supported range -41.25 to 96 dBm, in unit of 0.25 dBm */
db = clamp_t(s32, db, RTW89_MIN_DBM, RTW89_MAX_DBM);
db += (s32)RTW89_DB_INVERT_TABLE_OFFSET;
return db_invert_table[db];
}
EXPORT_SYMBOL(rtw89_db_quarter_to_linear);
u64 rtw89_db_to_linear(s32 db)
{
return rtw89_db_quarter_to_linear(db << RTW89_DBM_QUARTER_FACTOR);
}
EXPORT_SYMBOL(rtw89_db_to_linear);
void rtw89_might_trailing_ellipsis(char *buf, size_t size, ssize_t used)
{

View File

@@ -6,8 +6,6 @@
#include "core.h"
#define RTW89_LINEAR_FRAC_BITS 3
#define rtw89_iterate_vifs_bh(rtwdev, iterator, data) \
ieee80211_iterate_active_interfaces_atomic((rtwdev)->hw, \
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
@@ -75,8 +73,10 @@ static inline void ether_addr_copy_mask(u8 *dst, const u8 *src, u8 mask)
}
}
u32 rtw89_linear_2_db(u64 linear);
u64 rtw89_db_2_linear(u32 db);
s32 rtw89_linear_to_db_quarter(u64 val);
s32 rtw89_linear_to_db(u64 val);
u64 rtw89_db_quarter_to_linear(s32 db);
u64 rtw89_db_to_linear(s32 db);
void rtw89_might_trailing_ellipsis(char *buf, size_t size, ssize_t used);
#endif