diff --git a/services/std_svc/psci/psci_afflvl_off.c b/services/std_svc/psci/psci_afflvl_off.c index 83d19d3..6bf12db 100644 --- a/services/std_svc/psci/psci_afflvl_off.c +++ b/services/std_svc/psci/psci_afflvl_off.c @@ -47,9 +47,6 @@ assert(cpu_node->level == MPIDR_AFFLVL0); - /* State management: mark this cpu as turned off */ - psci_set_state(cpu_node, PSCI_STATE_OFF); - /* * Generic management: Get the index for clearing any lingering re-entry * information and allow the secure world to switch itself off @@ -97,9 +94,6 @@ /* Sanity check the cluster level */ assert(cluster_node->level == MPIDR_AFFLVL1); - /* State management: Decrement the cluster reference count */ - psci_set_state(cluster_node, PSCI_STATE_OFF); - /* * Keep the physical state of this cluster handy to decide * what action needs to be taken @@ -134,9 +128,6 @@ /* Cannot go beyond this level */ assert(system_node->level == MPIDR_AFFLVL2); - /* State management: Decrement the system reference count */ - psci_set_state(system_node, PSCI_STATE_OFF); - /* * Keep the physical state of the system handy to decide what * action needs to be taken @@ -240,6 +231,15 @@ end_afflvl, mpidr_nodes); + /* + * This function updates the state of each affinity instance + * corresponding to the mpidr in the range of affinity levels + * specified. + */ + psci_do_afflvl_state_mgmt(start_afflvl, + end_afflvl, + mpidr_nodes, + PSCI_STATE_OFF); /* Perform generic, architecture and platform specific handling */ rc = psci_call_off_handlers(mpidr_nodes, start_afflvl, diff --git a/services/std_svc/psci/psci_afflvl_on.c b/services/std_svc/psci/psci_afflvl_on.c index 3b7d805..10bc586 100644 --- a/services/std_svc/psci/psci_afflvl_on.c +++ b/services/std_svc/psci/psci_afflvl_on.c @@ -113,9 +113,6 @@ /* Set the secure world (EL3) re-entry point after BL1 */ psci_entrypoint = (unsigned long) psci_aff_on_finish_entry; - /* State management: Set this cpu's state as ON PENDING */ - psci_set_state(cpu_node, PSCI_STATE_ON_PENDING); - /* * Plat. management: Give the platform the current state * of the target cpu to allow it to perform the necessary @@ -318,6 +315,17 @@ context_id); /* + * This function updates the state of each affinity instance + * corresponding to the mpidr in the range of affinity levels + * specified. + */ + if (rc == PSCI_E_SUCCESS) + psci_do_afflvl_state_mgmt(start_afflvl, + end_afflvl, + target_cpu_nodes, + PSCI_STATE_ON_PENDING); + + /* * This loop releases the lock corresponding to each affinity level * in the reverse order to which they were acquired. */ @@ -385,9 +393,6 @@ */ cm_prepare_el3_exit(NON_SECURE); - /* State management: mark this cpu as on */ - psci_set_state(cpu_node, PSCI_STATE_ON); - /* Clean caches before re-entering normal world */ dcsw_op_louis(DCCSW); @@ -419,9 +424,6 @@ assert(rc == PSCI_E_SUCCESS); } - /* State management: Increment the cluster reference count */ - psci_set_state(cluster_node, PSCI_STATE_ON); - return rc; } @@ -456,9 +458,6 @@ assert(rc == PSCI_E_SUCCESS); } - /* State management: Increment the system reference count */ - psci_set_state(system_node, PSCI_STATE_ON); - return rc; } @@ -467,4 +466,3 @@ psci_afflvl1_on_finish, psci_afflvl2_on_finish, }; - diff --git a/services/std_svc/psci/psci_afflvl_suspend.c b/services/std_svc/psci/psci_afflvl_suspend.c index a123dc3..4fb640a 100644 --- a/services/std_svc/psci/psci_afflvl_suspend.c +++ b/services/std_svc/psci/psci_afflvl_suspend.c @@ -135,9 +135,6 @@ if (psci_spd_pm && psci_spd_pm->svc_suspend) psci_spd_pm->svc_suspend(power_state); - /* State management: mark this cpu as suspended */ - psci_set_state(cpu_node, PSCI_STATE_SUSPEND); - /* * Generic management: Store the re-entry information for the * non-secure world @@ -188,9 +185,6 @@ /* Sanity check the cluster level */ assert(cluster_node->level == MPIDR_AFFLVL1); - /* State management: Decrement the cluster reference count */ - psci_set_state(cluster_node, PSCI_STATE_SUSPEND); - /* * Keep the physical state of this cluster handy to decide * what action needs to be taken @@ -241,9 +235,6 @@ /* Cannot go beyond this */ assert(system_node->level == MPIDR_AFFLVL2); - /* State management: Decrement the system reference count */ - psci_set_state(system_node, PSCI_STATE_SUSPEND); - /* * Keep the physical state of the system handy to decide what * action needs to be taken @@ -365,6 +356,15 @@ end_afflvl, mpidr_nodes); + /* + * This function updates the state of each affinity instance + * corresponding to the mpidr in the range of affinity levels + * specified. + */ + psci_do_afflvl_state_mgmt(start_afflvl, + end_afflvl, + mpidr_nodes, + PSCI_STATE_SUSPEND); /* Perform generic, architecture and platform specific handling */ rc = psci_call_suspend_handlers(mpidr_nodes, start_afflvl, @@ -450,9 +450,6 @@ */ cm_prepare_el3_exit(NON_SECURE); - /* State management: mark this cpu as on */ - psci_set_state(cpu_node, PSCI_STATE_ON); - /* Clean caches before re-entering normal world */ dcsw_op_louis(DCCSW); @@ -484,9 +481,6 @@ assert(rc == PSCI_E_SUCCESS); } - /* State management: Increment the cluster reference count */ - psci_set_state(cluster_node, PSCI_STATE_ON); - return rc; } @@ -521,9 +515,6 @@ assert(rc == PSCI_E_SUCCESS); } - /* State management: Increment the system reference count */ - psci_set_state(system_node, PSCI_STATE_ON); - return rc; } diff --git a/services/std_svc/psci/psci_common.c b/services/std_svc/psci/psci_common.c index 9daf6f0..9485506 100644 --- a/services/std_svc/psci/psci_common.c +++ b/services/std_svc/psci/psci_common.c @@ -155,6 +155,25 @@ /******************************************************************************* * This function is passed an array of pointers to affinity level nodes in the + * topology tree for an mpidr and the state which each node should transition + * to. It updates the state of each node between the specified affinity levels. + ******************************************************************************/ +void psci_do_afflvl_state_mgmt(uint32_t start_afflvl, + uint32_t end_afflvl, + mpidr_aff_map_nodes_t mpidr_nodes, + uint32_t state) +{ + uint32_t level; + + for (level = start_afflvl; level <= end_afflvl; level++) { + if (mpidr_nodes[level] == NULL) + continue; + psci_set_state(mpidr_nodes[level], state); + } +} + +/******************************************************************************* + * This function is passed an array of pointers to affinity level nodes in the * topology tree for an mpidr. It picks up locks for each affinity level bottom * up in the range specified. ******************************************************************************/ @@ -431,6 +450,16 @@ panic(); /* + * This function updates the state of each affinity instance + * corresponding to the mpidr in the range of affinity levels + * specified. + */ + psci_do_afflvl_state_mgmt(start_afflvl, + end_afflvl, + mpidr_nodes, + PSCI_STATE_ON); + + /* * This loop releases the lock corresponding to each affinity level * in the reverse order to which they were acquired. */ diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h index 158a5f7..73690b8 100644 --- a/services/std_svc/psci/psci_private.h +++ b/services/std_svc/psci/psci_private.h @@ -92,6 +92,10 @@ uint64_t entrypoint, uint64_t context_id, uint32_t caller_scr_el3, uint32_t caller_sctlr_el1); int psci_check_afflvl_range(int start_afflvl, int end_afflvl); +void psci_do_afflvl_state_mgmt(uint32_t start_afflvl, + uint32_t end_afflvl, + mpidr_aff_map_nodes_t mpidr_nodes, + uint32_t state); void psci_acquire_afflvl_locks(int start_afflvl, int end_afflvl, mpidr_aff_map_nodes_t mpidr_nodes);