@@ -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 {
@@ -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;