From a45e39738bcfb8ad49f581c92c747e159aa23892 Mon Sep 17 00:00:00 2001 From: Achin Gupta Date: Thu, 5 Dec 2013 15:10:48 +0000 Subject: 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 --- common/psci/psci_afflvl_suspend.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'common/psci/psci_afflvl_suspend.c') 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 @@ -43,6 +43,37 @@ typedef int (*afflvl_suspend_handler)(unsigned long, 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, -- cgit