From: Po-Hao Huang <phhuang@xxxxxxxxxxx> Register rrsr determines the response rate we send. In field tests, using rate higher than current tx rate could lead to difficulty for the receiving end to receive management/control frames. Calculate current modulation level by tx rate then cross out rate higher than those. Signed-off-by: Po-Hao Huang <phhuang@xxxxxxxxxxx> Signed-off-by: Ping-Ke Shih <pkshih@xxxxxxxxxxx> Reviewed-by: Brian Norris <briannorris@xxxxxxxxxxxx> --- drivers/net/wireless/realtek/rtw88/main.c | 3 + drivers/net/wireless/realtek/rtw88/main.h | 5 ++ drivers/net/wireless/realtek/rtw88/phy.c | 62 ++++++++++++++++++- drivers/net/wireless/realtek/rtw88/phy.h | 3 + drivers/net/wireless/realtek/rtw88/reg.h | 2 + drivers/net/wireless/realtek/rtw88/rtw8822c.h | 2 - 6 files changed, 74 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 757aaf45f65e..871496713f98 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -894,6 +894,7 @@ static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev, void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) { + struct rtw_dm_info *dm_info = &rtwdev->dm_info; struct ieee80211_sta *sta = si->sta; struct rtw_efuse *efuse = &rtwdev->efuse; struct rtw_hal *hal = &rtwdev->hal; @@ -938,6 +939,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) } else { wireless_set = WIRELESS_OFDM; } + dm_info->rrsr_val_init = RRSR_INIT_5G; } else if (hal->current_band_type == RTW_BAND_2G) { ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; if (sta->vht_cap.vht_supported) { @@ -955,6 +957,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) } else { wireless_set = WIRELESS_CCK | WIRELESS_OFDM; } + dm_info->rrsr_val_init = RRSR_INIT_2G; } else { rtw_err(rtwdev, "Unknown band type\n"); wireless_set = 0; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 87524199d0d6..296a9b4da4fd 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1495,6 +1495,9 @@ struct rtw_iqk_info { } result; }; +#define RRSR_INIT_2G 0x15f +#define RRSR_INIT_5G 0x150 + struct rtw_dm_info { u32 cck_fa_cnt; u32 ofdm_fa_cnt; @@ -1525,6 +1528,8 @@ struct rtw_dm_info { u8 cck_gi_l_bnd; u8 tx_rate; + u32 rrsr_val_init; + u32 rrsr_mask_min; u8 thermal_avg[RTW_RF_PATH_MAX]; u8 thermal_meter_k; s8 delta_power_index[RTW_RF_PATH_MAX]; diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index d44960cd940c..e114ddecac09 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -465,6 +465,60 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); } +static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx) +{ + u8 rate_order; + + rate_order = rate_idx; + + if (rate_idx >= DESC_RATEVHT4SS_MCS0) + rate_order -= DESC_RATEVHT4SS_MCS0; + else if (rate_idx >= DESC_RATEVHT3SS_MCS0) + rate_order -= DESC_RATEVHT3SS_MCS0; + else if (rate_idx >= DESC_RATEVHT2SS_MCS0) + rate_order -= DESC_RATEVHT2SS_MCS0; + else if (rate_idx >= DESC_RATEVHT1SS_MCS0) + rate_order -= DESC_RATEVHT1SS_MCS0; + else if (rate_idx >= DESC_RATEMCS24) + rate_order -= DESC_RATEMCS24; + else if (rate_idx >= DESC_RATEMCS16) + rate_order -= DESC_RATEMCS16; + else if (rate_idx >= DESC_RATEMCS8) + rate_order -= DESC_RATEMCS8; + else if (rate_idx >= DESC_RATEMCS0) + rate_order -= DESC_RATEMCS0; + else if (rate_idx >= DESC_RATE6M) + rate_order -= DESC_RATE6M; + else + rate_order -= DESC_RATE1M; + + if (rate_idx >= DESC_RATEMCS0 || rate_order == 0) + rate_order++; + + return GENMASK(rate_order + RRSR_RATE_ORDER_CCK_LEN - 1, 0); +} + +static void rtw_phy_rrsr_mask_min_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw_dev *rtwdev = (struct rtw_dev *)data; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u32 mask = 0; + + mask = rtw_phy_get_rrsr_mask(rtwdev, si->ra_report.desc_rate); + if (mask < dm_info->rrsr_mask_min) + dm_info->rrsr_mask_min = mask; +} + +static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX; + rtw_iterate_stas_atomic(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev); + rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min); +} + static void rtw_phy_dpk_track(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; @@ -561,13 +615,19 @@ static void rtw_phy_pwr_track(struct rtw_dev *rtwdev) rtwdev->chip->ops->pwr_track(rtwdev); } +static void rtw_phy_ra_track(struct rtw_dev *rtwdev) +{ + rtw_phy_ra_info_update(rtwdev); + rtw_phy_rrsr_update(rtwdev); +} + void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev) { /* for further calculation */ rtw_phy_statistics(rtwdev); rtw_phy_dig(rtwdev); rtw_phy_cck_pd(rtwdev); - rtw_phy_ra_info_update(rtwdev); + rtw_phy_ra_track(rtwdev); rtw_phy_dpk_track(rtwdev); rtw_phy_pwr_track(rtwdev); } diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index b924ed07630a..a4fcfb878550 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -185,4 +185,7 @@ enum rtw_phy_cck_pd_lv { #define LSSI_READ_EDGE_MASK 0x80000000 #define LSSI_READ_DATA_MASK 0xfffff +#define RRSR_RATE_ORDER_MAX 0xfffff +#define RRSR_RATE_ORDER_CCK_LEN 4 + #endif diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index cf9a3b674d30..ea518aa78552 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -306,6 +306,8 @@ #define REG_DARFRC 0x0430 #define REG_DARFRCH 0x0434 #define REG_RARFRCH 0x043C +#define REG_RRSR 0x0440 +#define BITS_RRSR_RSC GENMASK(22, 21) #define REG_ARFR0 0x0444 #define REG_ARFRH0 0x0448 #define REG_ARFR1_V1 0x044C diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h index 32b4771e04d0..bb2495b8609e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h @@ -164,8 +164,6 @@ const struct rtw_table name ## _tbl = { \ #define REG_ANAPARLDO_POW_MAC 0x0029 #define BIT_LDOE25_PON BIT(0) -#define REG_RRSR 0x0440 -#define BITS_RRSR_RSC (BIT(21) | BIT(22)) #define REG_TXDFIR0 0x808 #define REG_DFIRBW 0x810 -- 2.21.0