summaryrefslogtreecommitdiff
path: root/common/psci/psci_afflvl_suspend.c
diff options
context:
space:
mode:
authorAchin Gupta <achin.gupta@arm.com>2013-12-05 15:10:48 +0000
committerDan Handley <dan.handley@arm.com>2014-01-20 18:45:04 +0000
commita45e39738bcfb8ad49f581c92c747e159aa23892 (patch)
tree9b52dcc3be7d54ab7ed72ec4c194d6fd7fc2f0c4 /common/psci/psci_afflvl_suspend.c
parenta59caa4cbd03c394e7a5bf098ddd9db457b35aae (diff)
psci: preserve target affinity level during suspend
This patch adds support to save and restore the target affinity level specified during a cpu_suspend psci call. This ensures that we traverse only through the affinity levels that we originally intended to after resuming from suspend. Change-Id: I0900ae49a50b496da137cfec8f158da0397ec56c
Diffstat (limited to 'common/psci/psci_afflvl_suspend.c')
-rw-r--r--common/psci/psci_afflvl_suspend.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/common/psci/psci_afflvl_suspend.c b/common/psci/psci_afflvl_suspend.c
index 6fb60f4a..b2dc732f 100644
--- a/common/psci/psci_afflvl_suspend.c
+++ b/common/psci/psci_afflvl_suspend.c
@@ -44,6 +44,37 @@ typedef int (*afflvl_suspend_handler)(unsigned long,
unsigned int);
/*******************************************************************************
+ * This function sets the affinity level till which the current cpu is being
+ * powered down to during a cpu_suspend call
+ ******************************************************************************/
+void psci_set_suspend_afflvl(aff_map_node *node, int afflvl)
+{
+ /*
+ * Check that nobody else is calling this function on our behalf &
+ * this information is being set only in the cpu node
+ */
+ assert(node->mpidr == (read_mpidr() & MPIDR_AFFINITY_MASK));
+ assert(node->level == MPIDR_AFFLVL0);
+
+ /*
+ * Store the affinity level we are powering down to in our context.
+ * The cache flush in the suspend code will ensure that this info
+ * is available immediately upon resuming.
+ */
+ psci_suspend_context[node->data].suspend_level = afflvl;
+}
+
+/*******************************************************************************
+ * This function gets the affinity level till which the current cpu was powered
+ * down during a cpu_suspend call.
+ ******************************************************************************/
+int psci_get_suspend_afflvl(aff_map_node *node)
+{
+ /* Return the target affinity level */
+ return psci_suspend_context[node->data].suspend_level;
+}
+
+/*******************************************************************************
* The next three functions implement a handler for each supported affinity
* level which is called when that affinity level is about to be suspended.
******************************************************************************/
@@ -336,6 +367,9 @@ int psci_afflvl_suspend(unsigned long mpidr,
end_afflvl,
PSCI_STATE_SUSPEND);
+ /* Save the affinity level till which this cpu can be powered down */
+ psci_set_suspend_afflvl(mpidr_nodes[MPIDR_AFFLVL0], end_afflvl);
+
/* Perform generic, architecture and platform specific handling */
rc = psci_call_suspend_handlers(mpidr_nodes,
start_afflvl,