From: Zong-Zhe Yang The Wi-Fi 7 RF calibration flow has a new design which mainly affect MLO cases. Before, old RFK H2C command can just send the used channels and MLO mode even if there are multiple active links. After, each RFK H2C command should send one channel corresponding to one active link. For example, connect MLD AP (channel X) and then activate second link (channel X + channel Y) Before: RFK#1: channel X (path A + path B) RFK#2: channel X (path A) + channel Y (path B) After: RFK#1: channel X (path A + path B) [set MLO mode to focus on 2nd link/channel] RFK#2: channel Y (path A + path B) [set MLO mode back to target case] Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/chan.c | 33 +++++++++++++++++++ drivers/net/wireless/realtek/rtw89/chan.h | 2 ++ drivers/net/wireless/realtek/rtw89/core.c | 29 +++++++++++++++- drivers/net/wireless/realtek/rtw89/core.h | 13 +++----- drivers/net/wireless/realtek/rtw89/mac80211.c | 3 +- 5 files changed, 69 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 8fe6a7ef738f..0b5509468582 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -295,6 +295,8 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE; } + hal->entity_force_hw = RTW89_PHY_NUM; + rtw89_config_default_chandef(rtwdev); } @@ -417,12 +419,43 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(__rtw89_mgnt_chan_get); +bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + switch (rtwdev->mlo_dbcc_mode) { + case MLO_2_PLUS_0_1RF: + return phy_idx == RTW89_PHY_0; + case MLO_0_PLUS_2_1RF: + return phy_idx == RTW89_PHY_1; + default: + return false; + } +} + +void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + rtwdev->hal.entity_force_hw = phy_idx; + + if (phy_idx != RTW89_PHY_NUM) + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: %d\n", __func__, phy_idx); + else + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: (none)\n", __func__); +} + static enum rtw89_mlo_dbcc_mode rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws) { if (rtwdev->chip->chip_gen != RTW89_CHIP_BE) return MLO_DBCC_NOT_SUPPORT; + switch (rtwdev->hal.entity_force_hw) { + case RTW89_PHY_0: + return MLO_2_PLUS_0_1RF; + case RTW89_PHY_1: + return MLO_0_PLUS_2_1RF; + default: + break; + } + switch (active_hws) { case BIT(0): return MLO_2_PLUS_0_1RF; diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index 5b22764d5329..c797cda2e763 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -166,6 +166,8 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev, const struct cfg80211_chan_def *chandef); void rtw89_entity_init(struct rtw89_dev *rtwdev); enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev); +bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work); void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev); void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index e713422ebd7c..96fb2839379f 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -470,6 +470,32 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) __rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_1); } +void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + bool mon = !!rtwdev->pure_monitor_mode_vif; + bool prehdl_link = false; + + if (chip->chip_gen != RTW89_CHIP_AX && + !RTW89_CHK_FW_FEATURE(WITH_RFK_PRE_NOTIFY, &rtwdev->fw) && + !mon && !rtw89_entity_check_hw(rtwdev, rtwvif_link->phy_idx)) + prehdl_link = true; + + if (prehdl_link) { + rtw89_entity_force_hw(rtwdev, rtwvif_link->phy_idx); + rtw89_set_channel(rtwdev); + } + + if (chip->ops->rfk_channel) + chip->ops->rfk_channel(rtwdev, rtwvif_link); + + if (prehdl_link) { + rtw89_entity_force_hw(rtwdev, RTW89_PHY_NUM); + rtw89_set_channel(rtwdev); + } +} + static void rtw89_chip_rfk_channel_for_pure_mon_vif(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -6218,7 +6244,8 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, goto wake_queue; } - rtw89_chip_rfk_channel(rtwdev, target); + if (RTW89_CHK_FW_FEATURE(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) + rtw89_chip_rfk_channel(rtwdev, target); rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index b7d5eb25ef74..52d6e5683d63 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -5075,6 +5075,8 @@ struct rtw89_hal { enum rtw89_entity_mode entity_mode; struct rtw89_entity_mgnt entity_mgnt; + enum rtw89_phy_idx entity_force_hw; + u32 disabled_dm_bitmap; /* bitmap of enum rtw89_dm_type */ u8 thermal_prot_th; @@ -7125,15 +7127,6 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev) chip->ops->rfk_init_late(rtwdev); } -static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) -{ - const struct rtw89_chip_info *chip = rtwdev->chip; - - if (chip->ops->rfk_channel) - chip->ops->rfk_channel(rtwdev, rtwvif_link); -} - static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan) @@ -7647,6 +7640,8 @@ struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); +void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); const struct rtw89_6ghz_span * rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq); void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index f80c847d1741..96dc94c1f556 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -720,7 +720,8 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_MLD_VALID_LINKS) { struct rtw89_vif_link *cur = rtw89_get_designated_link(rtwvif); - rtw89_chip_rfk_channel(rtwdev, cur); + if (RTW89_CHK_FW_FEATURE(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) + rtw89_chip_rfk_channel(rtwdev, cur); if (hweight16(vif->active_links) == 1) rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR; -- 2.25.1