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
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 @@
 }
 
 /*******************************************************************************
+ * 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