Skip to content

Commit d0252ba

Browse files
committed
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3290e9f commit d0252ba

File tree

3 files changed

+21
-12
lines changed

3 files changed

+21
-12
lines changed

drivers/cpuidle/cpuidle-psci-domain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
4343

4444
/* OSI mode is enabled, set the corresponding domain state. */
4545
pd_state = state->data;
46-
psci_set_domain_state(*pd_state);
46+
psci_set_domain_state(pd, pd->state_idx, *pd_state);
4747

4848
return 0;
4949
}

drivers/cpuidle/cpuidle-psci.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ struct psci_cpuidle_data {
3737
};
3838

3939
struct psci_cpuidle_domain_state {
40+
struct generic_pm_domain *pd;
41+
unsigned int state_idx;
4042
u32 state;
4143
};
4244

@@ -45,14 +47,14 @@ static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state);
4547
static bool psci_cpuidle_use_syscore;
4648
static bool psci_cpuidle_use_cpuhp;
4749

48-
void psci_set_domain_state(u32 state)
50+
void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
51+
u32 state)
4952
{
50-
__this_cpu_write(psci_domain_state.state, state);
51-
}
53+
struct psci_cpuidle_domain_state *ds = this_cpu_ptr(&psci_domain_state);
5254

53-
static inline u32 psci_get_domain_state(void)
54-
{
55-
return __this_cpu_read(psci_domain_state.state);
55+
ds->pd = pd;
56+
ds->state_idx = state_idx;
57+
ds->state = state;
5658
}
5759

5860
static inline void psci_clear_domain_state(void)
@@ -67,7 +69,8 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
6769
struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
6870
u32 *states = data->psci_states;
6971
struct device *pd_dev = data->dev;
70-
u32 state;
72+
struct psci_cpuidle_domain_state *ds;
73+
u32 state = states[idx];
7174
int ret;
7275

7376
ret = cpu_pm_enter();
@@ -80,9 +83,9 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
8083
else
8184
pm_runtime_put_sync_suspend(pd_dev);
8285

83-
state = psci_get_domain_state();
84-
if (!state)
85-
state = states[idx];
86+
ds = this_cpu_ptr(&psci_domain_state);
87+
if (ds->state)
88+
state = ds->state;
8689

8790
trace_psci_domain_idle_enter(dev->cpu, state, s2idle);
8891
ret = psci_cpu_suspend_enter(state) ? -1 : idx;
@@ -95,6 +98,10 @@ static __cpuidle int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
9598

9699
cpu_pm_exit();
97100

101+
/* Correct domain-idlestate statistics if we failed to enter. */
102+
if (ret == -1 && ds->state)
103+
pm_genpd_inc_rejected(ds->pd, ds->state_idx);
104+
98105
/* Clear the domain state to start fresh when back from idle. */
99106
psci_clear_domain_state();
100107
return ret;

drivers/cpuidle/cpuidle-psci.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
#define __CPUIDLE_PSCI_H
55

66
struct device_node;
7+
struct generic_pm_domain;
78

8-
void psci_set_domain_state(u32 state);
9+
void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
10+
u32 state);
911
int psci_dt_parse_state_node(struct device_node *np, u32 *state);
1012

1113
#endif /* __CPUIDLE_PSCI_H */

0 commit comments

Comments
 (0)