wifi: rtw89: support for setting HE GI and LTF
authorKuan-Chung Chen <damon.chen@realtek.com>
Mon, 12 Sep 2022 07:00:13 +0000 (15:00 +0800)
committerKalle Valo <kvalo@kernel.org>
Mon, 19 Sep 2022 10:02:36 +0000 (13:02 +0300)
Support setting HE GI and LTF values to the kernel via nl80211.
We currently only support some GI and LTF values settings.

The command example is:
  iw wlan0 set bitrates he-gi-2.4 0.8 he-ltf-2.4 2

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/20220912070014.10018-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/phy.c

index 28a3303..e64ecb3 100644 (file)
@@ -2069,7 +2069,9 @@ struct rtw89_ra_info {
        u8 ra_csi_rate_en:1;
        u8 fixed_csi_rate_en:1;
        u8 cr_tbl_sel:1;
-       u8 rsvd2:5;
+       u8 fix_giltf_en:1;
+       u8 fix_giltf:3;
+       u8 rsvd2:1;
        u8 csi_mcs_ss_idx;
        u8 csi_mode:2;
        u8 csi_gi_ltf:3;
index 2444f59..28b746a 100644 (file)
@@ -1468,6 +1468,8 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi
        RTW89_SET_FWCMD_RA_MASK_2(cmd, FIELD_GET(MASKBYTE2, ra->ra_mask));
        RTW89_SET_FWCMD_RA_MASK_3(cmd, FIELD_GET(MASKBYTE3, ra->ra_mask));
        RTW89_SET_FWCMD_RA_MASK_4(cmd, FIELD_GET(MASKBYTE4, ra->ra_mask));
+       RTW89_SET_FWCMD_RA_FIX_GILTF_EN(cmd, ra->fix_giltf_en);
+       RTW89_SET_FWCMD_RA_FIX_GILTF(cmd, ra->fix_giltf);
 
        if (csi) {
                RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(cmd, 1);
index a055ea5..6e3aca4 100644 (file)
@@ -361,6 +361,16 @@ static inline void RTW89_SET_FWCMD_RA_CR_TBL_SEL(void *cmd, u32 val)
        le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(10));
 }
 
+static inline void RTW89_SET_FWCMD_RA_FIX_GILTF_EN(void *cmd, u32 val)
+{
+       le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(11));
+}
+
+static inline void RTW89_SET_FWCMD_RA_FIX_GILTF(void *cmd, u32 val)
+{
+       le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(14, 12));
+}
+
 static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(void *cmd, u32 val)
 {
        le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(23, 16));
index 094f41c..be2c371 100644 (file)
@@ -193,6 +193,40 @@ 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 void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
+                               struct rtw89_sta *rtwsta,
+                               bool *fix_giltf_en, u8 *fix_giltf)
+{
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
+       u8 band = chan->band_type;
+       enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+       u8 he_gi = mask->control[nl_band].he_gi;
+       u8 he_ltf = mask->control[nl_band].he_ltf;
+
+       if (!rtwsta->use_cfg_mask)
+               return;
+
+       if (he_ltf == 2 && he_gi == 2) {
+               *fix_giltf = RTW89_GILTF_LGI_4XHE32;
+       } else if (he_ltf == 2 && he_gi == 0) {
+               *fix_giltf = RTW89_GILTF_SGI_4XHE08;
+       } else if (he_ltf == 1 && he_gi == 1) {
+               *fix_giltf = RTW89_GILTF_2XHE16;
+       } else if (he_ltf == 1 && he_gi == 0) {
+               *fix_giltf = RTW89_GILTF_2XHE08;
+       } else if (he_ltf == 0 && he_gi == 1) {
+               *fix_giltf = RTW89_GILTF_1XHE16;
+       } else if (he_ltf == 0 && he_gi == 0) {
+               *fix_giltf = RTW89_GILTF_1XHE08;
+       } else {
+               *fix_giltf_en = false;
+               return;
+       }
+
+       *fix_giltf_en = true;
+}
+
 static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
                                    struct ieee80211_sta *sta, bool csi)
 {
@@ -210,8 +244,10 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
        u8 bw_mode = 0;
        u8 stbc_en = 0;
        u8 ldpc_en = 0;
+       u8 fix_giltf = 0;
        u8 i;
        bool sgi = false;
+       bool fix_giltf_en = false;
 
        memset(ra, 0, sizeof(*ra));
        /* Set the ra mask from sta's capability */
@@ -226,6 +262,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
                if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] &
                    IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
                        ldpc_en = 1;
+               rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, &fix_giltf_en, &fix_giltf);
        } else if (sta->deflink.vht_cap.vht_supported) {
                u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
 
@@ -335,6 +372,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
        ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
        ra->en_sgi = sgi;
        ra->ra_mask = ra_mask;
+       ra->fix_giltf_en = fix_giltf_en;
+       ra->fix_giltf = fix_giltf;
 
        if (!csi)
                return;