platform/x86/intel/pmc: Refactor platform resume functions to use cnl_resume()
Subsystems (2)
PATCH v2 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.
---
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 v2 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.
---
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,52 @@ 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 (); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); +wrmsrl (MSR_PKG_CST_CONFIG_CONTROL ,per_cpu (pkg_cst_config, cpunum)); +} +void cnl_suspend (struct pmc_dev *pmcdev) { +if (!pm_suspend_via_firmware ()) { +preempt_disable (); +disable_c1_auto_demote (NULL ); +smp_call_function (disable_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +/* * Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. To unblock PC10 during suspend,
@@ -218,6 +264,13 @@ void cnl_suspend(struct pmc_dev *pmcdev)int cnl_resume (struct pmc_dev *pmcdev) { +if (!pm_suspend_via_firmware ()) { +preempt_disable (); +restore_c1_auto_demote (NULL ); +smp_call_function (restore_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +pmc_core_send_ltr_ignore (pmcdev,3 ,0 );return pmc_core_resume_common (pmcdev);
Signature · 1 line
2.43.0
Re: [PATCH V2 2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
Quoted 62 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]>---
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 +0
-0@@ -8,6 +8,8 @@* */ drivers/platform/x86/intel/pmc/cnp.c +2
-0+#include <linux/smp.h> +#include <linux/suspend.h> #include "
core.h"
/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */drivers/platform/x86/intel/pmc/cnp.c +0
-0@@ -206,8 +208,52 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, };drivers/platform/x86/intel/pmc/cnp.c +5
-0+ +/* +* 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, althoughMSR_PKG_CST_CONFIG_CONTROLhas '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.
+ */drivers/platform/x86/intel/pmc/cnp.c +3
-0+ +static DEFINE_PER_CPU(u64, pkg_cst_config); +
drivers/platform/x86/intel/pmc/cnp.c const struct pmc_reg_map cnp_reg_map = { · line 236
Quoted 10 lines
drivers/platform/x86/intel/pmc/cnp.c +10
-0+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);
Do you want to leave pr_debug?
Quoted 14 lines
drivers/platform/x86/intel/pmc/cnp.c +9
-0+} + +static void restore_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); + wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, per_cpu(pkg_cst_config,cpunum));
drivers/platform/x86/intel/pmc/cnp.c +2
-0+} +void
cnl_suspend(struct pmc_dev *pmcdev)
{
drivers/platform/x86/intel/pmc/cnp.c
Quoted 2 lines
drivers/platform/x86/intel/pmc/cnp.c +2
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable ();
Why do you need this?
Thanks,
Srinivas
Quoted 22 lines
drivers/platform/x86/intel/pmc/cnp.c +5
-0+disable_c1_auto_demote (NULL ); +smp_call_function (disable_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +/*
* Due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. To unblock PC10 during suspend,drivers/platform/x86/intel/pmc/cnp.c +0
-0@@ -218,6 +264,13 @@ void cnl_suspend(struct pmc_dev *pmcdev)
intcnl_resume(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +7
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable (); +restore_c1_auto_demote (NULL ); +smp_call_function (restore_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +
pmc_core_send_ltr_ignore(pmcdev, 3, 0);
returnpmc_core_resume_common(pmcdev);
Re: [PATCH V2 2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
Quoted 66 lines · srinivas pandruvada
Quoted 65 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]>---
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 +0
-0@@ -8,6 +8,8 @@* */ drivers/platform/x86/intel/pmc/cnp.c +2
-0+#include <linux/smp.h> +#include <linux/suspend.h> #include "
core.h"
/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */drivers/platform/x86/intel/pmc/cnp.c +0
-0@@ -206,8 +208,52 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, };drivers/platform/x86/intel/pmc/cnp.c +5
-0+ +/* +* 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, althoughMSR_PKG_CST_CONFIG_CONTROLhas '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.
+ */drivers/platform/x86/intel/pmc/cnp.c +6
-0+ +static DEFINE_PER_CPU(u64, pkg_cst_config); + +static void disable_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id ();
Quoted 8 lines
drivers/platform/x86/intel/pmc/cnp.c const struct pmc_reg_map cnp_reg_map = { · line 236
Quoted 7 lines
drivers/platform/x86/intel/pmc/cnp.c +7
-0+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);Do you want to leave
pr_debug?
Thought it could be useful but it can be removed.
Quoted 10 lines
Quoted 10 lines
drivers/platform/x86/intel/pmc/cnp.c +9
-0+} + +static void restore_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); + wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, per_cpu(pkg_cst_config,
Quoted 8 lines
drivers/platform/x86/intel/pmc/cnp.c
Quoted 7 lines
cpunum));
drivers/platform/x86/intel/pmc/cnp.c +2
-0+} +void
cnl_suspend(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +2
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable ();Why do you need this?
To ensure that the cpu doesn't change between the next two calls.
David
Quoted 28 lines
Thanks,
SrinivasQuoted 22 lines
drivers/platform/x86/intel/pmc/cnp.c +5
-0+disable_c1_auto_demote (NULL ); +smp_call_function (disable_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +/*
* Due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. To unblock PC10 during suspend,drivers/platform/x86/intel/pmc/cnp.c +0
-0@@ -218,6 +264,13 @@ void cnl_suspend(struct pmc_dev *pmcdev)
intcnl_resume(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +7
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable (); +restore_c1_auto_demote (NULL ); +smp_call_function (restore_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +
pmc_core_send_ltr_ignore(pmcdev, 3, 0);
returnpmc_core_resume_common(pmcdev);
Re: [PATCH V2 2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
Quoted 106 lines · David E. Box
Quoted 74 lines · srinivas pandruvada
Quoted 73 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]>---
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 +0
-0@@ -8,6 +8,8 @@* */ drivers/platform/x86/intel/pmc/cnp.c +2
-0+#include <linux/smp.h> +#include <linux/suspend.h> #include "
core.h"
/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */drivers/platform/x86/intel/pmc/cnp.c +0
-0@@ -206,8 +208,52 @@ const struct pmc_reg_map cnp_reg_map = { .etr3_offset = ETR3_OFFSET, };drivers/platform/x86/intel/pmc/cnp.c +5
-0+ +/* +* 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, althoughMSR_PKG_CST_CONFIG_CONTROLhas '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.
+ */drivers/platform/x86/intel/pmc/cnp.c +7
-0+ +static DEFINE_PER_CPU(u64, pkg_cst_config); + +static void disable_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); +u64 val;Quoted 8 lines
Quoted 7 lines
drivers/platform/x86/intel/pmc/cnp.c +6
-0+ +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);
Do you want to leave
pr_debug?Thought it could be useful but it can be removed.
Quoted 11 lines
Quoted 11 lines
drivers/platform/x86/intel/pmc/cnp.c +9
-0+} + +static void restore_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); + wrmsrl(MSR_PKG_CST_CONFIG_CONTROL,per_cpu(pkg_cst_config,
Quoted 8 lines
drivers/platform/x86/intel/pmc/cnp.c
Quoted 7 lines
cpunum));
drivers/platform/x86/intel/pmc/cnp.c +2
-0+} +void
cnl_suspend(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +2
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable ();Why do you need this?
Quoted 1 line
To ensure that the cpu doesn't change between the next two calls.
Correct. You need for smp_processor_id()
Generally for this avoiding issue with smp_processor_id(), you can use get_cpu(), which gives current cpu as return value and also disable preemption.
Something like this
this_cpu = get_cpu();
disable_c1_auto_demote(&this_cpu);
smp_call_function_many(cpu_online_mask, disable_c1_auto_demote, NULL,
0);
put_cpu();But fine, this makes your code more complex as you have to pass now a param and use for local_cpu and use smp_procesor_id() for remote call via smp_call..
Thanks,
Srinivas
Quoted 36 lines
David
Quoted 31 lines
Thanks,
SrinivasQuoted 25 lines
drivers/platform/x86/intel/pmc/cnp.c +2
-0+disable_c1_auto_demote (NULL ); + smp_call_function(disable_c1_auto_demote, NULL,0);
drivers/platform/x86/intel/pmc/cnp.c +3
-0+preempt_enable (); + } +/*
* Due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. To unblock PC10 during suspend,drivers/platform/x86/intel/pmc/cnp.c +0
-0@@ -218,6 +264,13 @@ void cnl_suspend(struct pmc_dev *pmcdev)
intcnl_resume(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +4
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable (); +restore_c1_auto_demote (NULL ); + smp_call_function(restore_c1_auto_demote, NULL,0);
drivers/platform/x86/intel/pmc/cnp.c +3
-0+preempt_enable (); + } +
pmc_core_send_ltr_ignore(pmcdev, 3, 0);
returnpmc_core_resume_common(pmcdev);
Re: [PATCH V2 2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
In reply to David E. BoxQuoted 53 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]>---
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 +19
-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,52 @@ 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)
drivers/platform/x86/intel/pmc/cnp.c const struct pmc_reg_map cnp_reg_map = { · line 237
Quoted 10 lines
drivers/platform/x86/intel/pmc/cnp.c +10
-0+{ +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); +}
If you decide to retain the debug statements, I generally prefer to separate them from the rest of the code with empty lines, for clarity.
drivers/platform/x86/intel/pmc/cnp.c const struct pmc_reg_map cnp_reg_map = { · line 247
Quoted 10 lines
drivers/platform/x86/intel/pmc/cnp.c +10
-0+ +static void restore_c1_auto_demote (void *unused) +{ +int cpunum =smp_processor_id (); + +pr_debug ("%s: cpu:%d cst %llx\n" , __func__, cpunum, +per_cpu (pkg_cst_config, cpunum)); +wrmsrl (MSR_PKG_CST_CONFIG_CONTROL ,per_cpu (pkg_cst_config, cpunum)); +} +
I would add something like
static void s2idle_cpu_quirk(smp_call_func_t func)
{
if (pm_suspend_via_firmware())
return;
preempt_disable();
func();
smp_call_function(func, NULL, 0);
preempt_enable();
}drivers/platform/x86/intel/pmc/cnp.c const struct pmc_reg_map cnp_reg_map = { · line 256
Quoted 9 lines
drivers/platform/x86/intel/pmc/cnp.c +7
-0void cnl_suspend (struct pmc_dev *pmcdev) { +if (!pm_suspend_via_firmware ()) { +preempt_disable (); +disable_c1_auto_demote (NULL ); +smp_call_function (disable_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +
And here I'd just do
s2idle_cpu_quirk(disable_c1_auto_demote);
and analogously below.
Quoted 18 lines
drivers/platform/x86/intel/pmc/cnp.c +7
-1/* * Due to a hardware limitation, the GBE LTR blocks PC10 * when a cable is attached. To unblock PC10 during suspend, @@ -218,6 +264,13 @@ void cnl_suspend(struct pmc_dev *pmcdev)int cnl_resume (struct pmc_dev *pmcdev) { +if (!pm_suspend_via_firmware ()) { +preempt_disable (); +restore_c1_auto_demote (NULL ); +smp_call_function (restore_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +pmc_core_send_ltr_ignore (pmcdev,3 ,0 );return pmc_core_resume_common (pmcdev); --
Re: [PATCH V2 2/2] platform/x86/intel/pmc: Disable C1 auto-demotion during suspend
In reply to David E. Box+Ricardo
Quoted 11 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]>---
[...]
drivers/platform/x86/intel/pmc/cnp.c const struct pmc_reg_map cnp_reg_map = { · line 255
Quoted 9 lines
void
cnl_suspend(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +6
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable (); +disable_c1_auto_demote (NULL ); +smp_call_function (disable_c1_auto_demote,NULL ,0 ); +preempt_enable (); + }
As suggested by Ricardo using the following will work avoiding separate local CPU call. Preemption will be disabled, no need separate call. Also cpu_online_mask can't be changed during these callbacks.
if (!pm_suspend_via_firmware())
on_each_cpu(disable_c1_auto_demote, NULL, true);
I think you need wait=true. I have seen on some occasions you will miss msr write as we called mwait before before async calls finished.
Thanks,
Srinivas
Quoted 18 lines
+
/*
* Due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. To unblock PC10 during suspend,(quoted diff) +0
-0@@ -218,6 +264,13 @@ void cnl_suspend(struct pmc_dev *pmcdev)
intcnl_resume(struct pmc_dev *pmcdev)
{drivers/platform/x86/intel/pmc/cnp.c +7
-0+if (!pm_suspend_via_firmware ()) { +preempt_disable (); +restore_c1_auto_demote (NULL ); +smp_call_function (restore_c1_auto_demote,NULL ,0 ); +preempt_enable (); + } +
pmc_core_send_ltr_ignore(pmcdev, 3, 0);
returnpmc_core_resume_common(pmcdev);