Commit 9eb071f8 authored by Chien-Hsun Liao's avatar Chien-Hsun Liao Committed by Kalle Valo
Browse files

rtw88: recover rates of rate adaptive mechanism



Some APs like CMW270 only support one phyrate and the function
rtw_update_rate_mask could disable that rate. To fix such problem, we
restore the rate mask if we find that the rate_mask is empty.

Signed-off-by: default avatarChien-Hsun Liao <ben.liao@realtek.com>
Signed-off-by: default avatarKuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220208082427.42433-2-pkshih@realtek.com
parent b478ff6b
Loading
Loading
Loading
Loading
+44 −23
Original line number Diff line number Diff line
@@ -1020,38 +1020,53 @@ static u8 get_rate_id(u8 wireless_set, enum rtw_bandwidth bw_mode, u8 tx_num)
#define RA_MASK_VHT_RATES	(RA_MASK_VHT_RATES_1SS | \
				 RA_MASK_VHT_RATES_2SS | \
				 RA_MASK_VHT_RATES_3SS)
#define RA_MASK_CCK_IN_BG	0x00005
#define RA_MASK_CCK_IN_HT	0x00005
#define RA_MASK_CCK_IN_VHT	0x00005
#define RA_MASK_OFDM_IN_VHT	0x00010
#define RA_MASK_OFDM_IN_HT_2G	0x00010
#define RA_MASK_OFDM_IN_HT_5G	0x00030

static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
				struct rtw_sta_info *si,
				u64 ra_mask, bool is_vht_enable,
				u8 wireless_set)
static u64 rtw_rate_mask_rssi(struct rtw_sta_info *si, u8 wireless_set)
{
	struct rtw_hal *hal = &rtwdev->hal;
	const struct cfg80211_bitrate_mask *mask = si->mask;
	u64 cfg_mask = GENMASK_ULL(63, 0);
	u8 rssi_level, band;
	u8 rssi_level = si->rssi_level;

	if (wireless_set == WIRELESS_CCK)
		return 0xffffffffffffffffULL;

	if (wireless_set != WIRELESS_CCK) {
		rssi_level = si->rssi_level;
	if (rssi_level == 0)
			ra_mask &= 0xffffffffffffffffULL;
		return 0xffffffffffffffffULL;
	else if (rssi_level == 1)
			ra_mask &= 0xfffffffffffffff0ULL;
		return 0xfffffffffffffff0ULL;
	else if (rssi_level == 2)
			ra_mask &= 0xffffffffffffefe0ULL;
		return 0xffffffffffffefe0ULL;
	else if (rssi_level == 3)
			ra_mask &= 0xffffffffffffcfc0ULL;
		return 0xffffffffffffcfc0ULL;
	else if (rssi_level == 4)
			ra_mask &= 0xffffffffffff8f80ULL;
		else if (rssi_level >= 5)
			ra_mask &= 0xffffffffffff0f00ULL;
		return 0xffffffffffff8f80ULL;
	else
		return 0xffffffffffff0f00ULL;
}

static u64 rtw_rate_mask_recover(u64 ra_mask, u64 ra_mask_bak)
{
	if ((ra_mask & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES)) == 0)
		ra_mask |= (ra_mask_bak & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES));

	if (ra_mask == 0)
		ra_mask |= (ra_mask_bak & (RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES));

	return ra_mask;
}

static u64 rtw_rate_mask_cfg(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
			     u64 ra_mask, bool is_vht_enable)
{
	struct rtw_hal *hal = &rtwdev->hal;
	const struct cfg80211_bitrate_mask *mask = si->mask;
	u64 cfg_mask = GENMASK_ULL(63, 0);
	u8 band;

	if (!si->use_cfg_mask)
		return ra_mask;

@@ -1100,6 +1115,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
	u8 ldpc_en = 0;
	u8 tx_num = 1;
	u64 ra_mask = 0;
	u64 ra_mask_bak = 0;
	bool is_vht_enable = false;
	bool is_support_sgi = false;

@@ -1124,6 +1140,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)

	if (hal->current_band_type == RTW_BAND_5G) {
		ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4;
		ra_mask_bak = ra_mask;
		if (sta->vht_cap.vht_supported) {
			ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT;
			wireless_set = WIRELESS_OFDM | WIRELESS_VHT;
@@ -1136,6 +1153,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
		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];
		ra_mask_bak = ra_mask;
		if (sta->vht_cap.vht_supported) {
			ra_mask &= RA_MASK_VHT_RATES | RA_MASK_CCK_IN_VHT |
				   RA_MASK_OFDM_IN_VHT;
@@ -1149,11 +1167,13 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
		} else if (sta->supp_rates[0] <= 0xf) {
			wireless_set = WIRELESS_CCK;
		} else {
			ra_mask &= RA_MASK_OFDM_RATES | RA_MASK_CCK_IN_BG;
			wireless_set = WIRELESS_CCK | WIRELESS_OFDM;
		}
		dm_info->rrsr_val_init = RRSR_INIT_2G;
	} else {
		rtw_err(rtwdev, "Unknown band type\n");
		ra_mask_bak = ra_mask;
		wireless_set = 0;
	}

@@ -1185,8 +1205,9 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)

	rate_id = get_rate_id(wireless_set, bw_mode, tx_num);

	ra_mask = rtw_update_rate_mask(rtwdev, si, ra_mask, is_vht_enable,
				       wireless_set);
	ra_mask &= rtw_rate_mask_rssi(si, wireless_set);
	ra_mask = rtw_rate_mask_recover(ra_mask, ra_mask_bak);
	ra_mask = rtw_rate_mask_cfg(rtwdev, si, ra_mask, is_vht_enable);

	si->bw_mode = bw_mode;
	si->stbc_en = stbc_en;