Merge pull request #145 from athoelke/at/psci-memory-optimization-v2

PSCI memory optimizations (v2)
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index d970190..f854af9 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -150,6 +150,11 @@
     Defines the maximum number of CPUs that can be implemented within a cluster
     on the platform.
 
+*   **#define : PLATFORM_NUM_AFFS**
+
+    Defines the total number of nodes in the affinity heirarchy at all affinity
+    levels used by the platform.
+
 *   **#define : PRIMARY_CPU**
 
     Defines the `MPIDR` of the primary CPU on the platform. This value is used
diff --git a/include/bl31/services/psci.h b/include/bl31/services/psci.h
index 887c4ce..77f406d 100644
--- a/include/bl31/services/psci.h
+++ b/include/bl31/services/psci.h
@@ -128,9 +128,6 @@
 #define psci_validate_power_state(pstate) (pstate & PSTATE_VALID_MASK)
 
 
-/* Number of affinity instances whose state this psci imp. can track */
-#define PSCI_NUM_AFFS		32ull
-
 #ifndef __ASSEMBLY__
 
 #include <stdint.h>
diff --git a/plat/fvp/include/platform_def.h b/plat/fvp/include/platform_def.h
index c8aaee6..fe4d73b 100644
--- a/plat/fvp/include/platform_def.h
+++ b/plat/fvp/include/platform_def.h
@@ -75,6 +75,8 @@
 #define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER1_CORE_COUNT + \
 						PLATFORM_CLUSTER0_CORE_COUNT)
 #define PLATFORM_MAX_CPUS_PER_CLUSTER	4
+#define PLATFORM_NUM_AFFS		(PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
 #define PRIMARY_CPU			0x0
 #define MAX_IO_DEVICES			3
 #define MAX_IO_HANDLES			4
diff --git a/services/std_svc/psci/psci_afflvl_suspend.c b/services/std_svc/psci/psci_afflvl_suspend.c
index f43dced..ea90389 100644
--- a/services/std_svc/psci/psci_afflvl_suspend.c
+++ b/services/std_svc/psci/psci_afflvl_suspend.c
@@ -57,16 +57,11 @@
 	assert(node->mpidr == (read_mpidr() & MPIDR_AFFINITY_MASK));
 	assert(node->level == MPIDR_AFFLVL0);
 
-	/* Save PSCI power state parameter for the core in suspend context */
-	psci_suspend_context[node->data].power_state = power_state;
-
 	/*
-	 * Flush the suspend data to PoC since it will be accessed while
-	 * returning back from suspend with the caches turned off
+	 * Save PSCI power state parameter for the core in suspend context.
+	 * The node is in always-coherent RAM so it does not need to be flushed
 	 */
-	flush_dcache_range(
-		(unsigned long)&psci_suspend_context[node->data],
-		sizeof(suspend_context_t));
+	node->power_state = power_state;
 }
 
 /*******************************************************************************
@@ -97,7 +92,7 @@
 
 	assert(node->level == MPIDR_AFFLVL0);
 
-	power_state = psci_suspend_context[node->data].power_state;
+	power_state = node->power_state;
 	return ((power_state == PSCI_INVALID_DATA) ?
 				power_state : psci_get_pstate_afflvl(power_state));
 }
@@ -117,7 +112,7 @@
 	assert(node);
 	assert(node->level == MPIDR_AFFLVL0);
 
-	power_state = psci_suspend_context[node->data].power_state;
+	power_state = node->power_state;
 	return ((power_state == PSCI_INVALID_DATA) ?
 					power_state : psci_get_pstate_id(power_state));
 }
diff --git a/services/std_svc/psci/psci_common.c b/services/std_svc/psci/psci_common.c
index d69c5f5..87be843 100644
--- a/services/std_svc/psci/psci_common.c
+++ b/services/std_svc/psci/psci_common.c
@@ -46,13 +46,6 @@
 const spd_pm_ops_t *psci_spd_pm;
 
 /*******************************************************************************
- * Arrays that contains information needs to resume a cpu's execution when woken
- * out of suspend or off states. Each cpu is allocated a single entry in each
- * array during startup.
- ******************************************************************************/
-suspend_context_t psci_suspend_context[PSCI_NUM_AFFS];
-
-/*******************************************************************************
  * Grand array that holds the platform's topology information for state
  * management of affinity instances. Each node (aff_map_node) in the array
  * corresponds to an affinity instance e.g. cluster, cpu within an mpidr
diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h
index 970ad21..f534087 100644
--- a/services/std_svc/psci/psci_private.h
+++ b/services/std_svc/psci/psci_private.h
@@ -33,8 +33,16 @@
 
 #include <arch.h>
 #include <bakery_lock.h>
+#include <platform_def.h>	/* for PLATFORM_NUM_AFFS */
 #include <psci.h>
 
+/* Number of affinity instances whose state this psci imp. can track */
+#ifdef PLATFORM_NUM_AFFS
+#define PSCI_NUM_AFFS		PLATFORM_NUM_AFFS
+#else
+#define PSCI_NUM_AFFS		(2 * PLATFORM_CORE_COUNT)
+#endif
+
 /*******************************************************************************
  * The following two data structures hold the topology tree which in turn tracks
  * the state of the all the affinity instances supported by the platform.
@@ -44,7 +52,7 @@
 	unsigned short ref_count;
 	unsigned char state;
 	unsigned char level;
-	unsigned int data;
+	unsigned int power_state;
 	bakery_lock_t lock;
 } aff_map_node_t;
 
@@ -53,14 +61,6 @@
 	int max;
 } aff_limits_node_t;
 
-/*******************************************************************************
- * This data structure holds secure world context that needs to be preserved
- * across cpu_suspend calls which enter the power down state.
- ******************************************************************************/
-typedef struct suspend_context {
-	unsigned int power_state;
-} __aligned(CACHE_WRITEBACK_GRANULE) suspend_context_t;
-
 typedef aff_map_node_t (*mpidr_aff_map_nodes_t[MPIDR_MAX_AFFLVL]);
 typedef unsigned int (*afflvl_power_on_finisher_t)(unsigned long,
 						 aff_map_node_t *);
@@ -68,7 +68,6 @@
 /*******************************************************************************
  * Data prototypes
  ******************************************************************************/
-extern suspend_context_t psci_suspend_context[PSCI_NUM_AFFS];
 extern const plat_pm_ops_t *psci_plat_pm_ops;
 extern aff_map_node_t psci_aff_map[PSCI_NUM_AFFS];
 
diff --git a/services/std_svc/psci/psci_setup.c b/services/std_svc/psci/psci_setup.c
index af82150..68f19a0 100644
--- a/services/std_svc/psci/psci_setup.c
+++ b/services/std_svc/psci/psci_setup.c
@@ -58,12 +58,6 @@
 static aff_limits_node_t psci_aff_limits[MPIDR_MAX_AFFLVL + 1];
 
 /*******************************************************************************
- * 'psci_ns_einfo_idx' keeps track of the next free index in the
- * 'psci_suspend_context' arrays.
- ******************************************************************************/
-static unsigned int psci_ns_einfo_idx;
-
-/*******************************************************************************
  * Routines for retrieving the node corresponding to an affinity level instance
  * in the mpidr. The first one uses binary search to find the node corresponding
  * to the mpidr (key) at a particular affinity level. The second routine decides
@@ -195,13 +189,8 @@
 		if (state & PSCI_AFF_PRESENT)
 			psci_set_state(&psci_aff_map[idx], PSCI_STATE_OFF);
 
-		/* Ensure that we have not overflowed the psci_ns_einfo array */
-		assert(psci_ns_einfo_idx < PSCI_NUM_AFFS);
-
-		psci_aff_map[idx].data = psci_ns_einfo_idx;
 		/* Invalidate the suspend context for the node */
-		psci_suspend_context[psci_ns_einfo_idx].power_state = PSCI_INVALID_DATA;
-		psci_ns_einfo_idx++;
+		psci_aff_map[idx].power_state = PSCI_INVALID_DATA;
 
 		/*
 		 * Associate a non-secure context with this affinity
@@ -301,7 +290,6 @@
 	int afflvl, affmap_idx, max_afflvl;
 	aff_map_node_t *node;
 
-	psci_ns_einfo_idx = 0;
 	psci_plat_pm_ops = NULL;
 
 	/* Find out the maximum affinity level that the platform implements */