Skip to content

Commit 2930844

Browse files
committed
PM: domains: Add a flag to defer power-off until all consumers probe
In some cases, power domains are active on boot and must remain turned on until all their dependent drivers probe. Examples are: - Boot-time framebuffers - Devices that run coprocessors which are handed off already running - Parent power domains with children that are also on at boot The genpd core currently powers off the genpd as soon as a single consumer device probes and goes into runtime suspend or when general probing is complete, whichever comes first. That breaks any devices which haven't probed yet. To fix this, add a GENPD_FLAG_DEFER_OFF which requests that the genpd core refuse to power down a domain if there are any consumer devices that either haven't probed yet, or whose device nodes do not exist yet (but fwlinks do). Genpd providers can set this if they expect to be critical for devices (e.g. if they are powered on at boot). It is possible for a device to be runtime suspended from its probe callback. If this is the last device to probe, this is allowable. To account for this, check whether the device whose callbacks are being invoked in the probing state, and in that case, allow 1 instead of 0 pending devices. Signed-off-by: Hector Martin <[email protected]>
1 parent 98decb0 commit 2930844

2 files changed

Lines changed: 56 additions & 6 deletions

File tree

drivers/base/power/domain.c

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define pr_fmt(fmt) "PM: " fmt
88

99
#include <linux/delay.h>
10+
#include <linux/fwnode.h>
1011
#include <linux/kernel.h>
1112
#include <linux/io.h>
1213
#include <linux/platform_device.h>
@@ -130,6 +131,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
130131
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
131132
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
132133
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
134+
#define genpd_is_defer_off(genpd) (genpd->flags & GENPD_FLAG_DEFER_OFF)
133135

134136
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
135137
const struct generic_pm_domain *genpd)
@@ -654,6 +656,27 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
654656
queue_work(pm_wq, &genpd->power_off_work);
655657
}
656658

659+
/**
660+
* genpd_must_defer - Check whether the genpd cannot be safely powered off.
661+
* @genpd: PM domain about to be powered down.
662+
* @one_dev_probing: True if we are being called from RPM callbacks on a device that
663+
* is probing, to allow poweroff if that device is the sole remaining consumer probing.
664+
*
665+
* Returns true if the @genpd has the GENPD_FLAG_DEFER_OFF flag and there
666+
* are any consumer devices which either do not exist yet (only represented
667+
* by fwlinks) or whose drivers have not probed yet.
668+
*/
669+
static bool genpd_must_defer(struct generic_pm_domain *genpd, bool one_dev_probing)
670+
{
671+
if (genpd_is_defer_off(genpd) && genpd->has_provider) {
672+
int absent = fw_devlink_count_absent_consumers(genpd->provider);
673+
674+
if (absent > (one_dev_probing ? 1 : 0))
675+
return true;
676+
}
677+
return false;
678+
}
679+
657680
/**
658681
* genpd_power_off - Remove power from a given PM domain.
659682
* @genpd: PM domain to power down.
@@ -667,7 +690,7 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
667690
* have been powered down, remove power from @genpd.
668691
*/
669692
static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
670-
unsigned int depth)
693+
bool one_dev_probing, unsigned int depth)
671694
{
672695
struct pm_domain_data *pdd;
673696
struct gpd_link *link;
@@ -717,6 +740,14 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
717740
if (not_suspended > 1 || (not_suspended == 1 && !one_dev_on))
718741
return -EBUSY;
719742

743+
/*
744+
* Do not allow PM domain to be powered off if it is marked
745+
* as GENPD_FLAG_DEFER_OFF and there are consumer devices
746+
* which have not probed yet.
747+
*/
748+
if (genpd_must_defer(genpd, one_dev_probing))
749+
return -EBUSY;
750+
720751
if (genpd->gov && genpd->gov->power_down_ok) {
721752
if (!genpd->gov->power_down_ok(&genpd->domain))
722753
return -EAGAIN;
@@ -743,7 +774,7 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
743774
list_for_each_entry(link, &genpd->child_links, child_node) {
744775
genpd_sd_counter_dec(link->parent);
745776
genpd_lock_nested(link->parent, depth + 1);
746-
genpd_power_off(link->parent, false, depth + 1);
777+
genpd_power_off(link->parent, false, false, depth + 1);
747778
genpd_unlock(link->parent);
748779
}
749780

@@ -801,7 +832,7 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
801832
child_node) {
802833
genpd_sd_counter_dec(link->parent);
803834
genpd_lock_nested(link->parent, depth + 1);
804-
genpd_power_off(link->parent, false, depth + 1);
835+
genpd_power_off(link->parent, false, false, depth + 1);
805836
genpd_unlock(link->parent);
806837
}
807838

@@ -868,7 +899,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
868899
genpd = container_of(work, struct generic_pm_domain, power_off_work);
869900

870901
genpd_lock(genpd);
871-
genpd_power_off(genpd, false, 0);
902+
genpd_power_off(genpd, false, false, 0);
872903
genpd_unlock(genpd);
873904
}
874905

@@ -933,6 +964,7 @@ static int genpd_runtime_suspend(struct device *dev)
933964
struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev);
934965
struct gpd_timing_data *td = gpd_data->td;
935966
bool runtime_pm = pm_runtime_enabled(dev);
967+
bool probing = dev->links.status != DL_DEV_DRIVER_BOUND;
936968
ktime_t time_start = 0;
937969
s64 elapsed_ns;
938970
int ret;
@@ -987,7 +1019,7 @@ static int genpd_runtime_suspend(struct device *dev)
9871019
return 0;
9881020

9891021
genpd_lock(genpd);
990-
genpd_power_off(genpd, true, 0);
1022+
genpd_power_off(genpd, true, probing, 0);
9911023
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
9921024
genpd_unlock(genpd);
9931025

@@ -1008,6 +1040,7 @@ static int genpd_runtime_resume(struct device *dev)
10081040
struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev);
10091041
struct gpd_timing_data *td = gpd_data->td;
10101042
bool timed = td && pm_runtime_enabled(dev);
1043+
bool probing = dev->links.status != DL_DEV_DRIVER_BOUND;
10111044
ktime_t time_start = 0;
10121045
s64 elapsed_ns;
10131046
int ret;
@@ -1065,7 +1098,7 @@ static int genpd_runtime_resume(struct device *dev)
10651098
err_poweroff:
10661099
if (!pm_runtime_is_irq_safe(dev) || genpd_is_irq_safe(genpd)) {
10671100
genpd_lock(genpd);
1068-
genpd_power_off(genpd, true, 0);
1101+
genpd_power_off(genpd, true, probing, 0);
10691102
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
10701103
genpd_unlock(genpd);
10711104
}
@@ -1131,6 +1164,9 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
11311164
|| atomic_read(&genpd->sd_count) > 0)
11321165
return;
11331166

1167+
if (genpd_must_defer(genpd, false))
1168+
return;
1169+
11341170
/* Check that the children are in their deepest (powered-off) state. */
11351171
list_for_each_entry(link, &genpd->parent_links, parent_node) {
11361172
struct generic_pm_domain *child = link->child;
@@ -2096,6 +2132,12 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
20962132
return -EINVAL;
20972133
}
20982134

2135+
/* Deferred-off power domains should be powered on at initialization. */
2136+
if (genpd_is_defer_off(genpd) && !genpd_status_on(genpd)) {
2137+
pr_warn("deferred-off PM domain %s is not on at init\n", genpd->name);
2138+
genpd->flags &= ~GENPD_FLAG_DEFER_OFF;
2139+
}
2140+
20992141
/* Multiple states but no governor doesn't make sense. */
21002142
if (!gov && genpd->state_count > 1)
21012143
pr_warn("%s: no governor for states\n", genpd->name);

include/linux/pm_domain.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@
6161
* GENPD_FLAG_MIN_RESIDENCY: Enable the genpd governor to consider its
6262
* components' next wakeup when determining the
6363
* optimal idle state.
64+
*
65+
* GENPD_FLAG_DEFER_OFF: Defer powerdown if there are any consumer
66+
* device fwlinks indicating that some consumer
67+
* devices have not yet probed. This is useful
68+
* for power domains which are active at boot and
69+
* must not be shut down until all consumers
70+
* complete their probe sequence.
6471
*/
6572
#define GENPD_FLAG_PM_CLK (1U << 0)
6673
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
@@ -69,6 +76,7 @@
6976
#define GENPD_FLAG_CPU_DOMAIN (1U << 4)
7077
#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
7178
#define GENPD_FLAG_MIN_RESIDENCY (1U << 6)
79+
#define GENPD_FLAG_DEFER_OFF (1U << 7)
7280

7381
enum gpd_status {
7482
GENPD_STATE_ON = 0, /* PM domain is on */

0 commit comments

Comments
 (0)