Skip to content

Commit ffe1285

Browse files
storulfrafaeljw
authored andcommitted
PM / Domains: Allow runtime PM callbacks to be re-used during system PM
A runtime PM centric subsystem/driver may typically use the runtime PM helpers, pm_runtime_force_suspend|resume() in the system PM path. This means the genpd's runtime PM callbacks might be invoked even when runtime PM has been disabled for the device. To properly cope with these and similar scenarios when these helper functions are used, change genpd to skip validating and measuring the device PM QOS latency. This is needed because otherwise genpd may prevent the device to be put into low power state. If this occurs during system PM, it causes the sequence to be aborted as a device's system PM callback returns -EBUSY. Fixes: ba2bbfb (PM / Domains: Remove intermediate states from the power off sequence) Reported-by: Cao Minh Hiep <[email protected]> Reported-by: Harunaga <[email protected]> Signed-off-by: Ulf Hansson <[email protected]> Cc: 4.3+ <[email protected]> # 4.3+ Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 265e2cf commit ffe1285

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

drivers/base/power/domain.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ static int pm_genpd_runtime_suspend(struct device *dev)
390390
struct generic_pm_domain *genpd;
391391
bool (*stop_ok)(struct device *__dev);
392392
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
393+
bool runtime_pm = pm_runtime_enabled(dev);
393394
ktime_t time_start;
394395
s64 elapsed_ns;
395396
int ret;
@@ -400,12 +401,19 @@ static int pm_genpd_runtime_suspend(struct device *dev)
400401
if (IS_ERR(genpd))
401402
return -EINVAL;
402403

404+
/*
405+
* A runtime PM centric subsystem/driver may re-use the runtime PM
406+
* callbacks for other purposes than runtime PM. In those scenarios
407+
* runtime PM is disabled. Under these circumstances, we shall skip
408+
* validating/measuring the PM QoS latency.
409+
*/
403410
stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
404-
if (stop_ok && !stop_ok(dev))
411+
if (runtime_pm && stop_ok && !stop_ok(dev))
405412
return -EBUSY;
406413

407414
/* Measure suspend latency. */
408-
time_start = ktime_get();
415+
if (runtime_pm)
416+
time_start = ktime_get();
409417

410418
ret = genpd_save_dev(genpd, dev);
411419
if (ret)
@@ -418,13 +426,15 @@ static int pm_genpd_runtime_suspend(struct device *dev)
418426
}
419427

420428
/* Update suspend latency value if the measured time exceeds it. */
421-
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
422-
if (elapsed_ns > td->suspend_latency_ns) {
423-
td->suspend_latency_ns = elapsed_ns;
424-
dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
425-
elapsed_ns);
426-
genpd->max_off_time_changed = true;
427-
td->constraint_changed = true;
429+
if (runtime_pm) {
430+
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
431+
if (elapsed_ns > td->suspend_latency_ns) {
432+
td->suspend_latency_ns = elapsed_ns;
433+
dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
434+
elapsed_ns);
435+
genpd->max_off_time_changed = true;
436+
td->constraint_changed = true;
437+
}
428438
}
429439

430440
/*
@@ -453,6 +463,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
453463
{
454464
struct generic_pm_domain *genpd;
455465
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
466+
bool runtime_pm = pm_runtime_enabled(dev);
456467
ktime_t time_start;
457468
s64 elapsed_ns;
458469
int ret;
@@ -479,14 +490,14 @@ static int pm_genpd_runtime_resume(struct device *dev)
479490

480491
out:
481492
/* Measure resume latency. */
482-
if (timed)
493+
if (timed && runtime_pm)
483494
time_start = ktime_get();
484495

485496
genpd_start_dev(genpd, dev);
486497
genpd_restore_dev(genpd, dev);
487498

488499
/* Update resume latency value if the measured time exceeds it. */
489-
if (timed) {
500+
if (timed && runtime_pm) {
490501
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
491502
if (elapsed_ns > td->resume_latency_ns) {
492503
td->resume_latency_ns = elapsed_ns;

0 commit comments

Comments
 (0)