[init] Add LK_INIT_HOOK_FLAGS

The new LK_INIT_HOOK_FLAGS macro can be used with a LK_INIT_FLAG_ALL_CPUS
flag to run an init hook on all cpus or with LK_INIT_FLAG_SECONDARY_CPUS
to run a hook on secondary cpus.

Change-Id: If866e287271de11082e61eeaf10be3a396e85950
Signed-off-by: Arve Hjønnevåg <arve@android.com>
This commit is contained in:
Arve Hjønnevåg
2013-09-16 19:59:22 -07:00
parent 375a896ecb
commit 0688393516
2 changed files with 54 additions and 10 deletions

View File

@@ -38,13 +38,20 @@
extern const struct lk_init_struct __lk_init[];
extern const struct lk_init_struct __lk_init_end[];
static uint last_init_level = 0;
enum init_level_type {
INIT_LEVEL_TYPE_PRIMARY_CPU,
INIT_LEVEL_TYPE_SECONDARY_CPUS,
INIT_LEVEL_TYPE_COUNT
};
static uint last_init_level[INIT_LEVEL_TYPE_COUNT];
int lk_init_level(uint level)
int lk_init_level_common(uint level, enum init_level_type type)
{
LTRACEF("level %#x, last_init_level %#x\n", level, last_init_level);
LTRACEF("level %#x, last_init_level %#x\n", level, last_init_level[type]);
uint last_called_level = last_init_level;
uint required_flag = (type == INIT_LEVEL_TYPE_PRIMARY_CPU) ?
LK_INIT_FLAG_PRIMARY_CPU : LK_INIT_FLAG_SECONDARY_CPUS;
uint last_called_level = last_init_level[type];
const struct lk_init_struct *last = NULL;
for (;;) {
/* search for the lowest uncalled hook to call */
@@ -53,12 +60,14 @@ int lk_init_level(uint level)
const struct lk_init_struct *found = NULL;
bool seen_last = false;
for (const struct lk_init_struct *ptr = __lk_init; ptr != __lk_init_end; ptr++) {
LTRACEF("looking at %p (%s) level %#x, seen_last %d\n", ptr, ptr->name, ptr->level, seen_last);
LTRACEF("looking at %p (%s) level %#x, flags %#x, seen_last %d\n", ptr, ptr->name, ptr->level, ptr->flags, seen_last);
if (ptr == last)
seen_last = true;
/* reject the easy ones */
if (!(ptr->flags & required_flag))
continue;
if (ptr->level > level)
continue;
if (ptr->level < last_called_level)
@@ -67,7 +76,7 @@ int lk_init_level(uint level)
continue;
/* keep the lowest one we haven't called yet */
if (ptr->level > last_init_level && ptr->level > last_called_level) {
if (ptr->level > last_init_level[type] && ptr->level > last_called_level) {
found = ptr;
continue;
}
@@ -86,18 +95,37 @@ int lk_init_level(uint level)
break;
#if TRACE_INIT
printf("INIT: calling hook %p (%s) at level %#x\n", found->hook, found->name, found->level);
printf("INIT: calling hook %p (%s) at level %#x, flags %#x\n", found->hook, found->name, found->level, found->flags);
#endif
found->hook(found->level);
last_called_level = found->level;
last = found;
}
last_init_level = level;
last_init_level[type] = level;
return 0;
}
int lk_init_level(uint level)
{
return lk_init_level_common(level, INIT_LEVEL_TYPE_PRIMARY_CPU);
}
/* Since there may be multiple secondary CPUs, we allow reseting the
* last_init_level for secondary CPUs so that we can call the same handlers
* on all secondary CPUs without having a separate last_init_level for each CPU.
*/
void lk_secondary_cpu_reset_init_level(void)
{
last_init_level[INIT_LEVEL_TYPE_SECONDARY_CPUS] = 0;
}
int lk_secondary_cpu_init_level(uint level)
{
return lk_init_level_common(level, INIT_LEVEL_TYPE_SECONDARY_CPUS);
}
#if 0
void test_hook(uint level)
{