wifi: rtw89: refine bandwidth 160MHz uplink OFDMA performance
authorPo-Hao Huang <phhuang@realtek.com>
Fri, 29 Sep 2023 00:40:24 +0000 (08:40 +0800)
committerKalle Valo <kvalo@kernel.org>
Tue, 3 Oct 2023 11:37:48 +0000 (14:37 +0300)
This improves 160MHz performance degradation with certain APs.
Some ICs transmit preamble that are hard to decode by others, continuous
retries then yield low throughput. Fix it with pre-calculated antenna
matrices.

Signed-off-by: Po-Hao Huang <phhuang@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/20230929004024.7504-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8851b.c
drivers/net/wireless/realtek/rtw89/rtw8852a.c
drivers/net/wireless/realtek/rtw89/rtw8852b.c
drivers/net/wireless/realtek/rtw89/rtw8852c.c

index def5db8804425703c931bac740a27d1fd51376a5..cca18d7ea1dd3abdce5a5a75accceeecb0f42041 100644 (file)
@@ -1689,8 +1689,8 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
 {
        struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
        struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data;
-       u8 *pos, *end, type;
-       u16 aid;
+       u8 *pos, *end, type, tf_bw;
+       u16 aid, tf_rua;
 
        if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) ||
            rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION ||
@@ -1698,7 +1698,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
                return;
 
        type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK);
-       if (type != IEEE80211_TRIGGER_TYPE_BASIC)
+       if (type != IEEE80211_TRIGGER_TYPE_BASIC && type != IEEE80211_TRIGGER_TYPE_MU_BAR)
                return;
 
        end = (u8 *)tf + skb->len;
@@ -1706,17 +1706,24 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
 
        while (end - pos >= RTW89_TF_BASIC_USER_INFO_SZ) {
                aid = RTW89_GET_TF_USER_INFO_AID12(pos);
+               tf_rua = RTW89_GET_TF_USER_INFO_RUA(pos);
+               tf_bw = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_ULBW_MASK);
                rtw89_debug(rtwdev, RTW89_DBG_TXRX,
-                           "[TF] aid: %d, ul_mcs: %d, rua: %d\n",
+                           "[TF] aid: %d, ul_mcs: %d, rua: %d, bw: %d\n",
                            aid, RTW89_GET_TF_USER_INFO_UL_MCS(pos),
-                           RTW89_GET_TF_USER_INFO_RUA(pos));
+                           tf_rua, tf_bw);
 
                if (aid == RTW89_TF_PAD)
                        break;
 
                if (aid == vif->cfg.aid) {
+                       enum nl80211_he_ru_alloc rua = rtw89_he_rua_to_ru_alloc(tf_rua >> 1);
+
                        rtwvif->stats.rx_tf_acc++;
                        rtwdev->stats.rx_tf_acc++;
+                       if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ &&
+                           rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106)
+                               rtwvif->pwr_diff_en = true;
                        break;
                }
 
index 65de2d5d473192856a64c3a5c70a2ec3e7b49679..e13959847aa84dd81acda625c6855fac40e081f1 100644 (file)
@@ -3045,6 +3045,8 @@ struct rtw89_vif {
        bool is_hesta;
        bool last_a_ctrl;
        bool dyn_tb_bedge_en;
+       bool pre_pwr_diff_en;
+       bool pwr_diff_en;
        u8 def_tri_idx;
        u32 tdls_peer;
        struct work_struct update_beacon_work;
@@ -3650,6 +3652,7 @@ struct rtw89_chip_info {
        bool support_bw160;
        bool support_unii4;
        bool ul_tb_waveform_ctrl;
+       bool ul_tb_pwr_diff;
        bool hw_sec_hdr;
        u8 rf_path_num;
        u8 tx_nss;
@@ -5206,6 +5209,30 @@ enum rtw89_bandwidth nl_to_rtw89_bandwidth(enum nl80211_chan_width width)
        }
 }
 
+static inline
+enum nl80211_he_ru_alloc rtw89_he_rua_to_ru_alloc(u16 rua)
+{
+       switch (rua) {
+       default:
+               WARN(1, "Invalid RU allocation: %d\n", rua);
+               fallthrough;
+       case 0 ... 36:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_26;
+       case 37 ... 52:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_52;
+       case 53 ... 60:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_106;
+       case 61 ... 64:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_242;
+       case 65 ... 66:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_484;
+       case 67:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_996;
+       case 68:
+               return NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
+       }
+}
+
 static inline
 struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif *rtwvif,
                                                   struct rtw89_sta *rtwsta)
index 1232ca48deee3c018c39b6056076cf5d99890630..05b0ca3d75fe73e530c659e0a5f842fc17020cae 100644 (file)
@@ -2934,6 +2934,61 @@ struct rtw89_phy_ul_tb_check_data {
        u8 def_tri_idx;
 };
 
+struct rtw89_phy_power_diff {
+       u32 q_00;
+       u32 q_11;
+       u32 q_matrix_en;
+       u32 ultb_1t_norm_160;
+       u32 ultb_2t_norm_160;
+       u32 com1_norm_1sts;
+       u32 com2_resp_1sts_path;
+};
+
+static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev,
+                                      struct rtw89_vif *rtwvif)
+{
+       static const struct rtw89_phy_power_diff table[2] = {
+               {0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3},
+               {0xb50, 0xb50, 0x1, 0xc, 0x0, 0x1, 0x1},
+       };
+       const struct rtw89_phy_power_diff *param;
+       u32 reg;
+
+       if (!rtwdev->chip->ul_tb_pwr_diff)
+               return;
+
+       if (rtwvif->pwr_diff_en == rtwvif->pre_pwr_diff_en) {
+               rtwvif->pwr_diff_en = false;
+               return;
+       }
+
+       rtwvif->pre_pwr_diff_en = rtwvif->pwr_diff_en;
+       param = &table[rtwvif->pwr_diff_en];
+
+       rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL,
+                              param->q_00);
+       rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_11, B_Q_MATRIX_11_REAL,
+                              param->q_11);
+       rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX,
+                              B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en);
+
+       reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif->mac_idx);
+       rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160,
+                          param->ultb_1t_norm_160);
+
+       reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif->mac_idx);
+       rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160,
+                          param->ultb_2t_norm_160);
+
+       reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif->mac_idx);
+       rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS,
+                          param->com1_norm_1sts);
+
+       reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif->mac_idx);
+       rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH,
+                          param->com2_resp_1sts_path);
+}
+
 static
 void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
                                struct rtw89_vif *rtwvif,
@@ -2958,6 +3013,8 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
                ul_tb_data->def_tri_idx = rtwvif->def_tri_idx;
                ul_tb_data->dyn_tb_bedge_en = rtwvif->dyn_tb_bedge_en;
        }
+
+       rtw89_phy_ofdma_power_diff(rtwdev, rtwvif);
 }
 
 static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev,
@@ -3005,7 +3062,7 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
        struct rtw89_phy_ul_tb_check_data ul_tb_data = {};
        struct rtw89_vif *rtwvif;
 
-       if (!chip->ul_tb_waveform_ctrl)
+       if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff)
                return;
 
        if (rtwdev->total_sta_assoc != 1)
index edaf2a13ef98d938edd107166aec9479fe9e50d6..4b9a090642cc79fdc8f8232c24035864b2cccc6c 100644 (file)
 #define R_AX_PWR_UL_TB_1T 0xD28C
 #define B_AX_PWR_UL_TB_1T_MASK GENMASK(4, 0)
 #define B_AX_PWR_UL_TB_1T_V1_MASK GENMASK(7, 0)
+#define B_AX_PWR_UL_TB_1T_NORM_BW160 GENMASK(31, 24)
 #define R_AX_PWR_UL_TB_2T 0xD290
 #define B_AX_PWR_UL_TB_2T_MASK GENMASK(4, 0)
 #define B_AX_PWR_UL_TB_2T_V1_MASK GENMASK(7, 0)
+#define B_AX_PWR_UL_TB_2T_NORM_BW160 GENMASK(31, 24)
 #define R_AX_PWR_BY_RATE_TABLE0 0xD2C0
 #define R_AX_PWR_BY_RATE_TABLE6 0xD2D8
 #define R_AX_PWR_BY_RATE_TABLE10 0xD2E8
 #define AX_PATH_COM0_PATHB 0x11111900
 #define AX_PATH_COM0_PATHAB 0x19999980
 #define R_AX_PATH_COM1 0xD804
+#define B_AX_PATH_COM1_NORM_1STS GENMASK(31, 28)
 #define AX_PATH_COM1_DFVAL 0x00000000
 #define AX_PATH_COM1_PATHA 0x13111111
 #define AX_PATH_COM1_PATHB 0x23222222
 #define AX_PATH_COM1_PATHAB 0x33333333
 #define R_AX_PATH_COM2 0xD808
+#define B_AX_PATH_COM2_RESP_1STS_PATH GENMASK(7, 4)
 #define AX_PATH_COM2_DFVAL 0x00000000
 #define AX_PATH_COM2_PATHA 0x01209313
 #define AX_PATH_COM2_PATHB 0x01209323
 #define B_ANT_RX_1RCCA_SEG1 GENMASK(21, 18)
 #define B_ANT_RX_1RCCA_SEG0 GENMASK(17, 14)
 #define B_FC0_BW_INV GENMASK(6, 0)
+#define R_Q_MATRIX_00 0x497C
+#define B_Q_MATRIX_00_IMAGINARY GENMASK(15, 0)
+#define B_Q_MATRIX_00_REAL GENMASK(31, 16)
 #define R_CHBW_MOD 0x4978
 #define R_CHBW_MOD_V1 0x49C4
 #define B_BT_SHARE BIT(14)
 #define B_CHBW_MOD_SBW GENMASK(13, 12)
 #define B_CHBW_MOD_PRICH GENMASK(11, 8)
 #define B_ANT_RX_SEG0 GENMASK(3, 0)
+#define R_Q_MATRIX_11 0x4988
+#define B_Q_MATRIX_11_IMAGINARY GENMASK(15, 0)
+#define B_Q_MATRIX_11_REAL GENMASK(31, 16)
+#define R_CUSTOMIZE_Q_MATRIX 0x498C
+#define B_CUSTOMIZE_Q_MATRIX_EN BIT(0)
 #define R_P0_RPL1 0x49B0
 #define B_P0_RPL1_41_MASK GENMASK(31, 24)
 #define B_P0_RPL1_40_MASK GENMASK(23, 16)
index b276816f1ce6f49f590b5da521bee135233c04c2..ecaa86ccd49ea5a84c50b6720a28b933af72cee6 100644 (file)
@@ -2380,6 +2380,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
        .support_bw160          = false,
        .support_unii4          = true,
        .ul_tb_waveform_ctrl    = true,
+       .ul_tb_pwr_diff         = false,
        .hw_sec_hdr             = false,
        .rf_path_num            = 1,
        .tx_nss                 = 1,
index 12b591d06000ab6c53ecb4f838edf312e47d233f..ec6ec3868d52776cdb7fc6b116abdb41d0d96f34 100644 (file)
@@ -2116,6 +2116,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
        .support_bw160          = false,
        .support_unii4          = false,
        .ul_tb_waveform_ctrl    = false,
+       .ul_tb_pwr_diff         = false,
        .hw_sec_hdr             = false,
        .rf_path_num            = 2,
        .tx_nss                 = 2,
index 1591ae82fac5fb6a21ef3c6e7dc26349131fe0b7..e5bc459dbe799f4a62b16e5f8ef06674fb1afe8a 100644 (file)
@@ -2550,6 +2550,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
        .support_bw160          = false,
        .support_unii4          = true,
        .ul_tb_waveform_ctrl    = true,
+       .ul_tb_pwr_diff         = false,
        .hw_sec_hdr             = false,
        .rf_path_num            = 2,
        .tx_nss                 = 2,
index 553f60d98f452321d197b52e3266f9fc296be1bf..db289f1d7ae5ca219c657a7ce9927cefad48b583 100644 (file)
@@ -2860,6 +2860,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
        .support_bw160          = true,
        .support_unii4          = true,
        .ul_tb_waveform_ctrl    = false,
+       .ul_tb_pwr_diff         = true,
        .hw_sec_hdr             = true,
        .rf_path_num            = 2,
        .tx_nss                 = 2,