summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtw89/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/phy.c')
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index d04eaf7c5500..8a306a86f1f0 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -88,6 +88,55 @@ static u64 get_he_ra_mask(struct ieee80211_sta *sta)
return get_mcs_ra_mask(mcs_map, 11, 2);
}
+static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss)
+{
+ u64 nss_mcs_shift;
+ u64 nss_mcs_val;
+ u64 mask = 0;
+ int i, j;
+ u8 nss;
+
+ for (i = 0; i < n_nss; i++) {
+ nss = u8_get_bits(max_nss[i], IEEE80211_EHT_MCS_NSS_RX);
+ if (!nss)
+ continue;
+
+ nss_mcs_val = GENMASK_ULL(start_mcs + i * 2, 0);
+
+ for (j = 0, nss_mcs_shift = 12; j < nss; j++, nss_mcs_shift += 16)
+ mask |= nss_mcs_val << nss_mcs_shift;
+ }
+
+ return mask;
+}
+
+static u64 get_eht_ra_mask(struct ieee80211_sta *sta)
+{
+ struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
+ struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz;
+ struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss;
+
+ switch (sta->deflink.bandwidth) {
+ case IEEE80211_STA_RX_BW_320:
+ mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320;
+ /* MCS 9, 11, 13 */
+ return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
+ case IEEE80211_STA_RX_BW_160:
+ mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._160;
+ /* MCS 9, 11, 13 */
+ return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
+ case IEEE80211_STA_RX_BW_80:
+ default:
+ mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80;
+ /* MCS 9, 11, 13 */
+ return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
+ case IEEE80211_STA_RX_BW_20:
+ mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz;
+ /* MCS 7, 9, 11, 13 */
+ return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4);
+ }
+}
+
#define RA_FLOOR_TABLE_SIZE 7
#define RA_FLOOR_UP_GAP 3
static u64 rtw89_phy_ra_mask_rssi(struct rtw89_dev *rtwdev, u8 rssi,
@@ -194,6 +243,9 @@ rtw89_ra_mask_vht_rates[4] = {RA_MASK_VHT_1SS_RATES, RA_MASK_VHT_2SS_RATES,
static const u64
rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES,
RA_MASK_HE_3SS_RATES, RA_MASK_HE_4SS_RATES};
+static const u64
+rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES,
+ RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES};
static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
struct rtw89_sta *rtwsta,
@@ -255,7 +307,11 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
memset(ra, 0, sizeof(*ra));
/* Set the ra mask from sta's capability */
- if (sta->deflink.he_cap.has_he) {
+ if (sta->deflink.eht_cap.has_eht) {
+ mode |= RTW89_RA_MODE_EHT;
+ ra_mask |= get_eht_ra_mask(sta);
+ high_rate_masks = rtw89_ra_mask_eht_rates;
+ } else if (sta->deflink.he_cap.has_he) {
mode |= RTW89_RA_MODE_HE;
csi_mode = RTW89_RA_RPT_MODE_HE;
ra_mask |= get_he_ra_mask(sta);
@@ -2343,6 +2399,18 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_3_2;
mcs = ra_report->txrate.mcs;
break;
+ case RTW89_RA_RPT_MODE_EHT:
+ ra_report->txrate.flags |= RATE_INFO_FLAGS_EHT_MCS;
+ ra_report->txrate.mcs = u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1);
+ ra_report->txrate.nss = u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1;
+ if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08)
+ ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_0_8;
+ else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16)
+ ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_1_6;
+ else
+ ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_3_2;
+ mcs = ra_report->txrate.mcs;
+ break;
}
ra_report->txrate.bw = rtw89_hw_to_rate_info_bw(bw);