]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
cpuidle: psci: Correct the domain-idlestate statistics in debugfs
authorUlf Hansson <ulf.hansson@linaro.org>
Fri, 14 Mar 2025 10:00:57 +0000 (11:00 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Wed, 23 Apr 2025 08:08:34 +0000 (10:08 +0200)
When trying to enter a domain-idlestate, we may occasionally fail to enter
the state, which is informed to us by psci_cpu_suspend_enter() returning an
error-code. In these cases, our corresponding genpd->power_off() callback
has already returned zero to indicate success, leading to getting
in-correct domain-idlestate statistics in debugfs for the genpd in
question.

Let's fix this by making use of the new pm_genpd_inc_rejected() helper, as
it allows us to correct the domain-idlestate statistics for this type of
scenario.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20250314100103.1294715-4-ulf.hansson@linaro.org
drivers/cpuidle/cpuidle-psci-domain.c
drivers/cpuidle/cpuidle-psci.c
drivers/cpuidle/cpuidle-psci.h

index 5fb5228f6bf1abe08111ea1487b67543cebe5bd0..2041f59116ce0c082713875b5e78354ebcc2421c 100644 (file)
@@ -43,7 +43,7 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
 
        /* OSI mode is enabled, set the corresponding domain state. */
        pd_state = state->data;
-       psci_set_domain_state(*pd_state);
+       psci_set_domain_state(pd, pd->state_idx, *pd_state);
 
        return 0;
 }
index b66c98a1c2e2663c951eb55c040ecb0117eebda2..4fd43b8d61a949dec473881e5f9a696141a925aa 100644 (file)
@@ -37,6 +37,8 @@ struct psci_cpuidle_data {
 };
 
 struct psci_cpuidle_domain_state {
+       struct generic_pm_domain *pd;
+       unsigned int state_idx;
        u32 state;
 };
 
@@ -45,14 +47,14 @@ static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state);
 static bool psci_cpuidle_use_syscore;
 static bool psci_cpuidle_use_cpuhp;
 
-void psci_set_domain_state(u32 state)
+void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
+                          u32 state)
 {
-       __this_cpu_write(psci_domain_state.state, state);
-}
+       struct psci_cpuidle_domain_state *ds = this_cpu_ptr(&psci_domain_state);
 
-static inline u32 psci_get_domain_state(void)
-{
-       return __this_cpu_read(psci_domain_state.state);
+       ds->pd = pd;
+       ds->state_idx = state_idx;
+       ds->state = state;
 }
 
 static inline void psci_clear_domain_state(void)
@@ -67,7 +69,8 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
        struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
        u32 *states = data->psci_states;
        struct device *pd_dev = data->dev;
-       u32 state;
+       struct psci_cpuidle_domain_state *ds;
+       u32 state = states[idx];
        int ret;
 
        ret = cpu_pm_enter();
@@ -80,9 +83,9 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
        else
                pm_runtime_put_sync_suspend(pd_dev);
 
-       state = psci_get_domain_state();
-       if (!state)
-               state = states[idx];
+       ds = this_cpu_ptr(&psci_domain_state);
+       if (ds->state)
+               state = ds->state;
 
        trace_psci_domain_idle_enter(dev->cpu, state, s2idle);
        ret = psci_cpu_suspend_enter(state) ? -1 : idx;
@@ -95,6 +98,10 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
 
        cpu_pm_exit();
 
+       /* Correct domain-idlestate statistics if we failed to enter. */
+       if (ret == -1 && ds->state)
+               pm_genpd_inc_rejected(ds->pd, ds->state_idx);
+
        /* Clear the domain state to start fresh when back from idle. */
        psci_clear_domain_state();
        return ret;
index ef004ec7a7c5c2109b058b32bebf024da818005b..d29cbd796cd560f4fc0bd6c869cf9bcbdc03f97f 100644 (file)
@@ -4,8 +4,10 @@
 #define __CPUIDLE_PSCI_H
 
 struct device_node;
+struct generic_pm_domain;
 
-void psci_set_domain_state(u32 state);
+void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
+                          u32 state);
 int psci_dt_parse_state_node(struct device_node *np, u32 *state);
 
 #endif /* __CPUIDLE_PSCI_H */