Skip to content

Commit ffaa42e

Browse files
storulfrafaeljw
authored andcommitted
PM / Domains: Enable users of genpd to specify always on PM domains
The current way to implement an always on PM domain consists of returning -EBUSY from the ->power_off() callback. This is a bit different compared to using the always on genpd governor, which prevents the PM domain from being powered off via runtime suspend, but not via system suspend. The approach to return -EBUSY from the ->power_off() callback to support always on PM domains in genpd is suboptimal. That is because it requires genpd to follow the regular execution path of the power off sequence, which ends by invoking the ->power_off() callback. To enable genpd to early abort the power off sequence for always on PM domains, it needs static information about these configurations. Therefore let's add a new genpd configuration flag, GENPD_FLAG_ALWAYS_ON. Users of the new GENPD_FLAG_ALWAYS_ON flag, are by genpd required to make sure the PM domain is powered on before calling pm_genpd_init(). Moreover, users don't need to implement the ->power_off() callback, as genpd doesn't ever invoke it. Signed-off-by: Ulf Hansson <[email protected]> Reviewed-by: Viresh Kumar <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Reviewed-by: Bartlomiej Zolnierkiewicz <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 41e2c8e commit ffaa42e

File tree

2 files changed

+13
-2
lines changed

2 files changed

+13
-2
lines changed

drivers/base/power/domain.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
123123

124124
#define genpd_status_on(genpd) (genpd->status == GPD_STATE_ACTIVE)
125125
#define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE)
126+
#define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON)
126127

127128
static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
128129
struct generic_pm_domain *genpd)
@@ -300,7 +301,12 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
300301
if (!genpd_status_on(genpd) || genpd->prepared_count > 0)
301302
return 0;
302303

303-
if (atomic_read(&genpd->sd_count) > 0)
304+
/*
305+
* Abort power off for the PM domain in the following situations:
306+
* (1) The domain is configured as always on.
307+
* (2) When the domain has a subdomain being powered on.
308+
*/
309+
if (genpd_is_always_on(genpd) || atomic_read(&genpd->sd_count) > 0)
304310
return -EBUSY;
305311

306312
list_for_each_entry(pdd, &genpd->dev_list, list_node) {
@@ -752,7 +758,7 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
752758
{
753759
struct gpd_link *link;
754760

755-
if (!genpd_status_on(genpd))
761+
if (!genpd_status_on(genpd) || genpd_is_always_on(genpd))
756762
return;
757763

758764
if (genpd->suspended_count != genpd->device_count
@@ -1491,6 +1497,10 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
14911497
genpd->dev_ops.start = pm_clk_resume;
14921498
}
14931499

1500+
/* Always-on domains must be powered on at initialization. */
1501+
if (genpd_is_always_on(genpd) && !genpd_status_on(genpd))
1502+
return -EINVAL;
1503+
14941504
/* Use only one "off" state if there were no states declared */
14951505
if (genpd->state_count == 0) {
14961506
ret = genpd_set_default_power_state(genpd);

include/linux/pm_domain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
/* Defines used for the flags field in the struct generic_pm_domain */
2121
#define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */
2222
#define GENPD_FLAG_IRQ_SAFE (1U << 1) /* PM domain operates in atomic */
23+
#define GENPD_FLAG_ALWAYS_ON (1U << 2) /* PM domain is always powered on */
2324

2425
enum gpd_status {
2526
GPD_STATE_ACTIVE = 0, /* PM domain is active */

0 commit comments

Comments
 (0)