From: Thomas Gleixner Date: Sat, 11 Apr 2026 05:58:33 +0000 (+0200) Subject: Merge branch 'timers/urgent' into timers/core X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ff1c0c5d07028a84837950b619d30da623f8ddb2;p=thirdparty%2Fkernel%2Flinux.git Merge branch 'timers/urgent' into timers/core to resolve the conflict with urgent fixes. --- ff1c0c5d07028a84837950b619d30da623f8ddb2 diff --cc include/linux/clockchips.h index 92d90220c0d49,50cdc9da8d32a..6adb72761246d --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@@ -73,6 -73,6 +73,7 @@@ enum clock_event_state * level handler of the event source * @set_next_event: set next event function using a clocksource delta * @set_next_ktime: set next event function using a direct ktime value ++ * @set_next_coupled: set next event function for clocksource coupled mode * @next_event: local storage for the next event in oneshot mode * @max_delta_ns: maximum delta value in ns * @min_delta_ns: minimum delta value in ns @@@ -80,6 -80,7 +81,8 @@@ * @shift: nanoseconds to cycles divisor (power of two) * @state_use_accessors:current state of the device, assigned by the core code * @features: features ++ * @cs_id: Clocksource ID to denote the clocksource for coupled mode + * @next_event_forced: True if the last programming was a forced event * @retries: number of forced programming retries * @set_state_periodic: switch state to periodic * @set_state_oneshot: switch state to oneshot @@@ -109,7 -109,7 +112,8 @@@ struct clock_event_device u32 shift; enum clock_event_state state_use_accessors; unsigned int features; + enum clocksource_ids cs_id; + unsigned int next_event_forced; unsigned long retries; int (*set_state_periodic)(struct clock_event_device *); diff --cc kernel/time/clockevents.c index 83712aa1d385c,38570998a19b8..b4d7306049724 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@@ -332,11 -301,11 +333,10 @@@ static inline bool clockevent_set_next_ * * Returns 0 on success, -ETIME when the event is in the past. */ -int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, - bool force) +int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, bool force) { - unsigned long long clc; int64_t delta; + u64 cycles; - int rc; if (WARN_ON_ONCE(expires < 0)) return -ETIME; @@@ -350,24 -319,32 +350,35 @@@ WARN_ONCE(!clockevent_state_oneshot(dev), "Current state: %d\n", clockevent_get_state(dev)); - /* Shortcut for clockevent devices that can deal with ktime. */ - if (dev->features & CLOCK_EVT_FEAT_KTIME) + /* ktime_t based reprogramming for the broadcast hrtimer device */ + if (unlikely(dev->features & CLOCK_EVT_FEAT_HRTIMER)) return dev->set_next_ktime(expires, dev); + if (likely(clockevent_set_next_coupled(dev, expires))) + return 0; + delta = ktime_to_ns(ktime_sub(expires, ktime_get())); - if (delta <= 0) - return force ? clockevents_program_min_delta(dev) : -ETIME; - delta = min(delta, (int64_t) dev->max_delta_ns); - delta = max(delta, (int64_t) dev->min_delta_ns); + /* Required for tick_periodic() during early boot */ + if (delta <= 0 && !force) + return -ETIME; - cycles = ((u64)delta * dev->mult) >> dev->shift; - rc = dev->set_next_event((unsigned long) cycles, dev); + if (delta > (int64_t)dev->min_delta_ns) { + delta = min(delta, (int64_t) dev->max_delta_ns); - clc = ((unsigned long long) delta * dev->mult) >> dev->shift; - if (!dev->set_next_event((unsigned long) clc, dev)) ++ cycles = ((u64)delta * dev->mult) >> dev->shift; ++ if (!dev->set_next_event((unsigned long) cycles, dev)) + return 0; + } - return (rc && force) ? clockevents_program_min_delta(dev) : rc; + 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; } /*