platform/x86/intel/pmc: Refactor platform resume functions to use cnl_resume()
Subsystems (2)
PATCH v3 1/2 platform/x86/intel/pmc: Refactor platform resume functions to use cnl_resume()
Several platform resume functions currently call pmc_core_send_ltr_ignore() and pmc_core_resume_common(), both of which are already called by cnl_resume(). Simplify the code by having these functions call cnl_resume() directly.
---
V3 - no change
V2 - New patch. Split from V1
drivers/platform/x86/intel/pmc/arl.c | 3 +-- drivers/platform/x86/intel/pmc/lnl.c | 3 +-- drivers/platform/x86/intel/pmc/mtl.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-)
drivers/platform/x86/intel/pmc/arl.c +1 -2
@@ -687,9 +687,8 @@ static void arl_d3_fixup(void)static int arl_resume (struct pmc_dev *pmcdev) {arl_d3_fixup (); -pmc_core_send_ltr_ignore (pmcdev,3 ,0 ); -return pmc_core_resume_common (pmcdev); +return cnl_resume (pmcdev); }int arl_core_init (struct pmc_dev *pmcdev)
drivers/platform/x86/intel/pmc/lnl.c +1 -2
@@ -546,9 +546,8 @@ static void lnl_d3_fixup(void)static int lnl_resume (struct pmc_dev *pmcdev) {lnl_d3_fixup (); -pmc_core_send_ltr_ignore (pmcdev,3 ,0 ); -return pmc_core_resume_common (pmcdev); +return cnl_resume (pmcdev); }int lnl_core_init (struct pmc_dev *pmcdev)
drivers/platform/x86/intel/pmc/mtl.c +1 -2
@@ -988,9 +988,8 @@ static void mtl_d3_fixup(void)static int mtl_resume (struct pmc_dev *pmcdev) {mtl_d3_fixup (); -pmc_core_send_ltr_ignore (pmcdev,3 ,0 ); -return pmc_core_resume_common (pmcdev); +return cnl_resume (pmcdev); }int mtl_core_init (struct pmc_dev *pmcdev)
base-commit: 9852d85ec9d492ebef56dc5f229416c925758edc
Signature · 1 line
2.43.0
PATCH v3 2/2 platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
On some platforms, aggressive C1 auto-demotion may lead to failure to enter the deepest C-state during suspend-to-idle, causing high power consumption. To prevent this, disable C1 auto-demotion during suspend and re-enable on resume.
---
V3 - Use s2idle wrapper function suggested by Rafael
- Use on_each_cpu() suggested by Ricardo
V2 - Remove #define DEBUG
- Move refactor of cnl_resume() to separate patch
- Use smp_call_function() to disable and restore C1_AUTO_DEMOTE
- Add comment that the MSR is per core, not per package.
- Add comment that the online cpu mask remains unchanged during suspend due to frozen userspace.
drivers/platform/x86/intel/pmc/cnp.c | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
drivers/platform/x86/intel/pmc/cnp.c +53 -0
@@ -8,6 +8,8 @@* */ +#include <linux/smp.h> +#include <linux/suspend.h> #include "core.h" /* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */
@@ -206,8 +208,57 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, }; + +/* +* Disable C1 auto-demotion +* +* Aggressive C1 auto-demotion may lead to failure to enter the deepest C-state +* during suspend-to-idle, causing high power consumption. To prevent this, we +* disable C1 auto-demotion during suspend and re-enable on resume. +* +* Note that, although MSR_PKG_CST_CONFIG_CONTROL has 'package' in its name, it +* is actually a per-core MSR on client platforms, affecting only a single CPU. +* Therefore, it must be configured on all online CPUs. The online cpu mask is +* unchanged during the phase of suspend/resume as user space is frozen. +*/ + +static DEFINE_PER_CPU(u64, pkg_cst_config); + +static void disable_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); +u64 val; + +rdmsrl (MSR_PKG_CST_CONFIG_CONTROL , val); +per_cpu (pkg_cst_config, cpunum) = val; + val &= ~NHM_C1_AUTO_DEMOTE ; +wrmsrl (MSR_PKG_CST_CONFIG_CONTROL , val); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, val); +} + +static void restore_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); + +wrmsrl (MSR_PKG_CST_CONFIG_CONTROL ,per_cpu (pkg_cst_config, cpunum)); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); +} + +static void s2idle_cpu_quirk (smp_call_func_t func) +{ +if (pm_suspend_via_firmware ()) +return ; + +on_each_cpu (func,NULL , true); +} +void cnl_suspend (struct pmc_dev *pmcdev) { +s2idle_cpu_quirk (disable_c1_auto_demote); +/* * Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. To unblock PC10 during suspend,
@@ -218,6 +269,8 @@ void cnl_suspend(struct pmc_dev *pmcdev)int cnl_resume (struct pmc_dev *pmcdev) { +s2idle_cpu_quirk (restore_c1_auto_demote); +pmc_core_send_ltr_ignore (pmcdev,3 ,0 );return pmc_core_resume_common (pmcdev);
Signature · 1 line
2.43.0
Re: [PATCH V3 2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
Quoted 10 lines · David E. Box
On some platforms, aggressive C1 auto-demotion may lead to failure to enter the deepest C-state during suspend-to-idle, causing high power consumption. To prevent this, disable C1 auto-demotion during suspend and re-enable on resume.
Signed-off-by David E. Box <[email protected]>---
V3 - Use s2idle wrapper function suggested by Rafael
- Useon_each_cpu()suggested by Ricardo
Quoted 94 lines
V2 - Remove #define DEBUG
- Move refactor ofcnl_resume()to separate patch
- Usesmp_call_function()to disable and restoreC1_AUTO_DEMOTE
- Add comment that the MSR is per core, not per package.
- Add comment that the online cpu mask remains unchanged during suspend due to frozen userspace.drivers/platform/x86/intel/pmc/cnp.c | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)drivers/platform/x86/intel/pmc/cnp.c +53
-1@@ -8,6 +8,8 @@* */ +#include <linux/smp.h> +#include <linux/suspend.h> #include "core.h" /* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */ @@ -206,8 +208,57 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, }; + +/* +* Disable C1 auto-demotion +* +* Aggressive C1 auto-demotion may lead to failure to enter the deepest C-state +* during suspend-to-idle, causing high power consumption. To prevent this, we +* disable C1 auto-demotion during suspend and re-enable on resume. +* +* Note that, although MSR_PKG_CST_CONFIG_CONTROL has 'package' in its name, it +* is actually a per-core MSR on client platforms, affecting only a single CPU. +* Therefore, it must be configured on all online CPUs. The online cpu mask is +* unchanged during the phase of suspend/resume as user space is frozen. +*/ + +static DEFINE_PER_CPU(u64, pkg_cst_config); + +static void disable_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); +u64 val; + +rdmsrl (MSR_PKG_CST_CONFIG_CONTROL , val); +per_cpu (pkg_cst_config, cpunum) = val; + val &= ~NHM_C1_AUTO_DEMOTE ; +wrmsrl (MSR_PKG_CST_CONFIG_CONTROL , val); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, val); +} + +static void restore_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); + +wrmsrl (MSR_PKG_CST_CONFIG_CONTROL ,per_cpu (pkg_cst_config, cpunum)); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); +} + +static void s2idle_cpu_quirk (smp_call_func_t func) +{ +if (pm_suspend_via_firmware ()) +return ; + +on_each_cpu (func,NULL , true); +} +void cnl_suspend (struct pmc_dev *pmcdev) { +s2idle_cpu_quirk (disable_c1_auto_demote); +/* * Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. To unblock PC10 during suspend, @@ -218,6 +269,8 @@ void cnl_suspend(struct pmc_dev *pmcdev)int cnl_resume (struct pmc_dev *pmcdev) { +s2idle_cpu_quirk (restore_c1_auto_demote); +pmc_core_send_ltr_ignore (pmcdev,3 ,0 );return pmc_core_resume_common (pmcdev); --2.43.0
Quoted 11 lines · David E. Box
Several platform resume functions currently call
pmc_core_send_ltr_ignore()andpmc_core_resume_common(), both of which are already called bycnl_resume(). Simplify the code by having these functions callcnl_resume()directly.Signed-off-by David E. Box <[email protected]>---
V3 - no changeV2 - New patch. Split from V1
Quoted 57 lines
drivers/platform/x86/intel/pmc/arl.c | 3 +-- drivers/platform/x86/intel/pmc/lnl.c | 3 +-- drivers/platform/x86/intel/pmc/mtl.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-)drivers/platform/x86/intel/pmc/arl.c +1
-2@@ -687,9 +687,8 @@ static void arl_d3_fixup(void)static int arl_resume (struct pmc_dev *pmcdev) {arl_d3_fixup (); -pmc_core_send_ltr_ignore (pmcdev,3 ,0 ); -return pmc_core_resume_common (pmcdev); +return cnl_resume (pmcdev); }int arl_core_init (struct pmc_dev *pmcdev)drivers/platform/x86/intel/pmc/lnl.c +1
-2@@ -546,9 +546,8 @@ static void lnl_d3_fixup(void)static int lnl_resume (struct pmc_dev *pmcdev) {lnl_d3_fixup (); -pmc_core_send_ltr_ignore (pmcdev,3 ,0 ); -return pmc_core_resume_common (pmcdev); +return cnl_resume (pmcdev); }int lnl_core_init (struct pmc_dev *pmcdev)drivers/platform/x86/intel/pmc/mtl.c +1
-2@@ -988,9 +988,8 @@ static void mtl_d3_fixup(void)static int mtl_resume (struct pmc_dev *pmcdev) {mtl_d3_fixup (); -pmc_core_send_ltr_ignore (pmcdev,3 ,0 ); -return pmc_core_resume_common (pmcdev); +return cnl_resume (pmcdev); }int mtl_core_init (struct pmc_dev *pmcdev)base-commit:
9852d85ec9d492ebef56dc5f229416c925758edc--
2.43.0
Ilpo Järvinen
maintainerQuoted 6 lines · David E. Box
Several platform resume functions currently call
pmc_core_send_ltr_ignore()andpmc_core_resume_common(), both of which are already called bycnl_resume(). Simplify the code by having these functions callcnl_resume()directly.
Thank you for your contribution, it has been applied to my local review-ilpo branch. Note it will show up in the public platform-drivers-x86/review-ilpo branch only once I've pushed my local branch there, which might take a while.
The list of commits applied:
[1/2] platform/x86/intel/pmc: Refactor platform resume functions to use cnl_resume()
commit: 9fe43c8020a60b9c9ff44c4a9914e7e7df63084e
[2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
commit: 7a797cc9f80915cc5f1a5aee46d14880eb444644--
i.