aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2020-07-07 14:58:04 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2020-07-29 18:38:30 +0200
commit81f94ddfeceddb3b8ffa6cfe5ddd3b896711d9ad (patch)
tree304c9143d9580d5bf54c3942eb7a3e28c9124096 /drivers/cpuidle
parentee7c34caac3892af08f9c4c91b834d2cb2871eb0 (diff)
downloadlinux-81f94ddfeceddb3b8ffa6cfe5ddd3b896711d9ad.tar.gz
cpuidle: psci: Prevent domain idlestates until consumers are ready
Depending on the SoC/platform, additional devices may be part of the PSCI PM domain topology. This is the case with 'qcom,rpmh-rsc' device, for example, even if this is not yet visible in the corresponding DTS-files. Without going into too much details, a device like the 'qcom,rpmh-rsc' may have HW constraints that needs to be obeyed to, before a domain idlestate can be picked. Therefore, let's implement the ->sync_state() callback to receive a notification when all consumers of the PSCI PM domain providers have been attached/probed to it. In this way, we can make sure all constraints from all relevant devices, are taken into account before allowing a domain idlestate to be picked. Acked-by: Saravana Kannan <saravanak@google.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/cpuidle-psci-domain.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index bf527d2bb4b62..b6e9649ab0da3 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -27,6 +27,7 @@ struct psci_pd_provider {
};
static LIST_HEAD(psci_pd_providers);
+static bool psci_pd_allow_domain_state;
static int psci_pd_power_off(struct generic_pm_domain *pd)
{
@@ -36,6 +37,9 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
if (!state->data)
return 0;
+ if (!psci_pd_allow_domain_state)
+ return -EBUSY;
+
/* OSI mode is enabled, set the corresponding domain state. */
pd_state = state->data;
psci_set_domain_state(*pd_state);
@@ -222,6 +226,15 @@ static void psci_pd_remove_topology(struct device_node *np)
psci_pd_init_topology(np, false);
}
+static void psci_cpuidle_domain_sync_state(struct device *dev)
+{
+ /*
+ * All devices have now been attached/probed to the PM domain topology,
+ * hence it's fine to allow domain states to be picked.
+ */
+ psci_pd_allow_domain_state = true;
+}
+
static const struct of_device_id psci_of_match[] = {
{ .compatible = "arm,psci-1.0" },
{}
@@ -289,6 +302,7 @@ static struct platform_driver psci_cpuidle_domain_driver = {
.driver = {
.name = "psci-cpuidle-domain",
.of_match_table = psci_of_match,
+ .sync_state = psci_cpuidle_domain_sync_state,
},
};