Firmware can only support PS on single one VIF operating in station mode, so argument of PS entry rtw89_enter_lps() should be rtwvif insetad of rtwvif_link. To enter PS under MLO, for each rtwvif, driver sends H2C command to tell firmware which mac_id will enter PS one by one, and afterward asks firmware to enter deep PS. Signed-off-by: Ping-Ke Shih <pkshih@xxxxxxxxxxx> --- drivers/net/wireless/realtek/rtw89/core.c | 26 ++++++------------ drivers/net/wireless/realtek/rtw89/ps.c | 33 ++++++++++++----------- drivers/net/wireless/realtek/rtw89/ps.h | 4 +-- drivers/net/wireless/realtek/rtw89/wow.c | 6 ++--- 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 29d0ac502bab..0519b0826281 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2729,10 +2729,6 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */ - if (rtwdev->support_mlo) - return RTW89_PS_MODE_NONE; - if (rtw89_disable_ps_mode || !chip->ps_mode_supported || RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw)) return RTW89_PS_MODE_NONE; @@ -3469,21 +3465,10 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) return tfc_changed; } -static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) -{ - if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && - rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) - return; - - rtw89_enter_lps(rtwdev, rtwvif_link, true); -} - static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) { - struct rtw89_vif_link *rtwvif_link; + struct ieee80211_vif *vif; struct rtw89_vif *rtwvif; - unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) { if (rtwvif->tdls_peer) @@ -3495,8 +3480,13 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE) continue; - rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) - rtw89_vif_enter_lps(rtwdev, rtwvif_link); + vif = rtwvif_to_vif(rtwvif); + + if (!(vif->type == NL80211_IFTYPE_STATION || + vif->type == NL80211_IFTYPE_P2P_CLIENT)) + continue; + + rtw89_enter_lps(rtwdev, rtwvif, true); } } diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index c1c12abc2ea9..5e3a5e3c9776 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -62,11 +62,8 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) rtw89_mac_power_mode_change(rtwdev, enter); } -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev) { - if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) - return; - if (!rtwdev->ps_mode) return; @@ -85,8 +82,8 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) rtw89_ps_power_mode_change(rtwdev, false); } -static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) +static void __rtw89_enter_lps_link(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_lps_parm lps_param = { .macid = rtwvif_link->mac_id, @@ -121,17 +118,27 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); } -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool ps_mode) { + struct rtw89_vif_link *rtwvif_link; + bool can_ps_mode = true; + unsigned int link_id; + lockdep_assert_held(&rtwdev->mutex); if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) return; - __rtw89_enter_lps(rtwdev, rtwvif_link); - if (ps_mode) - __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + __rtw89_enter_lps_link(rtwdev, rtwvif_link); + + if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + can_ps_mode = false; + } + + if (ps_mode && can_ps_mode) + __rtw89_enter_ps_mode(rtwdev); } static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, @@ -282,12 +289,6 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; int count = 0; - /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode() - * to take MLO cases into account before doing the following. - */ - if (rtwdev->support_mlo) - goto disable_lps; - mode = rtw89_get_entity_mode(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) goto disable_lps; diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index cdd712966b09..2b88f254a32d 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -5,11 +5,11 @@ #ifndef __RTW89_PS_H_ #define __RTW89_PS_H_ -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool ps_mode); void rtw89_leave_lps(struct rtw89_dev *rtwdev); void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev); void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); void rtw89_enter_ips(struct rtw89_dev *rtwdev); void rtw89_leave_ips(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 1e1dbb20d47a..01754d031bb4 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -694,9 +694,7 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) { - struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - - __rtw89_enter_ps_mode(rtwdev, rtwvif_link); + __rtw89_enter_ps_mode(rtwdev); } static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) @@ -704,7 +702,7 @@ static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; if (rtw89_wow_mgd_linked(rtwdev)) - rtw89_enter_lps(rtwdev, rtwvif_link, false); + rtw89_enter_lps(rtwdev, rtwvif_link->rtwvif, false); else if (rtw89_wow_no_link(rtwdev)) rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true); } -- 2.25.1