aboutsummaryrefslogtreecommitdiff
path: root/common/psci/psci_setup.c
diff options
context:
space:
mode:
authorAchin Gupta <achin.gupta@arm.com>2013-12-02 17:33:04 +0000
committerDan Handley <dan.handley@arm.com>2013-12-05 12:28:50 +0000
commit0959db5c99b189a1b04515050ef64348de6a2503 (patch)
tree2b5a151d7b9810cab6de7ad26e96321fed431a9d /common/psci/psci_setup.c
parent3140a9e5c7d524eb1ea1648ae7c26e61fe7d740c (diff)
downloadarm-trusted-firmware-0959db5c99b189a1b04515050ef64348de6a2503.tar.gz
psci: rectify and homogenise generic code
This patch performs a major rework of the psci generic implementation to achieve the following: 1. replace recursion with iteration where possible to aid code readability e.g. affinity instance states are changed iteratively instead of recursively. 2. acquire pointers to affinity instance nodes at the beginning of a psci operation. All subsequent actions use these pointers instead of calling psci_get_aff_map_node() repeatedly e.g. management of locks has been abstracted under functions which use these pointers to ensure correct ordering. Helper functions have been added to create these abstractions. 3. assertions have been added to cpu level handlers to ensure correct state transition 4. the affinity level extents specified to various functions have the same meaning i.e. start level is always less than the end level. Change-Id: If0508c3a7b20ea3ddda2a66128429382afc3dfc8
Diffstat (limited to 'common/psci/psci_setup.c')
-rw-r--r--common/psci/psci_setup.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/common/psci/psci_setup.c b/common/psci/psci_setup.c
index 8220b30..decc18d 100644
--- a/common/psci/psci_setup.c
+++ b/common/psci/psci_setup.c
@@ -87,6 +87,56 @@ aff_map_node *psci_get_aff_map_node(unsigned long mpidr, int aff_lvl)
}
/*******************************************************************************
+ * This function populates an array with nodes corresponding to a given range of
+ * affinity levels in an mpidr. It returns successfully only when the affinity
+ * levels are correct, the mpidr is valid i.e. no affinity level is absent from
+ * the topology tree & the affinity instance at level 0 is not absent.
+ ******************************************************************************/
+int psci_get_aff_map_nodes(unsigned long mpidr,
+ int start_afflvl,
+ int end_afflvl,
+ mpidr_aff_map_nodes mpidr_nodes)
+{
+ int rc = PSCI_E_INVALID_PARAMS, level;
+ aff_map_node *node;
+
+ rc = psci_check_afflvl_range(start_afflvl, end_afflvl);
+ if (rc != PSCI_E_SUCCESS)
+ return rc;
+
+ for (level = start_afflvl; level <= end_afflvl; level++) {
+
+ /*
+ * Grab the node for each affinity level. No affinity level
+ * can be missing as that would mean that the topology tree
+ * is corrupted.
+ */
+ node = psci_get_aff_map_node(mpidr, level);
+ if (node == NULL) {
+ rc = PSCI_E_INVALID_PARAMS;
+ break;
+ }
+
+ /*
+ * Skip absent affinity levels unless it's afffinity level 0.
+ * An absent cpu means that the mpidr is invalid. Save the
+ * pointer to the node for the present affinity level
+ */
+ if (!(node->state & PSCI_AFF_PRESENT)) {
+ if (level == MPIDR_AFFLVL0) {
+ rc = PSCI_E_INVALID_PARAMS;
+ break;
+ }
+
+ mpidr_nodes[level] = NULL;
+ } else
+ mpidr_nodes[level] = node;
+ }
+
+ return rc;
+}
+
+/*******************************************************************************
* Function which initializes the 'aff_map_node' corresponding to an affinity
* level instance. Each node has a unique mpidr, level and bakery lock. The data
* field is opaque and holds affinity level specific data e.g. for affinity