mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
cpuidle: psci: Correct the domain-idlestate statistics in debugfs
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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user