[PATCH wireless-next] wifi: brcmfmac: allow opting into PM_MAX power management

Alexander Fischer <[email protected]>
Newsgroups dev.linux.lists.brcm80211,org.kernel.vger.linux-kernel,org.kernel.vger.linux-wireless
Message-ID <[email protected]>
While investigating high idle power consumption on a BCM4364, I found
that brcmfmac always selects PM_FAST when cfg80211 enables power saving.
This keeps the device responsive, but on this system it also kept the
platform latency-tolerance request low enough to prevent deeper package
idle states for most of the idle time.

PM_MAX is already part of the firmware interface, and brcmfmac uses it
while configuring WoWLAN. Using it during normal connected operation
changed the BCM4364 platform latency-tolerance request from 61,440 ns to
3,145,728 ns. In controlled 45-second idle samples, package C8 residency
increased from 6.48% to 20.36%. Several days of normal use also showed
lower battery drain. BCM4364 and BCM4377 have been tested without
observed connectivity or latency regressions.

PM_FAST has been selected since brcmfmac first entered staging in 2010,
and the commit history does not document why it was chosen. Cypress
carried an opt-in module parameter for PM_MAX downstream in 2018. Since
additional wake latency may still be undesirable on other devices or
workloads, changing the existing default would be risky.

A read-only max_pm module parameter makes PM_MAX available while leaving
PM_FAST as the default. PM_OFF remains in use when power saving is
disabled or the interface is a P2P client.

Link: https://github.com/RobertCNelson/linux-dev/blob/master/patches/cypress/brcmfmac/0029-brcmfmac-introduce-module-parameter-to-configure-def.patch
Reviewed-by: Andre Eikmeyer <[email protected]>
Tested-by: Andre Eikmeyer <[email protected]>
Signed-off-by: Alexander Fischer <[email protected]>
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++--
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c   | 6 ++++++
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h   | 2 ++
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 872c48806d09..5e5b8bac53dc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -3327,7 +3327,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
 		goto done;
 	}
 
-	pm = enabled ? PM_FAST : PM_OFF;
+	pm = enabled ? ifp->drvr->settings->default_pm : PM_OFF;
 	/* Do not enable the power save after assoc if it is a p2p interface */
 	if (ifp->vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) {
 		brcmf_dbg(INFO, "Do not enable power save for P2P clients\n");
@@ -7821,7 +7821,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
 
 	brcmf_dongle_scantime(ifp);
 
-	power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
+	power_mode = cfg->pwr_save ? ifp->drvr->settings->default_pm : PM_OFF;
 	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
 	if (err)
 		goto default_conf_out;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index b6027d83e6ab..b2e06abc76f8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -20,6 +20,7 @@
 #include "of.h"
 #include "firmware.h"
 #include "chip.h"
+#include "defs.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -67,6 +68,10 @@ static int brcmf_iapp_enable;
 module_param_named(iapp, brcmf_iapp_enable, int, 0);
 MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
 
+static bool brcmf_max_pm;
+module_param_named(max_pm, brcmf_max_pm, bool, 0400);
+MODULE_PARM_DESC(max_pm, "Use PM_MAX instead of PM_FAST for power management");
+
 #ifdef DEBUG
 /* always succeed brcmf_bus_started() */
 static int brcmf_ignore_probe_fail;
@@ -530,6 +535,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
 	settings->fcmode = brcmf_fcmode;
 	settings->roamoff = !!brcmf_roamoff;
 	settings->iapp = !!brcmf_iapp_enable;
+	settings->default_pm = brcmf_max_pm ? PM_MAX : PM_FAST;
 #ifdef DEBUG
 	settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
 #endif
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 3bdb6984b2dd..d06c734ea82a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -37,6 +37,7 @@ extern struct brcmf_mp_global_t brcmf_mp_global;
  * @feature_disable: Feature_disable bitmask.
  * @fcmode: FWS flow control.
  * @roamoff: Firmware roaming off?
+ * @default_pm: Default power-management mode.
  * @ignore_probe_fail: Ignore probe failure.
  * @trivial_ccode_map: Assume firmware uses ISO3166 country codes with rev 0
  * @country_codes: If available, pointer to struct for translating country codes
@@ -48,6 +49,7 @@ struct brcmf_mp_device {
 	int		fcmode;
 	bool		roamoff;
 	bool		iapp;
+	int		default_pm;
 	bool		ignore_probe_fail;
 	bool		trivial_ccode_map;
 	struct brcmfmac_pd_cc *country_codes;

base-commit: ca800a9302764c445de0da0e84d2252400a770ee
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.