mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-27 06:50:37 +00:00
pmdomain: core: Leave powered-on genpds on until late_initcall_sync
Powering-off a genpd that was on during boot, before all of its consumer devices have been probed, is certainly prone to problems. As a step to improve this situation, let's prevent these genpds from being powered-off until genpd_power_off_unused() gets called, which is a late_initcall_sync(). Note that, this still doesn't guarantee that all the consumer devices has been probed before we allow to power-off the genpds. Yet, this should be a step in the right direction. Suggested-by: Saravana Kannan <saravanak@google.com> Tested-by: Hiago De Franco <hiago.franco@toradex.com> # Colibri iMX8X Tested-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> # TI AM62A,Xilinx ZynqMP ZCU106 Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://lore.kernel.org/r/20250701114733.636510-22-ulf.hansson@linaro.org
This commit is contained in:
parent
f66c65686a
commit
13a4b7fb62
@ -931,11 +931,12 @@ static void genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
|
|||||||
* The domain is already in the "power off" state.
|
* The domain is already in the "power off" state.
|
||||||
* System suspend is in progress.
|
* System suspend is in progress.
|
||||||
* The domain is configured as always on.
|
* The domain is configured as always on.
|
||||||
|
* The domain was on at boot and still need to stay on.
|
||||||
* The domain has a subdomain being powered on.
|
* The domain has a subdomain being powered on.
|
||||||
*/
|
*/
|
||||||
if (!genpd_status_on(genpd) || genpd->prepared_count > 0 ||
|
if (!genpd_status_on(genpd) || genpd->prepared_count > 0 ||
|
||||||
genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd) ||
|
genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd) ||
|
||||||
atomic_read(&genpd->sd_count) > 0)
|
genpd->stay_on || atomic_read(&genpd->sd_count) > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1346,8 +1347,12 @@ static int __init genpd_power_off_unused(void)
|
|||||||
pr_info("genpd: Disabling unused power domains\n");
|
pr_info("genpd: Disabling unused power domains\n");
|
||||||
mutex_lock(&gpd_list_lock);
|
mutex_lock(&gpd_list_lock);
|
||||||
|
|
||||||
list_for_each_entry(genpd, &gpd_list, gpd_list_node)
|
list_for_each_entry(genpd, &gpd_list, gpd_list_node) {
|
||||||
|
genpd_lock(genpd);
|
||||||
|
genpd->stay_on = false;
|
||||||
|
genpd_unlock(genpd);
|
||||||
genpd_queue_power_off_work(genpd);
|
genpd_queue_power_off_work(genpd);
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&gpd_list_lock);
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
@ -2352,6 +2357,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
|||||||
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
|
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
|
||||||
atomic_set(&genpd->sd_count, 0);
|
atomic_set(&genpd->sd_count, 0);
|
||||||
genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON;
|
genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON;
|
||||||
|
genpd->stay_on = !is_off;
|
||||||
genpd->sync_state = GENPD_SYNC_STATE_OFF;
|
genpd->sync_state = GENPD_SYNC_STATE_OFF;
|
||||||
genpd->device_count = 0;
|
genpd->device_count = 0;
|
||||||
genpd->provider = NULL;
|
genpd->provider = NULL;
|
||||||
|
@ -199,6 +199,7 @@ struct generic_pm_domain {
|
|||||||
unsigned int performance_state; /* Aggregated max performance state */
|
unsigned int performance_state; /* Aggregated max performance state */
|
||||||
cpumask_var_t cpus; /* A cpumask of the attached CPUs */
|
cpumask_var_t cpus; /* A cpumask of the attached CPUs */
|
||||||
bool synced_poweroff; /* A consumer needs a synced poweroff */
|
bool synced_poweroff; /* A consumer needs a synced poweroff */
|
||||||
|
bool stay_on; /* Stay powered-on during boot. */
|
||||||
enum genpd_sync_state sync_state; /* How sync_state is managed. */
|
enum genpd_sync_state sync_state; /* How sync_state is managed. */
|
||||||
int (*power_off)(struct generic_pm_domain *domain);
|
int (*power_off)(struct generic_pm_domain *domain);
|
||||||
int (*power_on)(struct generic_pm_domain *domain);
|
int (*power_on)(struct generic_pm_domain *domain);
|
||||||
|
Loading…
Reference in New Issue
Block a user