summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/realtek/rtw88/ps.c
diff options
context:
space:
mode:
authorPing-Ke Shih <pkshih@realtek.com>2023-05-27 16:29:37 +0800
committerKalle Valo <kvalo@kernel.org>2023-06-01 16:16:40 +0300
commit3918dd0177ee08970683a2c22a3388825d82fd79 (patch)
tree3147659d186251d9023c9a2168e6a843ddcaba55 /drivers/net/wireless/realtek/rtw88/ps.c
parent30bc32c7c1f975cc3c14e1c7dc437266311282cf (diff)
downloadlinux-3918dd0177ee08970683a2c22a3388825d82fd79.tar.gz
linux-3918dd0177ee08970683a2c22a3388825d82fd79.tar.bz2
linux-3918dd0177ee08970683a2c22a3388825d82fd79.zip
wifi: rtw88: correct PS calculation for SUPPORTS_DYNAMIC_PS
This driver relies on IEEE80211_CONF_PS of hw->conf.flags to turn off PS or turn on dynamic PS controlled by driver and firmware. Though this would be incorrect, it did work before because the flag is always recalculated until the commit 28977e790b5d ("wifi: mac80211: skip powersave recalc if driver SUPPORTS_DYNAMIC_PS") is introduced by kernel 5.20 to skip to recalculate IEEE80211_CONF_PS of hw->conf.flags if driver sets SUPPORTS_DYNAMIC_PS. Correct this by doing recalculation while BSS_CHANGED_PS is changed and interface is added or removed. It is allowed to enter PS only if single one station vif is working. Without this fix, driver doesn't enter PS anymore that causes higher power consumption. Fixes: bcde60e599fb ("rtw88: remove misleading module parameter rtw_fw_support_lps") Cc: stable@vger.kernel.org # 6.1+ Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20230527082939.11206-2-pkshih@realtek.com
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/ps.c')
-rw-r--r--drivers/net/wireless/realtek/rtw88/ps.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c
index 996365575f44..53933fb38a33 100644
--- a/drivers/net/wireless/realtek/rtw88/ps.c
+++ b/drivers/net/wireless/realtek/rtw88/ps.c
@@ -299,3 +299,46 @@ void rtw_leave_lps_deep(struct rtw_dev *rtwdev)
__rtw_leave_lps_deep(rtwdev);
}
+
+struct rtw_vif_recalc_lps_iter_data {
+ struct rtw_dev *rtwdev;
+ struct ieee80211_vif *found_vif;
+ int count;
+};
+
+static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data,
+ struct ieee80211_vif *vif)
+{
+ if (data->count < 0)
+ return;
+
+ if (vif->type != NL80211_IFTYPE_STATION) {
+ data->count = -1;
+ return;
+ }
+
+ data->count++;
+ data->found_vif = vif;
+}
+
+static void rtw_vif_recalc_lps_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ __rtw_vif_recalc_lps(data, vif);
+}
+
+void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif)
+{
+ struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev };
+
+ if (new_vif)
+ __rtw_vif_recalc_lps(&data, new_vif);
+ rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data);
+
+ if (data.count == 1 && data.found_vif->cfg.ps) {
+ rtwdev->ps_enabled = true;
+ } else {
+ rtwdev->ps_enabled = false;
+ rtw_leave_lps(rtwdev);
+ }
+}