pmdomain: core: Restore behaviour for disabling unused PM domains
Recent changes to genpd prevents those PM domains being powered-on during initialization from being powered-off during the boot sequence. Based upon whether CONFIG_PM_CONFIG_PM_GENERIC_DOMAINS_OF is set of not, genpd relies on the sync_state mechanism or the genpd_power_off_unused() (which is a late_initcall_sync), to understand when it's okay to allow these PM domains to be powered-off. This new behaviour in genpd has lead to problems on different platforms. Let's therefore restore the behavior of genpd_power_off_unused(). Moreover, let's introduce GENPD_FLAG_NO_STAY_ON, to allow genpd OF providers to opt-out from the new behaviour. Link: https://lore.kernel.org/all/20250701114733.636510-1-ulf.hansson@linaro.org/ Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Link: https://lore.kernel.org/all/20250902-rk3576-lockup-regression-v1-1-c4a0c9daeb00@collabora.com/ Reported-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com> Fixes:0e789b491b("pmdomain: core: Leave powered-on genpds on until sync_state") Fixes:13a4b7fb62("pmdomain: core: Leave powered-on genpds on until late_initcall_sync") Tested-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
@@ -187,6 +187,7 @@ static const struct genpd_lock_ops genpd_raw_spin_ops = {
|
||||
#define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)
|
||||
#define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW)
|
||||
#define genpd_is_no_sync_state(genpd) (genpd->flags & GENPD_FLAG_NO_SYNC_STATE)
|
||||
#define genpd_is_no_stay_on(genpd) (genpd->flags & GENPD_FLAG_NO_STAY_ON)
|
||||
|
||||
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
|
||||
const struct generic_pm_domain *genpd)
|
||||
@@ -1357,7 +1358,6 @@ err_poweroff:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
static bool pd_ignore_unused;
|
||||
static int __init pd_ignore_unused_setup(char *__unused)
|
||||
{
|
||||
@@ -1382,9 +1382,6 @@ static int __init genpd_power_off_unused(void)
|
||||
mutex_lock(&gpd_list_lock);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1393,7 +1390,6 @@ static int __init genpd_power_off_unused(void)
|
||||
return 0;
|
||||
}
|
||||
late_initcall_sync(genpd_power_off_unused);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
@@ -2367,6 +2363,18 @@ static void genpd_lock_init(struct generic_pm_domain *genpd)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
static void genpd_set_stay_on(struct generic_pm_domain *genpd, bool is_off)
|
||||
{
|
||||
genpd->stay_on = !genpd_is_no_stay_on(genpd) && !is_off;
|
||||
}
|
||||
#else
|
||||
static void genpd_set_stay_on(struct generic_pm_domain *genpd, bool is_off)
|
||||
{
|
||||
genpd->stay_on = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* pm_genpd_init - Initialize a generic I/O PM domain object.
|
||||
* @genpd: PM domain object to initialize.
|
||||
@@ -2392,7 +2400,7 @@ 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;
|
||||
genpd->stay_on = !is_off;
|
||||
genpd_set_stay_on(genpd, is_off);
|
||||
genpd->sync_state = GENPD_SYNC_STATE_OFF;
|
||||
genpd->device_count = 0;
|
||||
genpd->provider = NULL;
|
||||
|
||||
@@ -115,6 +115,12 @@ struct dev_pm_domain_list {
|
||||
* genpd provider specific way, likely through a
|
||||
* parent device node. This flag makes genpd to
|
||||
* skip its internal support for this.
|
||||
*
|
||||
* GENPD_FLAG_NO_STAY_ON: For genpd OF providers a powered-on PM domain at
|
||||
* initialization is prevented from being
|
||||
* powered-off until the ->sync_state() callback is
|
||||
* invoked. This flag informs genpd to allow a
|
||||
* power-off without waiting for ->sync_state().
|
||||
*/
|
||||
#define GENPD_FLAG_PM_CLK (1U << 0)
|
||||
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
|
||||
@@ -126,6 +132,7 @@ struct dev_pm_domain_list {
|
||||
#define GENPD_FLAG_OPP_TABLE_FW (1U << 7)
|
||||
#define GENPD_FLAG_DEV_NAME_FW (1U << 8)
|
||||
#define GENPD_FLAG_NO_SYNC_STATE (1U << 9)
|
||||
#define GENPD_FLAG_NO_STAY_ON (1U << 10)
|
||||
|
||||
enum gpd_status {
|
||||
GENPD_STATE_ON = 0, /* PM domain is on */
|
||||
|
||||
Reference in New Issue
Block a user