[REGRESSION][BISECTED] Boot hangs on Allwinner D1 RISC-V board
Indrek Kruusa <[email protected]>
| Newsgroups | dev.linux.lists.regressions |
|---|---|
| Message-ID | <[email protected]> |
Hi! I have an Allwinner D1 based board whose boot process hangs before the root filesystem is mounted. The issue has been present since v7.1-rc1. A git bisect points to: ff1c0c5d07028 Merge branch 'timers/urgent' into timers/core The board boots normally if I revert the changes in kernel/time/clockevents.c back to commit 09c04714cb455 (patch included below to speed up the testing). This platform has a history of requiring special quirks ([1], [2]). I originally reported this issue here [3] [1] https://lore.kernel.org/lkml/[email protected]/ [2] https://lore.kernel.org/linux-riscv/[email protected]/ [3] https://lore.kernel.org/linux-riscv/CA+fTLhgLmTY+exGujKf8OYYQvcEW5X5NJ_5sLq2AYL6zER2c0A@mail.gmail.com/ Best regards, Indrek diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 5e22697b098d8..83712aa1d385c 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -94,9 +94,6 @@ static int __clockevents_switch_state(struct clock_event_device *dev, if (dev->features & CLOCK_EVT_FEAT_DUMMY) return 0; - /* On state transitions clear the forced flag unconditionally */ - dev->next_event_forced = 0; - /* Transition with new state-specific callbacks */ switch (state) { case CLOCK_EVT_STATE_DETACHED: @@ -175,7 +172,6 @@ void clockevents_shutdown(struct clock_event_device *dev) { clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); dev->next_event = KTIME_MAX; - dev->next_event_forced = 0; } /** @@ -340,6 +336,7 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, b { int64_t delta; u64 cycles; + int rc; if (WARN_ON_ONCE(expires < 0)) return -ETIME; @@ -361,29 +358,16 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, b return 0; delta = ktime_to_ns(ktime_sub(expires, ktime_get())); + if (delta <= 0) + return force ? clockevents_program_min_delta(dev) : -ETIME; - /* Required for tick_periodic() during early boot */ - if (delta <= 0 && !force) - return -ETIME; + delta = min(delta, (int64_t) dev->max_delta_ns); + delta = max(delta, (int64_t) dev->min_delta_ns); - if (delta > (int64_t)dev->min_delta_ns) { - delta = min(delta, (int64_t) dev->max_delta_ns); - cycles = ((u64)delta * dev->mult) >> dev->shift; - if (!dev->set_next_event((unsigned long) cycles, dev)) { - dev->next_event_forced = 0; - return 0; - } - } + cycles = ((u64)delta * dev->mult) >> dev->shift; + rc = dev->set_next_event((unsigned long) cycles, dev); - if (dev->next_event_forced) - return 0; - - if (dev->set_next_event(dev->min_delta_ticks, dev)) { - if (!force || clockevents_program_min_delta(dev)) - return -ETIME; - } - dev->next_event_forced = 1; - return 0; + return (rc && force) ? clockevents_program_min_delta(dev) : rc; } /*