Skip to content

Commit 4d23a5e

Browse files
storulfrafaeljw
authored andcommitted
PM / Domains: Allow runtime PM during system PM phases
In cases when a PM domain isn't powered off when genpd's ->prepare() callback is invoked, genpd runtime resumes and disables runtime PM for the device. This behaviour was needed when genpd managed intermediate states during the power off sequence, as to maintain proper low power states of devices during system PM suspend/resume. Commit ba2bbfb (PM / Domains: Remove intermediate states from the power off sequence), enables genpd to improve its behaviour in that respect. The PM core disables runtime PM at __device_suspend_late() before it calls a system PM "late" callback for a device. When resuming a device, after a corresponding "early" callback has been invoked, the PM core re-enables runtime PM. By changing genpd to allow runtime PM according to the same system PM phases as the PM core, devices can be runtime resumed by their corresponding subsystem/driver when really needed. In this way, genpd no longer need to runtime resume the device from its ->prepare() callback. In most cases that avoids unnecessary and energy- wasting operations of runtime resuming devices that have nothing to do, only to runtime suspend them shortly after. Although, because of changing this behaviour in genpd and due to that genpd powers on the PM domain unconditionally in the system PM resume "noirq" phase, it could potentially cause a PM domain to stay powered on even if it's unused after the system has resumed. To avoid this, schedule a power off work when genpd's system PM ->complete() callback has been invoked for the last device in the PM domain. Signed-off-by: Ulf Hansson <[email protected]> Reviewed-by: Kevin Hilman <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 9f5b527 commit 4d23a5e

File tree

1 file changed

+8
-26
lines changed

1 file changed

+8
-26
lines changed

drivers/base/power/domain.c

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -739,29 +739,13 @@ static int pm_genpd_prepare(struct device *dev)
739739

740740
mutex_unlock(&genpd->lock);
741741

742-
/*
743-
* Even if the PM domain is powered off at this point, we can't expect
744-
* it to remain in that state during the entire system PM suspend
745-
* phase. Any subsystem/driver for a device in the PM domain, may still
746-
* need to serve a request which may require the device to be runtime
747-
* resumed and its PM domain to be powered.
748-
*
749-
* As we are disabling runtime PM at this point, we are preventing the
750-
* subsystem/driver to decide themselves. For that reason, we need to
751-
* make sure the device is operational as it may be required in some
752-
* cases.
753-
*/
754-
pm_runtime_resume(dev);
755-
__pm_runtime_disable(dev, false);
756-
757742
ret = pm_generic_prepare(dev);
758743
if (ret) {
759744
mutex_lock(&genpd->lock);
760745

761746
genpd->prepared_count--;
762747

763748
mutex_unlock(&genpd->lock);
764-
pm_runtime_enable(dev);
765749
}
766750

767751
return ret;
@@ -787,8 +771,6 @@ static int pm_genpd_suspend_noirq(struct device *dev)
787771
if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
788772
return 0;
789773

790-
genpd_stop_dev(genpd, dev);
791-
792774
/*
793775
* Since all of the "noirq" callbacks are executed sequentially, it is
794776
* guaranteed that this function will never run twice in parallel for
@@ -827,7 +809,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
827809
pm_genpd_sync_poweron(genpd, true);
828810
genpd->suspended_count--;
829811

830-
return genpd_start_dev(genpd, dev);
812+
return 0;
831813
}
832814

833815
/**
@@ -849,7 +831,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
849831
if (IS_ERR(genpd))
850832
return -EINVAL;
851833

852-
return genpd_stop_dev(genpd, dev);
834+
return 0;
853835
}
854836

855837
/**
@@ -869,7 +851,7 @@ static int pm_genpd_thaw_noirq(struct device *dev)
869851
if (IS_ERR(genpd))
870852
return -EINVAL;
871853

872-
return genpd_start_dev(genpd, dev);
854+
return 0;
873855
}
874856

875857
/**
@@ -907,7 +889,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
907889

908890
pm_genpd_sync_poweron(genpd, true);
909891

910-
return genpd_start_dev(genpd, dev);
892+
return 0;
911893
}
912894

913895
/**
@@ -929,15 +911,15 @@ static void pm_genpd_complete(struct device *dev)
929911
if (IS_ERR(genpd))
930912
return;
931913

914+
pm_generic_complete(dev);
915+
932916
mutex_lock(&genpd->lock);
933917

934918
genpd->prepared_count--;
919+
if (!genpd->prepared_count)
920+
genpd_queue_power_off_work(genpd);
935921

936922
mutex_unlock(&genpd->lock);
937-
938-
pm_generic_complete(dev);
939-
pm_runtime_set_active(dev);
940-
pm_runtime_enable(dev);
941923
}
942924

943925
/**

0 commit comments

Comments
 (0)