Skip to content

Commit a645ceb

Browse files
marcanjannau
authored andcommitted
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 <marcan@marcan.st>
1 parent 92c376a commit a645ceb

2 files changed

Lines changed: 58 additions & 8 deletions

File tree

drivers/pmdomain/core.c

Lines changed: 50 additions & 8 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/idr.h>
1112
#include <linux/kernel.h>
1213
#include <linux/io.h>
@@ -188,6 +189,7 @@ static const struct genpd_lock_ops genpd_raw_spin_ops = {
188189
#define genpd_is_dev_name_fw(genpd) (genpd->flags & GENPD_FLAG_DEV_NAME_FW)
189190
#define genpd_is_no_sync_state(genpd) (genpd->flags & GENPD_FLAG_NO_SYNC_STATE)
190191
#define genpd_is_no_stay_on(genpd) (genpd->flags & GENPD_FLAG_NO_STAY_ON)
192+
#define genpd_is_defer_off(genpd) (genpd->flags & GENPD_FLAG_DEFER_OFF)
191193

192194
static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
193195
const struct generic_pm_domain *genpd)
@@ -941,6 +943,27 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
941943
queue_work(pm_wq, &genpd->power_off_work);
942944
}
943945

946+
/**
947+
* genpd_must_defer - Check whether the genpd cannot be safely powered off.
948+
* @genpd: PM domain about to be powered down.
949+
* @one_dev_probing: True if we are being called from RPM callbacks on a device that
950+
* is probing, to allow poweroff if that device is the sole remaining consumer probing.
951+
*
952+
* Returns true if the @genpd has the GENPD_FLAG_DEFER_OFF flag and there
953+
* are any consumer devices which either do not exist yet (only represented
954+
* by fwlinks) or whose drivers have not probed yet.
955+
*/
956+
static bool genpd_must_defer(struct generic_pm_domain *genpd, bool one_dev_probing)
957+
{
958+
if (genpd_is_defer_off(genpd) && genpd->has_provider) {
959+
int absent = fw_devlink_count_absent_consumers(genpd->provider);
960+
961+
if (absent > (one_dev_probing ? 1 : 0))
962+
return true;
963+
}
964+
return false;
965+
}
966+
944967
/**
945968
* genpd_power_off - Remove power from a given PM domain.
946969
* @genpd: PM domain to power down.
@@ -954,7 +977,7 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
954977
* have been powered down, remove power from @genpd.
955978
*/
956979
static void genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
957-
unsigned int depth)
980+
bool one_dev_probing, unsigned int depth)
958981
{
959982
struct pm_domain_data *pdd;
960983
struct gpd_link *link;
@@ -1002,6 +1025,14 @@ static void genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
10021025
if (not_suspended > 1 || (not_suspended == 1 && !one_dev_on))
10031026
return;
10041027

1028+
/*
1029+
* Do not allow PM domain to be powered off if it is marked
1030+
* as GENPD_FLAG_DEFER_OFF and there are consumer devices
1031+
* which have not probed yet.
1032+
*/
1033+
if (genpd_must_defer(genpd, one_dev_probing))
1034+
return;
1035+
10051036
if (genpd->gov && genpd->gov->power_down_ok) {
10061037
if (!genpd->gov->power_down_ok(&genpd->domain))
10071038
return;
@@ -1027,7 +1058,7 @@ static void genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
10271058
list_for_each_entry(link, &genpd->child_links, child_node) {
10281059
genpd_sd_counter_dec(link->parent);
10291060
genpd_lock_nested(link->parent, depth + 1);
1030-
genpd_power_off(link->parent, false, depth + 1);
1061+
genpd_power_off(link->parent, false, false, depth + 1);
10311062
genpd_unlock(link->parent);
10321063
}
10331064
}
@@ -1086,7 +1117,7 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
10861117
child_node) {
10871118
genpd_sd_counter_dec(link->parent);
10881119
genpd_lock_nested(link->parent, depth + 1);
1089-
genpd_power_off(link->parent, false, depth + 1);
1120+
genpd_power_off(link->parent, false, false, depth + 1);
10901121
genpd_unlock(link->parent);
10911122
}
10921123

@@ -1153,7 +1184,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
11531184
genpd = container_of(work, struct generic_pm_domain, power_off_work);
11541185

11551186
genpd_lock(genpd);
1156-
genpd_power_off(genpd, false, 0);
1187+
genpd_power_off(genpd, false, false, 0);
11571188
genpd_unlock(genpd);
11581189
}
11591190

@@ -1218,6 +1249,7 @@ static int genpd_runtime_suspend(struct device *dev)
12181249
struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev);
12191250
struct gpd_timing_data *td = gpd_data->td;
12201251
bool runtime_pm = pm_runtime_enabled(dev);
1252+
bool probing = dev->links.status != DL_DEV_DRIVER_BOUND;
12211253
ktime_t time_start = 0;
12221254
s64 elapsed_ns;
12231255
int ret;
@@ -1272,7 +1304,7 @@ static int genpd_runtime_suspend(struct device *dev)
12721304
return 0;
12731305

12741306
genpd_lock(genpd);
1275-
genpd_power_off(genpd, true, 0);
1307+
genpd_power_off(genpd, true, probing, 0);
12761308
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
12771309
genpd_unlock(genpd);
12781310

@@ -1293,6 +1325,7 @@ static int genpd_runtime_resume(struct device *dev)
12931325
struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev);
12941326
struct gpd_timing_data *td = gpd_data->td;
12951327
bool timed = td && pm_runtime_enabled(dev);
1328+
bool probing = dev->links.status != DL_DEV_DRIVER_BOUND;
12961329
ktime_t time_start = 0;
12971330
s64 elapsed_ns;
12981331
int ret;
@@ -1350,7 +1383,7 @@ static int genpd_runtime_resume(struct device *dev)
13501383
err_poweroff:
13511384
if (!pm_runtime_is_irq_safe(dev) || genpd_is_irq_safe(genpd)) {
13521385
genpd_lock(genpd);
1353-
genpd_power_off(genpd, true, 0);
1386+
genpd_power_off(genpd, true, probing, 0);
13541387
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
13551388
genpd_unlock(genpd);
13561389
}
@@ -1418,6 +1451,9 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
14181451
|| atomic_read(&genpd->sd_count) > 0)
14191452
return;
14201453

1454+
if (genpd_must_defer(genpd, false))
1455+
return;
1456+
14211457
/* Check that the children are in their deepest (powered-off) state. */
14221458
list_for_each_entry(link, &genpd->parent_links, parent_node) {
14231459
struct generic_pm_domain *child = link->child;
@@ -2437,6 +2473,12 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
24372473
return -EINVAL;
24382474
}
24392475

2476+
/* Deferred-off power domains should be powered on at initialization. */
2477+
if (genpd_is_defer_off(genpd) && !genpd_status_on(genpd)) {
2478+
pr_warn("deferred-off PM domain %s is not on at init\n", genpd->name);
2479+
genpd->flags &= ~GENPD_FLAG_DEFER_OFF;
2480+
}
2481+
24402482
/* Multiple states but no governor doesn't make sense. */
24412483
if (!gov && genpd->state_count > 1)
24422484
pr_warn("%s: no governor for states\n", genpd->name);
@@ -3503,7 +3545,7 @@ void of_genpd_sync_state(struct device_node *np)
35033545
if (genpd->provider == of_fwnode_handle(np)) {
35043546
genpd_lock(genpd);
35053547
genpd->stay_on = false;
3506-
genpd_power_off(genpd, false, 0);
3548+
genpd_power_off(genpd, false, false, 0);
35073549
genpd_unlock(genpd);
35083550
}
35093551
}
@@ -3531,7 +3573,7 @@ static void genpd_provider_sync_state(struct device *dev)
35313573
case GENPD_SYNC_STATE_SIMPLE:
35323574
genpd_lock(genpd);
35333575
genpd->stay_on = false;
3534-
genpd_power_off(genpd, false, 0);
3576+
genpd_power_off(genpd, false, false, 0);
35353577
genpd_unlock(genpd);
35363578
break;
35373579

include/linux/pm_domain.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ struct dev_pm_domain_list {
121121
* powered-off until the ->sync_state() callback is
122122
* invoked. This flag informs genpd to allow a
123123
* power-off without waiting for ->sync_state().
124+
* GENPD_FLAG_DEFER_OFF: Defer powerdown if there are any consumer
125+
* device fwlinks indicating that some consumer
126+
* devices have not yet probed. This is useful
127+
* for power domains which are active at boot and
128+
* must not be shut down until all consumers
129+
* complete their probe sequence.
130+
124131
*/
125132
#define GENPD_FLAG_PM_CLK (1U << 0)
126133
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
@@ -133,6 +140,7 @@ struct dev_pm_domain_list {
133140
#define GENPD_FLAG_DEV_NAME_FW (1U << 8)
134141
#define GENPD_FLAG_NO_SYNC_STATE (1U << 9)
135142
#define GENPD_FLAG_NO_STAY_ON (1U << 10)
143+
#define GENPD_FLAG_DEFER_OFF (1U << 11)
136144

137145
enum gpd_status {
138146
GENPD_STATE_ON = 0, /* PM domain is on */

0 commit comments

Comments
 (0)