rtw88: recover rates of rate adaptive mechanism
authorChien-Hsun Liao <ben.liao@realtek.com>
Tue, 8 Feb 2022 08:24:26 +0000 (16:24 +0800)
committerKalle Valo <kvalo@kernel.org>
Thu, 10 Feb 2022 08:44:44 +0000 (10:44 +0200)
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: Chien-Hsun Liao <ben.liao@realtek.com>
Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220208082427.42433-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw88/main.c

index 39c223a2e3e2da7c0917dacd0ec5f3f4eb8e89a8..2757aa0dc586bef4eaefe21f2798ef783f8e57d5 100644 (file)
@@ -1020,37 +1020,52 @@ 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)
+{
+       u8 rssi_level = si->rssi_level;
+
+       if (wireless_set == WIRELESS_CCK)
+               return 0xffffffffffffffffULL;
+
+       if (rssi_level == 0)
+               return 0xffffffffffffffffULL;
+       else if (rssi_level == 1)
+               return 0xfffffffffffffff0ULL;
+       else if (rssi_level == 2)
+               return 0xffffffffffffefe0ULL;
+       else if (rssi_level == 3)
+               return 0xffffffffffffcfc0ULL;
+       else if (rssi_level == 4)
+               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 rssi_level, band;
-
-       if (wireless_set != WIRELESS_CCK) {
-               rssi_level = si->rssi_level;
-               if (rssi_level == 0)
-                       ra_mask &= 0xffffffffffffffffULL;
-               else if (rssi_level == 1)
-                       ra_mask &= 0xfffffffffffffff0ULL;
-               else if (rssi_level == 2)
-                       ra_mask &= 0xffffffffffffefe0ULL;
-               else if (rssi_level == 3)
-                       ra_mask &= 0xffffffffffffcfc0ULL;
-               else if (rssi_level == 4)
-                       ra_mask &= 0xffffffffffff8f80ULL;
-               else if (rssi_level >= 5)
-                       ra_mask &= 0xffffffffffff0f00ULL;
-       }
+       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;