Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
f5b904ea
Commit
f5b904ea
authored
Jun 10, 2019
by
Soby Mathew
Committed by
TrustedFirmware Code Review
Jun 10, 2019
Browse files
Merge "PSCI: Lookup list of parent nodes to lock only once" into integration
parents
08156504
74d27d00
Changes
4
Hide whitespace changes
Inline
Side-by-side
lib/psci/psci_common.c
View file @
f5b904ea
...
@@ -568,35 +568,35 @@ unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info)
...
@@ -568,35 +568,35 @@ unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info)
}
}
/*******************************************************************************
/*******************************************************************************
* This function is passed a cpu_index and the highest level in the topology
* This function is passed the highest level in the topology tree that the
* tree that the operation should be applied to. It picks up locks in order of
* operation should be applied to and a list of node indexes. It picks up locks
* increasing power domain level in the range specified.
* from the node index list in order of increasing power domain level in the
* range specified.
******************************************************************************/
******************************************************************************/
void
psci_acquire_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
int
cpu_idx
)
void
psci_acquire_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
const
unsigned
int
*
parent_nodes
)
{
{
unsigned
int
parent_idx
=
psci_cpu_pd_nodes
[
cpu_idx
].
parent_node
;
unsigned
int
parent_idx
;
unsigned
int
level
;
unsigned
int
level
;
/* No locking required for level 0. Hence start locking from level 1 */
/* No locking required for level 0. Hence start locking from level 1 */
for
(
level
=
PSCI_CPU_PWR_LVL
+
1U
;
level
<=
end_pwrlvl
;
level
++
)
{
for
(
level
=
PSCI_CPU_PWR_LVL
+
1U
;
level
<=
end_pwrlvl
;
level
++
)
{
parent_idx
=
parent_nodes
[
level
-
1U
];
psci_lock_get
(
&
psci_non_cpu_pd_nodes
[
parent_idx
]);
psci_lock_get
(
&
psci_non_cpu_pd_nodes
[
parent_idx
]);
parent_idx
=
psci_non_cpu_pd_nodes
[
parent_idx
].
parent_node
;
}
}
}
}
/*******************************************************************************
/*******************************************************************************
* This function is passed
a cpu_index and
the highest level in the topology
* This function is passed the highest level in the topology
tree that the
*
tree that the
operation should be applied to. It releases the
locks in order
* operation should be applied to
and a list of node indexes
. It releases the
* of decreasing power domain level in the range specified.
*
locks in order
of decreasing power domain level in the range specified.
******************************************************************************/
******************************************************************************/
void
psci_release_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
int
cpu_idx
)
void
psci_release_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
const
unsigned
int
*
parent_nodes
)
{
{
unsigned
int
parent_idx
,
parent_nodes
[
PLAT_MAX_PWR_LVL
]
=
{
0
}
;
unsigned
int
parent_idx
;
unsigned
int
level
;
unsigned
int
level
;
/* Get the parent nodes */
psci_get_parent_pwr_domain_nodes
(
cpu_idx
,
end_pwrlvl
,
parent_nodes
);
/* Unlock top down. No unlocking required for level 0. */
/* Unlock top down. No unlocking required for level 0. */
for
(
level
=
end_pwrlvl
;
level
>=
PSCI_CPU_PWR_LVL
+
1U
;
level
--
)
{
for
(
level
=
end_pwrlvl
;
level
>=
PSCI_CPU_PWR_LVL
+
1U
;
level
--
)
{
parent_idx
=
parent_nodes
[
level
-
1U
];
parent_idx
=
parent_nodes
[
level
-
1U
];
...
@@ -764,6 +764,7 @@ void psci_warmboot_entrypoint(void)
...
@@ -764,6 +764,7 @@ void psci_warmboot_entrypoint(void)
{
{
unsigned
int
end_pwrlvl
;
unsigned
int
end_pwrlvl
;
int
cpu_idx
=
(
int
)
plat_my_core_pos
();
int
cpu_idx
=
(
int
)
plat_my_core_pos
();
unsigned
int
parent_nodes
[
PLAT_MAX_PWR_LVL
]
=
{
0
};
psci_power_state_t
state_info
=
{
{
PSCI_LOCAL_STATE_RUN
}
};
psci_power_state_t
state_info
=
{
{
PSCI_LOCAL_STATE_RUN
}
};
/*
/*
...
@@ -781,12 +782,15 @@ void psci_warmboot_entrypoint(void)
...
@@ -781,12 +782,15 @@ void psci_warmboot_entrypoint(void)
*/
*/
end_pwrlvl
=
get_power_on_target_pwrlvl
();
end_pwrlvl
=
get_power_on_target_pwrlvl
();
/* Get the parent nodes */
psci_get_parent_pwr_domain_nodes
(
cpu_idx
,
end_pwrlvl
,
parent_nodes
);
/*
/*
* This function acquires the lock corresponding to each power level so
* This function acquires the lock corresponding to each power level so
* that by the time all locks are taken, the system topology is snapshot
* that by the time all locks are taken, the system topology is snapshot
* and state management can be done safely.
* and state management can be done safely.
*/
*/
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
cpu_idx
);
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
psci_get_target_local_pwr_states
(
end_pwrlvl
,
&
state_info
);
psci_get_target_local_pwr_states
(
end_pwrlvl
,
&
state_info
);
...
@@ -831,7 +835,7 @@ void psci_warmboot_entrypoint(void)
...
@@ -831,7 +835,7 @@ void psci_warmboot_entrypoint(void)
* This loop releases the lock corresponding to each power level
* This loop releases the lock corresponding to each power level
* in the reverse order to which they were acquired.
* in the reverse order to which they were acquired.
*/
*/
psci_release_pwr_domain_locks
(
end_pwrlvl
,
cpu_idx
);
psci_release_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
}
}
/*******************************************************************************
/*******************************************************************************
...
...
lib/psci/psci_off.c
View file @
f5b904ea
...
@@ -45,6 +45,7 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
...
@@ -45,6 +45,7 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
int
rc
=
PSCI_E_SUCCESS
;
int
rc
=
PSCI_E_SUCCESS
;
int
idx
=
(
int
)
plat_my_core_pos
();
int
idx
=
(
int
)
plat_my_core_pos
();
psci_power_state_t
state_info
;
psci_power_state_t
state_info
;
unsigned
int
parent_nodes
[
PLAT_MAX_PWR_LVL
]
=
{
0
};
/*
/*
* This function must only be called on platforms where the
* This function must only be called on platforms where the
...
@@ -55,12 +56,21 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
...
@@ -55,12 +56,21 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
/* Construct the psci_power_state for CPU_OFF */
/* Construct the psci_power_state for CPU_OFF */
psci_set_power_off_state
(
&
state_info
);
psci_set_power_off_state
(
&
state_info
);
/*
* Get the parent nodes here, this is important to do before we
* initiate the power down sequence as after that point the core may
* have exited coherency and its cache may be disabled, any access to
* shared memory after that (such as the parent node lookup in
* psci_cpu_pd_nodes) can cause coherency issues on some platforms.
*/
psci_get_parent_pwr_domain_nodes
(
idx
,
end_pwrlvl
,
parent_nodes
);
/*
/*
* This function acquires the lock corresponding to each power
* This function acquires the lock corresponding to each power
* level so that by the time all locks are taken, the system topology
* level so that by the time all locks are taken, the system topology
* is snapshot and state management can be done safely.
* is snapshot and state management can be done safely.
*/
*/
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
idx
);
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
/*
/*
* Call the cpu off handler registered by the Secure Payload Dispatcher
* Call the cpu off handler registered by the Secure Payload Dispatcher
...
@@ -122,7 +132,7 @@ exit:
...
@@ -122,7 +132,7 @@ exit:
* Release the locks corresponding to each power level in the
* Release the locks corresponding to each power level in the
* reverse order to which they were acquired.
* reverse order to which they were acquired.
*/
*/
psci_release_pwr_domain_locks
(
end_pwrlvl
,
idx
);
psci_release_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
/*
/*
* Check if all actions needed to safely power down this cpu have
* Check if all actions needed to safely power down this cpu have
...
...
lib/psci/psci_private.h
View file @
f5b904ea
...
@@ -274,8 +274,10 @@ void psci_get_parent_pwr_domain_nodes(int cpu_idx,
...
@@ -274,8 +274,10 @@ void psci_get_parent_pwr_domain_nodes(int cpu_idx,
unsigned
int
*
node_index
);
unsigned
int
*
node_index
);
void
psci_do_state_coordination
(
unsigned
int
end_pwrlvl
,
void
psci_do_state_coordination
(
unsigned
int
end_pwrlvl
,
psci_power_state_t
*
state_info
);
psci_power_state_t
*
state_info
);
void
psci_acquire_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
int
cpu_idx
);
void
psci_acquire_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
void
psci_release_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
int
cpu_idx
);
const
unsigned
int
*
parent_nodes
);
void
psci_release_pwr_domain_locks
(
unsigned
int
end_pwrlvl
,
const
unsigned
int
*
parent_nodes
);
int
psci_validate_suspend_req
(
const
psci_power_state_t
*
state_info
,
int
psci_validate_suspend_req
(
const
psci_power_state_t
*
state_info
,
unsigned
int
is_power_down_state
);
unsigned
int
is_power_down_state
);
unsigned
int
psci_find_max_off_lvl
(
const
psci_power_state_t
*
state_info
);
unsigned
int
psci_find_max_off_lvl
(
const
psci_power_state_t
*
state_info
);
...
...
lib/psci/psci_suspend.c
View file @
f5b904ea
...
@@ -28,10 +28,13 @@
...
@@ -28,10 +28,13 @@
static
void
psci_suspend_to_standby_finisher
(
int
cpu_idx
,
static
void
psci_suspend_to_standby_finisher
(
int
cpu_idx
,
unsigned
int
end_pwrlvl
)
unsigned
int
end_pwrlvl
)
{
{
unsigned
int
parent_nodes
[
PLAT_MAX_PWR_LVL
]
=
{
0
};
psci_power_state_t
state_info
;
psci_power_state_t
state_info
;
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
/* Get the parent nodes */
cpu_idx
);
psci_get_parent_pwr_domain_nodes
(
cpu_idx
,
end_pwrlvl
,
parent_nodes
);
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
/*
/*
* Find out which retention states this CPU has exited from until the
* Find out which retention states this CPU has exited from until the
...
@@ -57,8 +60,7 @@ static void psci_suspend_to_standby_finisher(int cpu_idx,
...
@@ -57,8 +60,7 @@ static void psci_suspend_to_standby_finisher(int cpu_idx,
*/
*/
psci_set_pwr_domains_to_run
(
end_pwrlvl
);
psci_set_pwr_domains_to_run
(
end_pwrlvl
);
psci_release_pwr_domain_locks
(
end_pwrlvl
,
psci_release_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
cpu_idx
);
}
}
/*******************************************************************************
/*******************************************************************************
...
@@ -156,6 +158,7 @@ void psci_cpu_suspend_start(const entry_point_info_t *ep,
...
@@ -156,6 +158,7 @@ void psci_cpu_suspend_start(const entry_point_info_t *ep,
{
{
int
skip_wfi
=
0
;
int
skip_wfi
=
0
;
int
idx
=
(
int
)
plat_my_core_pos
();
int
idx
=
(
int
)
plat_my_core_pos
();
unsigned
int
parent_nodes
[
PLAT_MAX_PWR_LVL
]
=
{
0
};
/*
/*
* This function must only be called on platforms where the
* This function must only be called on platforms where the
...
@@ -164,13 +167,15 @@ void psci_cpu_suspend_start(const entry_point_info_t *ep,
...
@@ -164,13 +167,15 @@ void psci_cpu_suspend_start(const entry_point_info_t *ep,
assert
((
psci_plat_pm_ops
->
pwr_domain_suspend
!=
NULL
)
&&
assert
((
psci_plat_pm_ops
->
pwr_domain_suspend
!=
NULL
)
&&
(
psci_plat_pm_ops
->
pwr_domain_suspend_finish
!=
NULL
));
(
psci_plat_pm_ops
->
pwr_domain_suspend_finish
!=
NULL
));
/* Get the parent nodes */
psci_get_parent_pwr_domain_nodes
(
idx
,
end_pwrlvl
,
parent_nodes
);
/*
/*
* This function acquires the lock corresponding to each power
* This function acquires the lock corresponding to each power
* level so that by the time all locks are taken, the system topology
* level so that by the time all locks are taken, the system topology
* is snapshot and state management can be done safely.
* is snapshot and state management can be done safely.
*/
*/
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
psci_acquire_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
idx
);
/*
/*
* We check if there are any pending interrupts after the delay
* We check if there are any pending interrupts after the delay
...
@@ -214,8 +219,8 @@ exit:
...
@@ -214,8 +219,8 @@ exit:
* Release the locks corresponding to each power level in the
* Release the locks corresponding to each power level in the
* reverse order to which they were acquired.
* reverse order to which they were acquired.
*/
*/
psci_release_pwr_domain_locks
(
end_pwrlvl
,
psci_release_pwr_domain_locks
(
end_pwrlvl
,
parent_nodes
);
idx
);
if
(
skip_wfi
==
1
)
if
(
skip_wfi
==
1
)
return
;
return
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment