wifi: rtw89: add EVM for antenna diversity
authorEric Huang <echuang@realtek.com>
Tue, 18 Apr 2023 01:28:20 +0000 (09:28 +0800)
committerKalle Valo <kvalo@kernel.org>
Fri, 5 May 2023 11:58:29 +0000 (14:58 +0300)
Take EVM into consideration when doing antenna diversity, and the priority
is higher than RSSI. Since EVM is more relevant to performance than RSSI,
especially in OTA environment.

Signed-off-by: Eric Huang <echuang@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/20230418012820.5139-8-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/phy.c

index ca9d6e9..40406ec 100644 (file)
@@ -3134,6 +3134,7 @@ struct rtw89_antdiv_stats {
        u16 pkt_cnt_cck;
        u16 pkt_cnt_ofdm;
        u16 pkt_cnt_non_legacy;
+       u32 evm;
 };
 
 struct rtw89_antdiv_info {
index b9a3ebc..5eac00c 100644 (file)
@@ -2956,6 +2956,7 @@ void rtw89_phy_antdiv_sts_instance_reset(struct rtw89_antdiv_stats *antdiv_sts)
        antdiv_sts->pkt_cnt_cck = 0;
        antdiv_sts->pkt_cnt_ofdm = 0;
        antdiv_sts->pkt_cnt_non_legacy = 0;
+       antdiv_sts->evm = 0;
 }
 
 static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev,
@@ -2969,10 +2970,12 @@ static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev,
                } else {
                        ewma_rssi_add(&stats->ofdm_rssi_avg, phy_ppdu->rssi_avg);
                        stats->pkt_cnt_ofdm++;
+                       stats->evm += phy_ppdu->ofdm.evm_min;
                }
        } else {
                ewma_rssi_add(&stats->non_legacy_rssi_avg, phy_ppdu->rssi_avg);
                stats->pkt_cnt_non_legacy++;
+               stats->evm += phy_ppdu->ofdm.evm_min;
        }
 }
 
@@ -2988,6 +2991,11 @@ static u8 rtw89_phy_antdiv_sts_instance_get_rssi(struct rtw89_antdiv_stats *stat
                return ewma_rssi_read(&stats->cck_rssi_avg);
 }
 
+static u8 rtw89_phy_antdiv_sts_instance_get_evm(struct rtw89_antdiv_stats *stats)
+{
+       return phy_div(stats->evm, stats->pkt_cnt_non_legacy + stats->pkt_cnt_ofdm);
+}
+
 void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
                            struct rtw89_rx_phy_ppdu *phy_ppdu)
 {
@@ -4270,15 +4278,22 @@ static void rtw89_phy_antdiv_decision_state(struct rtw89_dev *rtwdev)
        struct rtw89_hal *hal = &rtwdev->hal;
        bool no_change = false;
        u8 main_rssi, aux_rssi;
+       u8 main_evm, aux_evm;
        u32 candidate;
 
        antdiv->get_stats = false;
        antdiv->training_count = 0;
 
        main_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->main_stats);
+       main_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->main_stats);
        aux_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->aux_stats);
+       aux_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->aux_stats);
 
-       if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
+       if (main_evm > aux_evm + ANTDIV_EVM_DIFF_TH)
+               candidate = RF_A;
+       else if (aux_evm > main_evm + ANTDIV_EVM_DIFF_TH)
+               candidate = RF_B;
+       else if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
                candidate = RF_A;
        else if (aux_rssi > main_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
                candidate = RF_B;