wifi: rtw89: support TX diversity for 1T2R chipset
authorPing-Ke Shih <pkshih@realtek.com>
Thu, 8 Sep 2022 07:41:40 +0000 (15:41 +0800)
committerKalle Valo <kvalo@kernel.org>
Mon, 12 Sep 2022 11:51:44 +0000 (14:51 +0300)
Check RSSI strength to decide which path is better, and then set TX path
accordingly.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220908074140.39776-6-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/debug.c
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h
drivers/net/wireless/realtek/rtw89/reg.h

index 0f474b5..8c64af9 100644 (file)
@@ -2218,6 +2218,7 @@ static void rtw89_track_work(struct work_struct *work)
        rtw89_chip_rfk_track(rtwdev);
        rtw89_phy_ra_update(rtwdev);
        rtw89_phy_cfo_track(rtwdev);
+       rtw89_phy_tx_path_div_track(rtwdev);
 
        if (rtwdev->lps_enabled && !rtwdev->btc.lps)
                rtw89_enter_lps_track(rtwdev);
index 392a8bf..40453ed 100644 (file)
@@ -34,6 +34,7 @@ extern const struct ieee80211_ops rtw89_ops;
 #define MAX_RSSI 110
 #define RSSI_FACTOR 1
 #define RTW89_RSSI_RAW_TO_DBM(rssi) ((s8)((rssi) >> RSSI_FACTOR) - MAX_RSSI)
+#define RTW89_TX_DIV_RSSI_RAW_TH (2 << RSSI_FACTOR)
 
 #define RTW89_HTC_MASK_VARIANT GENMASK(1, 0)
 #define RTW89_HTC_VARIANT_HE 3
index a34f612..eed28c3 100644 (file)
@@ -2291,6 +2291,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
        struct ieee80211_rx_status *status = &rtwsta->rx_status;
        struct seq_file *m = (struct seq_file *)data;
        struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+       struct rtw89_hal *hal = &rtwdev->hal;
        u8 rssi;
        int i;
 
@@ -2341,7 +2342,8 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
                   RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi);
        for (i = 0; i < rtwdev->chip->rf_path_num; i++) {
                rssi = ewma_rssi_read(&rtwsta->rssi[i]);
-               seq_printf(m, "%d%s", RTW89_RSSI_RAW_TO_DBM(rssi),
+               seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi),
+                          hal->tx_path_diversity && (hal->antenna_tx & BIT(i)) ? "*" : "",
                           i + 1 == rtwdev->chip->rf_path_num ? "" : ", ");
        }
        seq_puts(m, "]\n");
index a2ebef0..9733ad1 100644 (file)
@@ -3660,6 +3660,62 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev)
                rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false);
 }
 
+static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
+{
+       struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+       struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+       struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+       struct rtw89_hal *hal = &rtwdev->hal;
+       bool *done = data;
+       u8 rssi_a, rssi_b;
+       u32 candidate;
+
+       if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls)
+               return;
+
+       if (*done)
+               return;
+
+       *done = true;
+
+       rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]);
+       rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]);
+
+       if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH)
+               candidate = RF_A;
+       else if (rssi_b > rssi_a + RTW89_TX_DIV_RSSI_RAW_TH)
+               candidate = RF_B;
+       else
+               return;
+
+       if (hal->antenna_tx == candidate)
+               return;
+
+       hal->antenna_tx = candidate;
+       rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta);
+
+       if (hal->antenna_tx == RF_A) {
+               rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12);
+               rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x11);
+       } else if (hal->antenna_tx == RF_B) {
+               rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x11);
+               rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x12);
+       }
+}
+
+void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       bool done = false;
+
+       if (!hal->tx_path_diversity)
+               return;
+
+       ieee80211_iterate_stations_atomic(rtwdev->hw,
+                                         rtw89_phy_tx_path_div_sta_iter,
+                                         &done);
+}
+
 static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev)
 {
        rtw89_phy_ccx_top_setting_init(rtwdev);
index 0eeab18..ee3bc5e 100644 (file)
@@ -491,6 +491,7 @@ void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
                            u32 val);
 void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev);
 void rtw89_phy_dig(struct rtw89_dev *rtwdev);
+void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev);
 void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
 void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
                                          enum rtw89_mac_idx mac_idx,
index 38139ff..cd7b21b 100644 (file)
 #define B_P0_RXCK_VAL GENMASK(18, 16)
 #define B_P0_TXCK_ON BIT(15)
 #define B_P0_TXCK_VAL GENMASK(14, 12)
+#define R_P0_RFMODE 0x12AC
+#define B_P0_RFMODE_ORI_TXRX_FTM_TX GENMASK(31, 4)
+#define B_P0_RFMODE_MUX GENMASK(11, 4)
 #define R_P0_NRBW 0x12B8
 #define B_P0_NRBW_DBG BIT(30)
 #define R_S0_RXDC 0x12D4
 #define B_P1_EN_SOUND_WO_NDP BIT(1)
 #define R_S1_HW_SI_DIS 0x3200
 #define B_S1_HW_SI_DIS_W_R_TRIG GENMASK(30, 28)
+#define R_P1_RFMODE 0x32AC
+#define B_P1_RFMODE_ORI_TXRX_FTM_TX GENMASK(31, 4)
+#define B_P1_RFMODE_MUX GENMASK(11, 4)
 #define R_P1_DBGMOD 0x32B8
 #define B_P1_DBGMOD_ON BIT(30)
 #define R_S1_RXDC 0x32D4