Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 0e789b491ba0 ("pmdomain: core: Leave powered-on genpds on until sync_state")
Fixes: 13a4b7fb6260 ("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>

+21 -6
+14 -6
drivers/pmdomain/core.c
··· 187 187 #define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW) 188 188 #define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW) 189 189 #define genpd_is_no_sync_state(genpd) (genpd->flags & GENPD_FLAG_NO_SYNC_STATE) 190 + #define genpd_is_no_stay_on(genpd) (genpd->flags & GENPD_FLAG_NO_STAY_ON) 190 191 191 192 static inline bool irq_safe_dev_in_sleep_domain(struct device *dev, 192 193 const struct generic_pm_domain *genpd) ··· 1358 1357 return ret; 1359 1358 } 1360 1359 1361 - #ifndef CONFIG_PM_GENERIC_DOMAINS_OF 1362 1360 static bool pd_ignore_unused; 1363 1361 static int __init pd_ignore_unused_setup(char *__unused) 1364 1362 { ··· 1382 1382 mutex_lock(&gpd_list_lock); 1383 1383 1384 1384 list_for_each_entry(genpd, &gpd_list, gpd_list_node) { 1385 - genpd_lock(genpd); 1386 - genpd->stay_on = false; 1387 - genpd_unlock(genpd); 1388 1385 genpd_queue_power_off_work(genpd); 1389 1386 } 1390 1387 ··· 1390 1393 return 0; 1391 1394 } 1392 1395 late_initcall_sync(genpd_power_off_unused); 1393 - #endif 1394 1396 1395 1397 #ifdef CONFIG_PM_SLEEP 1396 1398 ··· 2363 2367 } 2364 2368 } 2365 2369 2370 + #ifdef CONFIG_PM_GENERIC_DOMAINS_OF 2371 + static void genpd_set_stay_on(struct generic_pm_domain *genpd, bool is_off) 2372 + { 2373 + genpd->stay_on = !genpd_is_no_stay_on(genpd) && !is_off; 2374 + } 2375 + #else 2376 + static void genpd_set_stay_on(struct generic_pm_domain *genpd, bool is_off) 2377 + { 2378 + genpd->stay_on = false; 2379 + } 2380 + #endif 2381 + 2366 2382 /** 2367 2383 * pm_genpd_init - Initialize a generic I/O PM domain object. 2368 2384 * @genpd: PM domain object to initialize. ··· 2400 2392 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); 2401 2393 atomic_set(&genpd->sd_count, 0); 2402 2394 genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON; 2403 - genpd->stay_on = !is_off; 2395 + genpd_set_stay_on(genpd, is_off); 2404 2396 genpd->sync_state = GENPD_SYNC_STATE_OFF; 2405 2397 genpd->device_count = 0; 2406 2398 genpd->provider = NULL;
+7
include/linux/pm_domain.h
··· 115 115 * genpd provider specific way, likely through a 116 116 * parent device node. This flag makes genpd to 117 117 * skip its internal support for this. 118 + * 119 + * GENPD_FLAG_NO_STAY_ON: For genpd OF providers a powered-on PM domain at 120 + * initialization is prevented from being 121 + * powered-off until the ->sync_state() callback is 122 + * invoked. This flag informs genpd to allow a 123 + * power-off without waiting for ->sync_state(). 118 124 */ 119 125 #define GENPD_FLAG_PM_CLK (1U << 0) 120 126 #define GENPD_FLAG_IRQ_SAFE (1U << 1) ··· 132 126 #define GENPD_FLAG_OPP_TABLE_FW (1U << 7) 133 127 #define GENPD_FLAG_DEV_NAME_FW (1U << 8) 134 128 #define GENPD_FLAG_NO_SYNC_STATE (1U << 9) 129 + #define GENPD_FLAG_NO_STAY_ON (1U << 10) 135 130 136 131 enum gpd_status { 137 132 GENPD_STATE_ON = 0, /* PM domain is on */