diff options
| author | Rasmus Villemoes <[email protected]> | 2026-07-30 12:55:15 +0200 |
|---|---|---|
| committer | Stefan Roese <[email protected]> | 2026-08-03 15:00:33 +0200 |
| commit | 2f44bb1417bfbcd2c8722dddec76425f27c8a8f5 (patch) | |
| tree | 687a7aa4364deecdb2b1d4fc0a1f74c992b56e45 | |
| parent | dcadbeed2a90b2e1cc98c369b299c3c59e9d712c (diff) | |
cyclic: return early from cyclic_run() if the list is empty
It is possible that schedule(), and hence cyclic_run(), gets called
very early, perhaps even from assembly code. With
commit 9c1b13b3fd27 ("cyclic: reduce get_timer_us() calls inside
hlist_for_each_entry_safe()"), there is now an unconditional
get_timer_us(0) done outside the loop, and depending on the platform,
the timer infrastructure may not be set up yet. In at least one case,
that has caused a divide-by-0 and hence a failure to boot.
Platforms should really ensure their timers are ready ASAP, and in the
concrete case reported, that was indeed possible to fix that
way. However, it doesn't hurt to also insert an early return here, and
that could prevent other such hard-to-debug boot failures.
Reported-by: Emanuele Ghidoli <[email protected]>
Link: https://marc.info/?l=u-boot&m=178481834846283&w=2
Fixes: 9c1b13b3fd27 ("cyclic: reduce get_timer_us() calls inside hlist_for_each_entry_safe()")
Signed-off-by: Rasmus Villemoes <[email protected]>
Reviewed-by: Emanuele Ghidoli <[email protected]>
Reviewed-by: Stefan Roese <[email protected]>
[sr: fix Fixes: tag SHA length and return statement indentation]
| -rw-r--r-- | common/cyclic.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/common/cyclic.c b/common/cyclic.c index 2bc3c773f27..1cf5b25d1d8 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -63,6 +63,19 @@ static void cyclic_run(void) struct hlist_node *tmp; u64 now, after, cpu_time; + /* + * Nothing to do if the list is empty. Also, schedule() can be + * called before timer infrastructure is ready, in which case + * calling get_timer_us() before the (empty) loop could cause + * a divide-by-0 or otherwise crash the system. No clients + * should be registered before the timer infrastructure is up, + * so the check for the list being empty should be + * ok. Otherwise, we would need a new GD_FLG_TIMERS_READY + * flag. + */ + if (hlist_empty(&gd->cyclic_list)) + return; + /* Prevent recursion */ if (gd->flags & GD_FLG_CYCLIC_RUNNING) return; |
