diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c index b9e4ad7d43a33..fab9de648b17f 100644 --- a/drivers/cpuidle/cpuidle-psci-domain.c +++ b/drivers/cpuidle/cpuidle-psci-domain.c @@ -78,7 +78,19 @@ static int psci_pd_init(struct device_node *np, bool use_osi) /* Use governor for CPU PM domains if it has some states to manage. */ pd_gov = pd->states ? &pm_domain_cpu_gov : NULL; - ret = pm_genpd_init(pd, pd_gov, false); + /* + * Start the domain in the OFF state when OSI is in use, so that + * genpd's own status tracking (and its power-on notifier chain) + * reflects reality from the outset instead of reporting ON before + * any CPU in the domain has actually requested it. This is safe: + * dt_idle_attach_cpu() runtime-resumes the domain for every CPU + * that is already online by the time this driver probes, and the + * PSCI cpuidle cpuhp callbacks power it on/off for CPUs that come + * online/offline afterwards. When OSI isn't in use, GENPD_FLAG_ALWAYS_ON + * above keeps the domain powered regardless of is_off, so this has + * no effect there. + */ + ret = pm_genpd_init(pd, pd_gov, use_osi); if (ret) goto free_pd_prov; diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 842c4169e2906..5d96d9eabc1f3 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -2409,6 +2409,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd, INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); atomic_set(&genpd->sd_count, 0); genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON; + if (is_off && genpd->state_count) + genpd->state_idx = genpd->state_count - 1; genpd_set_stay_on(genpd, is_off); genpd->sync_state = GENPD_SYNC_STATE_OFF; genpd->device_count = 0;