diff options
-rw-r--r-- | drivers/cpuidle/cpuidle-psci-domain.c | 2 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-psci.c | 27 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-psci.h | 4 |
3 files changed, 21 insertions, 12 deletions
diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c index 5fb5228f6bf1..2041f59116ce 100644 --- a/drivers/cpuidle/cpuidle-psci-domain.c +++ b/drivers/cpuidle/cpuidle-psci-domain.c @@ -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; } diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c index b66c98a1c2e2..4fd43b8d61a9 100644 --- a/drivers/cpuidle/cpuidle-psci.c +++ b/drivers/cpuidle/cpuidle-psci.c @@ -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; diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h index ef004ec7a7c5..d29cbd796cd5 100644 --- a/drivers/cpuidle/cpuidle-psci.h +++ b/drivers/cpuidle/cpuidle-psci.h @@ -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 */ |