* [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling
@ 2023-11-14 10:07 Stephan Gerhold
2023-11-14 10:07 ` [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices Stephan Gerhold
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Stephan Gerhold @ 2023-11-14 10:07 UTC (permalink / raw)
To: Viresh Kumar, Ulf Hansson
Cc: Andy Gross, Bjorn Andersson, Konrad Dybcio, Ilia Lin,
Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, Stephan Gerhold, stable
The power domain scaling setup for QCS404 and MSM8909 in
cpufreq-com-nvmem does not work correctly at the moment because the
genpd core ignores all the performance state votes that are specified in
the CPU OPP table. This happens because nothing in the driver makes the
genpd core aware that the power domains are actively being consumed by
the CPU.
Fix this by marking the devices as runtime active. Also mark the devices
to be in the "awake path" during system suspend so that performance
state votes necessary for the CPU are preserved during system suspend.
While all the patches in this series are needed for full functionality,
the cpufreq and pmdomain patches can be merged independently. There is
no compile-time dependency between those two.
Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
---
Changes in v3:
- Drop patches with MSM8909 definitions that were applied already
- Add extra patch to fix system suspend properly by using
device_set_awake_path() instead of dev_pm_syscore_device()
- Set GENPD_FLAG_ACTIVE_WAKEUP for rpmpd so that performance state votes
needed by the CPU are preserved during suspend
- Link to v2: https://lore.kernel.org/r/20231018-msm8909-cpufreq-v2-0-0962df95f654@kernkonzept.com
Changes in v2:
- Reword commit messages based on discussion with Uffe
- Use generic power domain name "perf" (Uffe)
- Fix pm_runtime error handling (Uffe)
- Add allocation cleanup patch as preparation
- Fix ordering of qcom,msm8909 compatible (Konrad)
- cpufreq-dt-platdev blocklist/dt-bindings patches were applied already
- Link to v1: https://lore.kernel.org/r/20230912-msm8909-cpufreq-v1-0-767ce66b544b@kernkonzept.com
---
Stephan Gerhold (3):
cpufreq: qcom-nvmem: Enable virtual power domain devices
cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend
pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP
drivers/cpufreq/qcom-cpufreq-nvmem.c | 73 ++++++++++++++++++++++++++++++++++--
drivers/pmdomain/qcom/rpmpd.c | 1 +
2 files changed, 71 insertions(+), 3 deletions(-)
---
base-commit: b85ea95d086471afb4ad062012a4d73cd328fa86
change-id: 20230906-msm8909-cpufreq-dff238de9ff3
Best regards,
--
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
Kernkonzept GmbH at Dresden, Germany, HRB 31129, CEO Dr.-Ing. Michael Hohmuth
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices
2023-11-14 10:07 [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Stephan Gerhold
@ 2023-11-14 10:07 ` Stephan Gerhold
2023-11-22 9:47 ` Ulf Hansson
2023-11-14 10:07 ` [PATCH v3 2/3] cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend Stephan Gerhold
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Stephan Gerhold @ 2023-11-14 10:07 UTC (permalink / raw)
To: Viresh Kumar, Ulf Hansson
Cc: Andy Gross, Bjorn Andersson, Konrad Dybcio, Ilia Lin,
Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, Stephan Gerhold, stable
The genpd core caches performance state votes from devices that are
runtime suspended as of commit 3c5a272202c2 ("PM: domains: Improve
runtime PM performance state handling"). They get applied once the
device becomes active again.
To attach the power domains needed by qcom-cpufreq-nvmem the OPP core
calls genpd_dev_pm_attach_by_id(). This results in "virtual" dummy
devices that use runtime PM only to control the enable and performance
state for the attached power domain.
However, at the moment nothing ever resumes the virtual devices created
for qcom-cpufreq-nvmem. They remain permanently runtime suspended. This
means that performance state votes made during cpufreq scaling get
always cached and never applied to the hardware.
Fix this by enabling the devices after attaching them.
Without this fix performance states votes are silently ignored, and the
CPU/CPR voltage is never adjusted. This has been broken since 5.14 but
for some reason no one noticed this on QCS404 so far.
Cc: stable@vger.kernel.org
Fixes: 1cb8339ca225 ("cpufreq: qcom: Add support for qcs404 on nvmem driver")
Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
---
drivers/cpufreq/qcom-cpufreq-nvmem.c | 46 +++++++++++++++++++++++++++++++++---
1 file changed, 43 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index 6355a39418c5..d239a45ed497 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -25,6 +25,7 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
@@ -55,6 +56,7 @@ struct qcom_cpufreq_match_data {
struct qcom_cpufreq_drv_cpu {
int opp_token;
+ struct device **virt_devs;
};
struct qcom_cpufreq_drv {
@@ -424,6 +426,18 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
.get_version = qcom_cpufreq_ipq8074_name_version,
};
+static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
+{
+ const char * const *name = drv->data->genpd_names;
+ int i;
+
+ if (!drv->cpus[cpu].virt_devs)
+ return;
+
+ for (i = 0; *name; i++, name++)
+ pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
+}
+
static int qcom_cpufreq_probe(struct platform_device *pdev)
{
struct qcom_cpufreq_drv *drv;
@@ -478,6 +492,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
of_node_put(np);
for_each_possible_cpu(cpu) {
+ struct device **virt_devs = NULL;
struct dev_pm_opp_config config = {
.supported_hw = NULL,
};
@@ -498,7 +513,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
if (drv->data->genpd_names) {
config.genpd_names = drv->data->genpd_names;
- config.virt_devs = NULL;
+ config.virt_devs = &virt_devs;
}
if (config.supported_hw || config.genpd_names) {
@@ -509,6 +524,27 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
goto free_opp;
}
}
+
+ if (virt_devs) {
+ const char * const *name = config.genpd_names;
+ int i, j;
+
+ for (i = 0; *name; i++, name++) {
+ ret = pm_runtime_resume_and_get(virt_devs[i]);
+ if (ret) {
+ dev_err(cpu_dev, "failed to resume %s: %d\n",
+ *name, ret);
+
+ /* Rollback previous PM runtime calls */
+ name = config.genpd_names;
+ for (j = 0; *name && j < i; j++, name++)
+ pm_runtime_put(virt_devs[j]);
+
+ goto free_opp;
+ }
+ }
+ drv->cpus[cpu].virt_devs = virt_devs;
+ }
}
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
@@ -522,8 +558,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
dev_err(cpu_dev, "Failed to register platform device\n");
free_opp:
- for_each_possible_cpu(cpu)
+ for_each_possible_cpu(cpu) {
+ qcom_cpufreq_put_virt_devs(drv, cpu);
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
+ }
return ret;
}
@@ -534,8 +572,10 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
platform_device_unregister(cpufreq_dt_pdev);
- for_each_possible_cpu(cpu)
+ for_each_possible_cpu(cpu) {
+ qcom_cpufreq_put_virt_devs(drv, cpu);
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
+ }
}
static struct platform_driver qcom_cpufreq_driver = {
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 2/3] cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend
2023-11-14 10:07 [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Stephan Gerhold
2023-11-14 10:07 ` [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices Stephan Gerhold
@ 2023-11-14 10:07 ` Stephan Gerhold
2023-11-22 9:48 ` Ulf Hansson
2023-11-14 10:07 ` [PATCH v3 3/3] pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP Stephan Gerhold
2023-11-23 7:39 ` [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Viresh Kumar
3 siblings, 1 reply; 10+ messages in thread
From: Stephan Gerhold @ 2023-11-14 10:07 UTC (permalink / raw)
To: Viresh Kumar, Ulf Hansson
Cc: Andy Gross, Bjorn Andersson, Konrad Dybcio, Ilia Lin,
Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, Stephan Gerhold
From the Linux point of view, the power domains used by the CPU must
stay always-on. This is because we still need the CPU to keep running
until the last instruction, which will typically be a firmware call that
shuts down the CPU cleanly.
At the moment the power domain votes (enable + performance state) are
dropped during system suspend, which means the CPU could potentially
malfunction while entering suspend.
We need to distinguish between two different setups used with
qcom-cpufreq-nvmem:
1. CPR power domain: The backing regulator used by CPR should stay
always-on in Linux; it is typically disabled automatically by
hardware when the CPU enters a deep idle state. However, we
should pause the CPR state machine during system suspend.
2. RPMPD: The power domains used by the CPU should stay always-on
in Linux (also across system suspend). The CPU typically only
uses the *_AO ("active-only") variants of the power domains in
RPMPD. For those, the RPM firmware will automatically drop
the votes internally when the CPU enters a deep idle state.
Make this work correctly by calling device_set_awake_path() on the
virtual genpd devices, so that the votes are maintained across system
suspend. The power domain drivers need to set GENPD_FLAG_ACTIVE_WAKEUP
to opt into staying on during system suspend.
For now we only set this for the RPMPD case. For CPR, not setting it
will ensure the state machine is still paused during system suspend,
while the backing regulator will stay on with "regulator-always-on".
Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
---
This patch can be merged independently from the pmdomain one for RPMPD.
Both are needed to actually preserve the votes during system suspend but
there is no compile-time dependency.
---
drivers/cpufreq/qcom-cpufreq-nvmem.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
index d239a45ed497..ea05d9d67490 100644
--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -23,6 +23,7 @@
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
@@ -426,6 +427,18 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
.get_version = qcom_cpufreq_ipq8074_name_version,
};
+static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
+{
+ const char * const *name = drv->data->genpd_names;
+ int i;
+
+ if (!drv->cpus[cpu].virt_devs)
+ return;
+
+ for (i = 0; *name; i++, name++)
+ device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
+}
+
static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
{
const char * const *name = drv->data->genpd_names;
@@ -578,11 +591,25 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
}
}
+static int qcom_cpufreq_suspend(struct device *dev)
+{
+ struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu)
+ qcom_cpufreq_suspend_virt_devs(drv, cpu);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(qcom_cpufreq_pm_ops, qcom_cpufreq_suspend, NULL);
+
static struct platform_driver qcom_cpufreq_driver = {
.probe = qcom_cpufreq_probe,
.remove_new = qcom_cpufreq_remove,
.driver = {
.name = "qcom-cpufreq-nvmem",
+ .pm = pm_sleep_ptr(&qcom_cpufreq_pm_ops),
},
};
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/3] pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP
2023-11-14 10:07 [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Stephan Gerhold
2023-11-14 10:07 ` [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices Stephan Gerhold
2023-11-14 10:07 ` [PATCH v3 2/3] cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend Stephan Gerhold
@ 2023-11-14 10:07 ` Stephan Gerhold
2023-11-22 9:48 ` Ulf Hansson
2023-11-23 7:39 ` [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Viresh Kumar
3 siblings, 1 reply; 10+ messages in thread
From: Stephan Gerhold @ 2023-11-14 10:07 UTC (permalink / raw)
To: Viresh Kumar, Ulf Hansson
Cc: Andy Gross, Bjorn Andersson, Konrad Dybcio, Ilia Lin,
Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, Stephan Gerhold
Set GENPD_FLAG_ACTIVE_WAKEUP for all RPM power domains so that power
domains necessary for wakeup/"awake path" devices are kept on across
suspend.
This is needed for example for the *_AO ("active-only") variants of the
RPMPDs used by the CPU. Those should maintain their votes also across
system suspend to ensure the CPU can keep running for the whole suspend
process (ending in a firmware call). When the RPM firmware detects that
the CPUs are in a deep idle state it will drop those votes automatically.
Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
---
drivers/pmdomain/qcom/rpmpd.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c
index 07590a3ef19c..7796d65f96e8 100644
--- a/drivers/pmdomain/qcom/rpmpd.c
+++ b/drivers/pmdomain/qcom/rpmpd.c
@@ -1044,6 +1044,7 @@ static int rpmpd_probe(struct platform_device *pdev)
rpmpds[i]->pd.power_off = rpmpd_power_off;
rpmpds[i]->pd.power_on = rpmpd_power_on;
rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
+ rpmpds[i]->pd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
pm_genpd_init(&rpmpds[i]->pd, NULL, true);
data->domains[i] = &rpmpds[i]->pd;
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices
2023-11-14 10:07 ` [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices Stephan Gerhold
@ 2023-11-22 9:47 ` Ulf Hansson
0 siblings, 0 replies; 10+ messages in thread
From: Ulf Hansson @ 2023-11-22 9:47 UTC (permalink / raw)
To: Stephan Gerhold
Cc: Viresh Kumar, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Ilia Lin, Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, stable
On Tue, 14 Nov 2023 at 11:08, Stephan Gerhold
<stephan.gerhold@kernkonzept.com> wrote:
>
> The genpd core caches performance state votes from devices that are
> runtime suspended as of commit 3c5a272202c2 ("PM: domains: Improve
> runtime PM performance state handling"). They get applied once the
> device becomes active again.
>
> To attach the power domains needed by qcom-cpufreq-nvmem the OPP core
> calls genpd_dev_pm_attach_by_id(). This results in "virtual" dummy
> devices that use runtime PM only to control the enable and performance
> state for the attached power domain.
>
> However, at the moment nothing ever resumes the virtual devices created
> for qcom-cpufreq-nvmem. They remain permanently runtime suspended. This
> means that performance state votes made during cpufreq scaling get
> always cached and never applied to the hardware.
>
> Fix this by enabling the devices after attaching them.
>
> Without this fix performance states votes are silently ignored, and the
> CPU/CPR voltage is never adjusted. This has been broken since 5.14 but
> for some reason no one noticed this on QCS404 so far.
>
> Cc: stable@vger.kernel.org
> Fixes: 1cb8339ca225 ("cpufreq: qcom: Add support for qcs404 on nvmem driver")
> Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Kind regards
Uffe
> ---
> drivers/cpufreq/qcom-cpufreq-nvmem.c | 46 +++++++++++++++++++++++++++++++++---
> 1 file changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> index 6355a39418c5..d239a45ed497 100644
> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> @@ -25,6 +25,7 @@
> #include <linux/platform_device.h>
> #include <linux/pm_domain.h>
> #include <linux/pm_opp.h>
> +#include <linux/pm_runtime.h>
> #include <linux/slab.h>
> #include <linux/soc/qcom/smem.h>
>
> @@ -55,6 +56,7 @@ struct qcom_cpufreq_match_data {
>
> struct qcom_cpufreq_drv_cpu {
> int opp_token;
> + struct device **virt_devs;
> };
>
> struct qcom_cpufreq_drv {
> @@ -424,6 +426,18 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
> .get_version = qcom_cpufreq_ipq8074_name_version,
> };
>
> +static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
> +{
> + const char * const *name = drv->data->genpd_names;
> + int i;
> +
> + if (!drv->cpus[cpu].virt_devs)
> + return;
> +
> + for (i = 0; *name; i++, name++)
> + pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
> +}
> +
> static int qcom_cpufreq_probe(struct platform_device *pdev)
> {
> struct qcom_cpufreq_drv *drv;
> @@ -478,6 +492,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> of_node_put(np);
>
> for_each_possible_cpu(cpu) {
> + struct device **virt_devs = NULL;
> struct dev_pm_opp_config config = {
> .supported_hw = NULL,
> };
> @@ -498,7 +513,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
>
> if (drv->data->genpd_names) {
> config.genpd_names = drv->data->genpd_names;
> - config.virt_devs = NULL;
> + config.virt_devs = &virt_devs;
> }
>
> if (config.supported_hw || config.genpd_names) {
> @@ -509,6 +524,27 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> goto free_opp;
> }
> }
> +
> + if (virt_devs) {
> + const char * const *name = config.genpd_names;
> + int i, j;
> +
> + for (i = 0; *name; i++, name++) {
> + ret = pm_runtime_resume_and_get(virt_devs[i]);
> + if (ret) {
> + dev_err(cpu_dev, "failed to resume %s: %d\n",
> + *name, ret);
> +
> + /* Rollback previous PM runtime calls */
> + name = config.genpd_names;
> + for (j = 0; *name && j < i; j++, name++)
> + pm_runtime_put(virt_devs[j]);
> +
> + goto free_opp;
> + }
> + }
> + drv->cpus[cpu].virt_devs = virt_devs;
> + }
> }
>
> cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
> @@ -522,8 +558,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
> dev_err(cpu_dev, "Failed to register platform device\n");
>
> free_opp:
> - for_each_possible_cpu(cpu)
> + for_each_possible_cpu(cpu) {
> + qcom_cpufreq_put_virt_devs(drv, cpu);
> dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
> + }
> return ret;
> }
>
> @@ -534,8 +572,10 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
>
> platform_device_unregister(cpufreq_dt_pdev);
>
> - for_each_possible_cpu(cpu)
> + for_each_possible_cpu(cpu) {
> + qcom_cpufreq_put_virt_devs(drv, cpu);
> dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
> + }
> }
>
> static struct platform_driver qcom_cpufreq_driver = {
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend
2023-11-14 10:07 ` [PATCH v3 2/3] cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend Stephan Gerhold
@ 2023-11-22 9:48 ` Ulf Hansson
0 siblings, 0 replies; 10+ messages in thread
From: Ulf Hansson @ 2023-11-22 9:48 UTC (permalink / raw)
To: Stephan Gerhold
Cc: Viresh Kumar, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Ilia Lin, Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold
On Tue, 14 Nov 2023 at 11:08, Stephan Gerhold
<stephan.gerhold@kernkonzept.com> wrote:
>
> From the Linux point of view, the power domains used by the CPU must
> stay always-on. This is because we still need the CPU to keep running
> until the last instruction, which will typically be a firmware call that
> shuts down the CPU cleanly.
>
> At the moment the power domain votes (enable + performance state) are
> dropped during system suspend, which means the CPU could potentially
> malfunction while entering suspend.
>
> We need to distinguish between two different setups used with
> qcom-cpufreq-nvmem:
>
> 1. CPR power domain: The backing regulator used by CPR should stay
> always-on in Linux; it is typically disabled automatically by
> hardware when the CPU enters a deep idle state. However, we
> should pause the CPR state machine during system suspend.
>
> 2. RPMPD: The power domains used by the CPU should stay always-on
> in Linux (also across system suspend). The CPU typically only
> uses the *_AO ("active-only") variants of the power domains in
> RPMPD. For those, the RPM firmware will automatically drop
> the votes internally when the CPU enters a deep idle state.
>
> Make this work correctly by calling device_set_awake_path() on the
> virtual genpd devices, so that the votes are maintained across system
> suspend. The power domain drivers need to set GENPD_FLAG_ACTIVE_WAKEUP
> to opt into staying on during system suspend.
>
> For now we only set this for the RPMPD case. For CPR, not setting it
> will ensure the state machine is still paused during system suspend,
> while the backing regulator will stay on with "regulator-always-on".
>
> Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Kind regards
Uffe
> ---
> This patch can be merged independently from the pmdomain one for RPMPD.
> Both are needed to actually preserve the votes during system suspend but
> there is no compile-time dependency.
> ---
> drivers/cpufreq/qcom-cpufreq-nvmem.c | 27 +++++++++++++++++++++++++++
> 1 file changed, 27 insertions(+)
>
> diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> index d239a45ed497..ea05d9d67490 100644
> --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
> +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
> @@ -23,6 +23,7 @@
> #include <linux/nvmem-consumer.h>
> #include <linux/of.h>
> #include <linux/platform_device.h>
> +#include <linux/pm.h>
> #include <linux/pm_domain.h>
> #include <linux/pm_opp.h>
> #include <linux/pm_runtime.h>
> @@ -426,6 +427,18 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
> .get_version = qcom_cpufreq_ipq8074_name_version,
> };
>
> +static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
> +{
> + const char * const *name = drv->data->genpd_names;
> + int i;
> +
> + if (!drv->cpus[cpu].virt_devs)
> + return;
> +
> + for (i = 0; *name; i++, name++)
> + device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
> +}
> +
> static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
> {
> const char * const *name = drv->data->genpd_names;
> @@ -578,11 +591,25 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
> }
> }
>
> +static int qcom_cpufreq_suspend(struct device *dev)
> +{
> + struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
> + unsigned int cpu;
> +
> + for_each_possible_cpu(cpu)
> + qcom_cpufreq_suspend_virt_devs(drv, cpu);
> +
> + return 0;
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(qcom_cpufreq_pm_ops, qcom_cpufreq_suspend, NULL);
> +
> static struct platform_driver qcom_cpufreq_driver = {
> .probe = qcom_cpufreq_probe,
> .remove_new = qcom_cpufreq_remove,
> .driver = {
> .name = "qcom-cpufreq-nvmem",
> + .pm = pm_sleep_ptr(&qcom_cpufreq_pm_ops),
> },
> };
>
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP
2023-11-14 10:07 ` [PATCH v3 3/3] pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP Stephan Gerhold
@ 2023-11-22 9:48 ` Ulf Hansson
0 siblings, 0 replies; 10+ messages in thread
From: Ulf Hansson @ 2023-11-22 9:48 UTC (permalink / raw)
To: Stephan Gerhold
Cc: Viresh Kumar, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Ilia Lin, Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold
On Tue, 14 Nov 2023 at 11:08, Stephan Gerhold
<stephan.gerhold@kernkonzept.com> wrote:
>
> Set GENPD_FLAG_ACTIVE_WAKEUP for all RPM power domains so that power
> domains necessary for wakeup/"awake path" devices are kept on across
> suspend.
>
> This is needed for example for the *_AO ("active-only") variants of the
> RPMPDs used by the CPU. Those should maintain their votes also across
> system suspend to ensure the CPU can keep running for the whole suspend
> process (ending in a firmware call). When the RPM firmware detects that
> the CPUs are in a deep idle state it will drop those votes automatically.
>
> Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Kind regards
Uffe
> ---
> drivers/pmdomain/qcom/rpmpd.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c
> index 07590a3ef19c..7796d65f96e8 100644
> --- a/drivers/pmdomain/qcom/rpmpd.c
> +++ b/drivers/pmdomain/qcom/rpmpd.c
> @@ -1044,6 +1044,7 @@ static int rpmpd_probe(struct platform_device *pdev)
> rpmpds[i]->pd.power_off = rpmpd_power_off;
> rpmpds[i]->pd.power_on = rpmpd_power_on;
> rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
> + rpmpds[i]->pd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
> pm_genpd_init(&rpmpds[i]->pd, NULL, true);
>
> data->domains[i] = &rpmpds[i]->pd;
>
> --
> 2.39.2
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling
2023-11-14 10:07 [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Stephan Gerhold
` (2 preceding siblings ...)
2023-11-14 10:07 ` [PATCH v3 3/3] pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP Stephan Gerhold
@ 2023-11-23 7:39 ` Viresh Kumar
2023-11-23 16:14 ` Ulf Hansson
3 siblings, 1 reply; 10+ messages in thread
From: Viresh Kumar @ 2023-11-23 7:39 UTC (permalink / raw)
To: Stephan Gerhold
Cc: Ulf Hansson, Andy Gross, Bjorn Andersson, Konrad Dybcio, Ilia Lin,
Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, stable
On 14-11-23, 11:07, Stephan Gerhold wrote:
> The power domain scaling setup for QCS404 and MSM8909 in
> cpufreq-com-nvmem does not work correctly at the moment because the
> genpd core ignores all the performance state votes that are specified in
> the CPU OPP table. This happens because nothing in the driver makes the
> genpd core aware that the power domains are actively being consumed by
> the CPU.
>
> Fix this by marking the devices as runtime active. Also mark the devices
> to be in the "awake path" during system suspend so that performance
> state votes necessary for the CPU are preserved during system suspend.
>
> While all the patches in this series are needed for full functionality,
> the cpufreq and pmdomain patches can be merged independently. There is
> no compile-time dependency between those two.
>
> Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
> ---
> Changes in v3:
> - Drop patches with MSM8909 definitions that were applied already
> - Add extra patch to fix system suspend properly by using
> device_set_awake_path() instead of dev_pm_syscore_device()
> - Set GENPD_FLAG_ACTIVE_WAKEUP for rpmpd so that performance state votes
> needed by the CPU are preserved during suspend
> - Link to v2: https://lore.kernel.org/r/20231018-msm8909-cpufreq-v2-0-0962df95f654@kernkonzept.com
Applied. Thanks.
I picked the pmdomain patch too, lemme know if that needs to go via
some other tree.
--
viresh
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling
2023-11-23 7:39 ` [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Viresh Kumar
@ 2023-11-23 16:14 ` Ulf Hansson
2023-11-27 4:22 ` Viresh Kumar
0 siblings, 1 reply; 10+ messages in thread
From: Ulf Hansson @ 2023-11-23 16:14 UTC (permalink / raw)
To: Viresh Kumar
Cc: Stephan Gerhold, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Ilia Lin, Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, stable
On Thu, 23 Nov 2023 at 08:39, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> On 14-11-23, 11:07, Stephan Gerhold wrote:
> > The power domain scaling setup for QCS404 and MSM8909 in
> > cpufreq-com-nvmem does not work correctly at the moment because the
> > genpd core ignores all the performance state votes that are specified in
> > the CPU OPP table. This happens because nothing in the driver makes the
> > genpd core aware that the power domains are actively being consumed by
> > the CPU.
> >
> > Fix this by marking the devices as runtime active. Also mark the devices
> > to be in the "awake path" during system suspend so that performance
> > state votes necessary for the CPU are preserved during system suspend.
> >
> > While all the patches in this series are needed for full functionality,
> > the cpufreq and pmdomain patches can be merged independently. There is
> > no compile-time dependency between those two.
> >
> > Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
> > ---
> > Changes in v3:
> > - Drop patches with MSM8909 definitions that were applied already
> > - Add extra patch to fix system suspend properly by using
> > device_set_awake_path() instead of dev_pm_syscore_device()
> > - Set GENPD_FLAG_ACTIVE_WAKEUP for rpmpd so that performance state votes
> > needed by the CPU are preserved during suspend
> > - Link to v2: https://lore.kernel.org/r/20231018-msm8909-cpufreq-v2-0-0962df95f654@kernkonzept.com
>
> Applied. Thanks.
>
> I picked the pmdomain patch too, lemme know if that needs to go via
> some other tree.
Usually I should pick the pmdomain patches. Although, I thought it may
be better to keep this series together.
Assuming you are going to send these as fixes for 6.7-rc[n]? In that
case, I can just rebase my tree on a later rc if I find any problems.
Kind regards
Uffe
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling
2023-11-23 16:14 ` Ulf Hansson
@ 2023-11-27 4:22 ` Viresh Kumar
0 siblings, 0 replies; 10+ messages in thread
From: Viresh Kumar @ 2023-11-27 4:22 UTC (permalink / raw)
To: Ulf Hansson
Cc: Stephan Gerhold, Andy Gross, Bjorn Andersson, Konrad Dybcio,
Ilia Lin, Rafael J. Wysocki, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-pm, linux-arm-msm, linux-kernel, devicetree,
Stephan Gerhold, stable
On 23-11-23, 17:14, Ulf Hansson wrote:
> Assuming you are going to send these as fixes for 6.7-rc[n]?
Yes I will.
--
viresh
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-11-27 4:22 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-14 10:07 [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Stephan Gerhold
2023-11-14 10:07 ` [PATCH v3 1/3] cpufreq: qcom-nvmem: Enable virtual power domain devices Stephan Gerhold
2023-11-22 9:47 ` Ulf Hansson
2023-11-14 10:07 ` [PATCH v3 2/3] cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend Stephan Gerhold
2023-11-22 9:48 ` Ulf Hansson
2023-11-14 10:07 ` [PATCH v3 3/3] pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP Stephan Gerhold
2023-11-22 9:48 ` Ulf Hansson
2023-11-23 7:39 ` [PATCH v3 0/3] cpufreq: qcom-nvmem: Fix power domain scaling Viresh Kumar
2023-11-23 16:14 ` Ulf Hansson
2023-11-27 4:22 ` Viresh Kumar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).