Commit 0ba97bc4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Ingo Molnar:
 "The main changes in this cycle were:

   - rework hrtimer expiry calculation in hrtimer_interrupt(): the
     previous code had a subtle bug where expiry caching would miss an
     expiry, resulting in occasional bogus (late) expiry of hrtimers.

   - continuing Y2038 fixes

   - ktime division optimization

   - misc smaller fixes and cleanups"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  hrtimer: Make __hrtimer_get_next_event() static
  rtc: Convert rtc_set_ntp_time() to use timespec64
  rtc: Remove redundant rtc_valid_tm() from rtc_hctosys()
  rtc: Modify rtc_hctosys() to address y2038 issues
  rtc: Update rtc-dev to use y2038-safe time interfaces
  rtc: Update interface.c to use y2038-safe time interfaces
  time: Expose get_monotonic_boottime64 for in-kernel use
  time: Expose getboottime64 for in-kernel uses
  ktime: Optimize ktime_divns for constant divisors
  hrtimer: Prevent stale expiry time in hrtimer_interrupt()
  ktime.h: Introduce ktime_ms_delta
parents 5b9b28a6 4ebbda52
...@@ -26,7 +26,7 @@ static int __init rtc_hctosys(void) ...@@ -26,7 +26,7 @@ static int __init rtc_hctosys(void)
{ {
int err = -ENODEV; int err = -ENODEV;
struct rtc_time tm; struct rtc_time tm;
struct timespec tv = { struct timespec64 tv64 = {
.tv_nsec = NSEC_PER_SEC >> 1, .tv_nsec = NSEC_PER_SEC >> 1,
}; };
struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
...@@ -45,25 +45,17 @@ static int __init rtc_hctosys(void) ...@@ -45,25 +45,17 @@ static int __init rtc_hctosys(void)
} }
err = rtc_valid_tm(&tm); tv64.tv_sec = rtc_tm_to_time64(&tm);
if (err) {
dev_err(rtc->dev.parent,
"hctosys: invalid date/time\n");
goto err_invalid;
}
rtc_tm_to_time(&tm, &tv.tv_sec);
err = do_settimeofday(&tv); err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent, dev_info(rtc->dev.parent,
"setting system clock to " "setting system clock to "
"%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", "%d-%02d-%02d %02d:%02d:%02d UTC (%lld)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_hour, tm.tm_min, tm.tm_sec,
(unsigned int) tv.tv_sec); (long long) tv64.tv_sec);
err_invalid:
err_read: err_read:
rtc_class_close(rtc); rtc_class_close(rtc);
......
...@@ -73,10 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) ...@@ -73,10 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
else if (rtc->ops->set_time) else if (rtc->ops->set_time)
err = rtc->ops->set_time(rtc->dev.parent, tm); err = rtc->ops->set_time(rtc->dev.parent, tm);
else if (rtc->ops->set_mmss) { else if (rtc->ops->set_mmss) {
unsigned long secs; time64_t secs64 = rtc_tm_to_time64(tm);
err = rtc_tm_to_time(tm, &secs); err = rtc->ops->set_mmss(rtc->dev.parent, secs64);
if (err == 0)
err = rtc->ops->set_mmss(rtc->dev.parent, secs);
} else } else
err = -EINVAL; err = -EINVAL;
...@@ -105,7 +103,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) ...@@ -105,7 +103,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
err = rtc->ops->read_time(rtc->dev.parent, &old); err = rtc->ops->read_time(rtc->dev.parent, &old);
if (err == 0) { if (err == 0) {
rtc_time_to_tm(secs, &new); rtc_time64_to_tm(secs, &new);
/* /*
* avoid writing when we're going to change the day of * avoid writing when we're going to change the day of
...@@ -157,7 +155,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) ...@@ -157,7 +155,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
int err; int err;
struct rtc_time before, now; struct rtc_time before, now;
int first_time = 1; int first_time = 1;
unsigned long t_now, t_alm; time64_t t_now, t_alm;
enum { none, day, month, year } missing = none; enum { none, day, month, year } missing = none;
unsigned days; unsigned days;
...@@ -258,8 +256,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) ...@@ -258,8 +256,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
} }
/* with luck, no rollover is needed */ /* with luck, no rollover is needed */
rtc_tm_to_time(&now, &t_now); t_now = rtc_tm_to_time64(&now);
rtc_tm_to_time(&alarm->time, &t_alm); t_alm = rtc_tm_to_time64(&alarm->time);
if (t_now < t_alm) if (t_now < t_alm)
goto done; goto done;
...@@ -273,7 +271,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) ...@@ -273,7 +271,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
case day: case day:
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day"); dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
t_alm += 24 * 60 * 60; t_alm += 24 * 60 * 60;
rtc_time_to_tm(t_alm, &alarm->time); rtc_time64_to_tm(t_alm, &alarm->time);
break; break;
/* Month rollover ... if it's the 31th, an alarm on the 3rd will /* Month rollover ... if it's the 31th, an alarm on the 3rd will
...@@ -346,19 +344,19 @@ EXPORT_SYMBOL_GPL(rtc_read_alarm); ...@@ -346,19 +344,19 @@ EXPORT_SYMBOL_GPL(rtc_read_alarm);
static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{ {
struct rtc_time tm; struct rtc_time tm;
long now, scheduled; time64_t now, scheduled;
int err; int err;
err = rtc_valid_tm(&alarm->time); err = rtc_valid_tm(&alarm->time);
if (err) if (err)
return err; return err;
rtc_tm_to_time(&alarm->time, &scheduled); scheduled = rtc_tm_to_time64(&alarm->time);
/* Make sure we're not setting alarms in the past */ /* Make sure we're not setting alarms in the past */
err = __rtc_read_time(rtc, &tm); err = __rtc_read_time(rtc, &tm);
if (err) if (err)
return err; return err;
rtc_tm_to_time(&tm, &now); now = rtc_tm_to_time64(&tm);
if (scheduled <= now) if (scheduled <= now)
return -ETIME; return -ETIME;
/* /*
......
...@@ -304,12 +304,12 @@ static long rtc_dev_ioctl(struct file *file, ...@@ -304,12 +304,12 @@ static long rtc_dev_ioctl(struct file *file,
* Not supported here. * Not supported here.
*/ */
{ {
unsigned long now, then; time64_t now, then;
err = rtc_read_time(rtc, &tm); err = rtc_read_time(rtc, &tm);
if (err < 0) if (err < 0)
return err; return err;
rtc_tm_to_time(&tm, &now); now = rtc_tm_to_time64(&tm);
alarm.time.tm_mday = tm.tm_mday; alarm.time.tm_mday = tm.tm_mday;
alarm.time.tm_mon = tm.tm_mon; alarm.time.tm_mon = tm.tm_mon;
...@@ -317,11 +317,11 @@ static long rtc_dev_ioctl(struct file *file, ...@@ -317,11 +317,11 @@ static long rtc_dev_ioctl(struct file *file,
err = rtc_valid_tm(&alarm.time); err = rtc_valid_tm(&alarm.time);
if (err < 0) if (err < 0)
return err; return err;
rtc_tm_to_time(&alarm.time, &then); then = rtc_tm_to_time64(&alarm.time);
/* alarm may need to wrap into tomorrow */ /* alarm may need to wrap into tomorrow */
if (then < now) { if (then < now) {
rtc_time_to_tm(now + 24 * 60 * 60, &tm); rtc_time64_to_tm(now + 24 * 60 * 60, &tm);
alarm.time.tm_mday = tm.tm_mday; alarm.time.tm_mday = tm.tm_mday;
alarm.time.tm_mon = tm.tm_mon; alarm.time.tm_mon = tm.tm_mon;
alarm.time.tm_year = tm.tm_year; alarm.time.tm_year = tm.tm_year;
......
...@@ -20,16 +20,16 @@ ...@@ -20,16 +20,16 @@
* *
* If temporary failure is indicated the caller should try again 'soon' * If temporary failure is indicated the caller should try again 'soon'
*/ */
int rtc_set_ntp_time(struct timespec now) int rtc_set_ntp_time(struct timespec64 now)
{ {
struct rtc_device *rtc; struct rtc_device *rtc;
struct rtc_time tm; struct rtc_time tm;
int err = -ENODEV; int err = -ENODEV;
if (now.tv_nsec < (NSEC_PER_SEC >> 1)) if (now.tv_nsec < (NSEC_PER_SEC >> 1))
rtc_time_to_tm(now.tv_sec, &tm); rtc_time64_to_tm(now.tv_sec, &tm);
else else
rtc_time_to_tm(now.tv_sec + 1, &tm); rtc_time64_to_tm(now.tv_sec + 1, &tm);
rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
if (rtc) { if (rtc) {
......
...@@ -170,6 +170,7 @@ enum hrtimer_base_type { ...@@ -170,6 +170,7 @@ enum hrtimer_base_type {
* @clock_was_set: Indicates that clock was set from irq context. * @clock_was_set: Indicates that clock was set from irq context.
* @expires_next: absolute time of the next event which was scheduled * @expires_next: absolute time of the next event which was scheduled
* via clock_set_next_event() * via clock_set_next_event()
* @in_hrtirq: hrtimer_interrupt() is currently executing
* @hres_active: State of high resolution mode * @hres_active: State of high resolution mode
* @hang_detected: The last hrtimer interrupt detected a hang * @hang_detected: The last hrtimer interrupt detected a hang
* @nr_events: Total number of hrtimer interrupt events * @nr_events: Total number of hrtimer interrupt events
...@@ -185,6 +186,7 @@ struct hrtimer_cpu_base { ...@@ -185,6 +186,7 @@ struct hrtimer_cpu_base {
unsigned int clock_was_set; unsigned int clock_was_set;
#ifdef CONFIG_HIGH_RES_TIMERS #ifdef CONFIG_HIGH_RES_TIMERS
ktime_t expires_next; ktime_t expires_next;
int in_hrtirq;
int hres_active; int hres_active;
int hang_detected; int hang_detected;
unsigned long nr_events; unsigned long nr_events;
......
...@@ -166,7 +166,17 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2) ...@@ -166,7 +166,17 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
} }
#if BITS_PER_LONG < 64 #if BITS_PER_LONG < 64
extern u64 ktime_divns(const ktime_t kt, s64 div); extern u64 __ktime_divns(const ktime_t kt, s64 div);
static inline u64 ktime_divns(const ktime_t kt, s64 div)
{
if (__builtin_constant_p(div) && !(div >> 32)) {
u64 ns = kt.tv64;
do_div(ns, div);
return ns;
} else {
return __ktime_divns(kt, div);
}
}
#else /* BITS_PER_LONG < 64 */ #else /* BITS_PER_LONG < 64 */
# define ktime_divns(kt, div) (u64)((kt).tv64 / (div)) # define ktime_divns(kt, div) (u64)((kt).tv64 / (div))
#endif #endif
...@@ -186,6 +196,11 @@ static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) ...@@ -186,6 +196,11 @@ static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
return ktime_to_us(ktime_sub(later, earlier)); return ktime_to_us(ktime_sub(later, earlier));
} }
static inline s64 ktime_ms_delta(const ktime_t later, const ktime_t earlier)
{
return ktime_to_ms(ktime_sub(later, earlier));
}
static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec) static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
{ {
return ktime_add_ns(kt, usec * NSEC_PER_USEC); return ktime_add_ns(kt, usec * NSEC_PER_USEC);
......
...@@ -161,7 +161,7 @@ extern void devm_rtc_device_unregister(struct device *dev, ...@@ -161,7 +161,7 @@ extern void devm_rtc_device_unregister(struct device *dev,
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm); extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm); extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs); extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs);
extern int rtc_set_ntp_time(struct timespec now); extern int rtc_set_ntp_time(struct timespec64 now);
int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm); int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
extern int rtc_read_alarm(struct rtc_device *rtc, extern int rtc_read_alarm(struct rtc_device *rtc,
struct rtc_wkalrm *alrm); struct rtc_wkalrm *alrm);
......
...@@ -33,6 +33,7 @@ extern time64_t ktime_get_real_seconds(void); ...@@ -33,6 +33,7 @@ extern time64_t ktime_get_real_seconds(void);
extern int __getnstimeofday64(struct timespec64 *tv); extern int __getnstimeofday64(struct timespec64 *tv);
extern void getnstimeofday64(struct timespec64 *tv); extern void getnstimeofday64(struct timespec64 *tv);
extern void getboottime64(struct timespec64 *ts);
#if BITS_PER_LONG == 64 #if BITS_PER_LONG == 64
/** /**
...@@ -72,6 +73,11 @@ static inline struct timespec get_monotonic_coarse(void) ...@@ -72,6 +73,11 @@ static inline struct timespec get_monotonic_coarse(void)
{ {
return get_monotonic_coarse64(); return get_monotonic_coarse64();
} }
static inline void getboottime(struct timespec *ts)
{
return getboottime64(ts);
}
#else #else
/** /**
* Deprecated. Use do_settimeofday64(). * Deprecated. Use do_settimeofday64().
...@@ -129,9 +135,15 @@ static inline struct timespec get_monotonic_coarse(void) ...@@ -129,9 +135,15 @@ static inline struct timespec get_monotonic_coarse(void)
{ {
return timespec64_to_timespec(get_monotonic_coarse64()); return timespec64_to_timespec(get_monotonic_coarse64());
} }
#endif
extern void getboottime(struct timespec *ts); static inline void getboottime(struct timespec *ts)
{
struct timespec64 ts64;
getboottime64(&ts64);
*ts = timespec64_to_timespec(ts64);
}
#endif
#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
#define ktime_get_real_ts64(ts) getnstimeofday64(ts) #define ktime_get_real_ts64(ts) getnstimeofday64(ts)
...@@ -217,6 +229,11 @@ static inline void get_monotonic_boottime(struct timespec *ts) ...@@ -217,6 +229,11 @@ static inline void get_monotonic_boottime(struct timespec *ts)
*ts = ktime_to_timespec(ktime_get_boottime()); *ts = ktime_to_timespec(ktime_get_boottime());
} }
static inline void get_monotonic_boottime64(struct timespec64 *ts)
{
*ts = ktime_to_timespec64(ktime_get_boottime());
}
static inline void timekeeping_clocktai(struct timespec *ts) static inline void timekeeping_clocktai(struct timespec *ts)
{ {
*ts = ktime_to_timespec(ktime_get_clocktai()); *ts = ktime_to_timespec(ktime_get_clocktai());
......
...@@ -266,7 +266,7 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) ...@@ -266,7 +266,7 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
/* /*
* Divide a ktime value by a nanosecond value * Divide a ktime value by a nanosecond value
*/ */
u64 ktime_divns(const ktime_t kt, s64 div) u64 __ktime_divns(const ktime_t kt, s64 div)
{ {
u64 dclc; u64 dclc;
int sft = 0; int sft = 0;
...@@ -282,7 +282,7 @@ u64 ktime_divns(const ktime_t kt, s64 div) ...@@ -282,7 +282,7 @@ u64 ktime_divns(const ktime_t kt, s64 div)
return dclc; return dclc;
} }
EXPORT_SYMBOL_GPL(ktime_divns); EXPORT_SYMBOL_GPL(__ktime_divns);
#endif /* BITS_PER_LONG >= 64 */ #endif /* BITS_PER_LONG >= 64 */
/* /*
...@@ -440,6 +440,37 @@ static inline void debug_deactivate(struct hrtimer *timer) ...@@ -440,6 +440,37 @@ static inline void debug_deactivate(struct hrtimer *timer)
trace_hrtimer_cancel(timer); trace_hrtimer_cancel(timer);
} }
#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
{
struct hrtimer_clock_base *base = cpu_base->clock_base;
ktime_t expires, expires_next = { .tv64 = KTIME_MAX };
int i;
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
struct timerqueue_node *next;
struct hrtimer *timer;
next = timerqueue_getnext(&base->active);
if (!next)
continue;
timer = container_of(next, struct hrtimer, node);
expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
if (expires.tv64 < expires_next.tv64)
expires_next = expires;
}
/*
* clock_was_set() might have changed base->offset of any of
* the clock bases so the result might be negative. Fix it up
* to prevent a false positive in clockevents_program_event().
*/
if (expires_next.tv64 < 0)
expires_next.tv64 = 0;
return expires_next;
}
#endif
/* High resolution timer related functions */ /* High resolution timer related functions */
#ifdef CONFIG_HIGH_RES_TIMERS #ifdef CONFIG_HIGH_RES_TIMERS
...@@ -488,32 +519,7 @@ static inline int hrtimer_hres_active(void) ...@@ -488,32 +519,7 @@ static inline int hrtimer_hres_active(void)
static void static void
hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
{ {
int i; ktime_t expires_next = __hrtimer_get_next_event(cpu_base);
struct hrtimer_clock_base *base = cpu_base->clock_base;
ktime_t expires, expires_next;
expires_next.tv64 = KTIME_MAX;
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
struct hrtimer *timer;
struct timerqueue_node *next;
next = timerqueue_getnext(&base->active);
if (!next)
continue;
timer = container_of(next, struct hrtimer, node);
expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
/*
* clock_was_set() has changed base->offset so the
* result might be negative. Fix it up to prevent a
* false positive in clockevents_program_event()
*/
if (expires.tv64 < 0)
expires.tv64 = 0;
if (expires.tv64 < expires_next.tv64)
expires_next = expires;
}
if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64) if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64)
return; return;
...@@ -586,6 +592,15 @@ static int hrtimer_reprogram(struct hrtimer *timer, ...@@ -586,6 +592,15 @@ static int hrtimer_reprogram(struct hrtimer *timer,
if (expires.tv64 >= cpu_base->expires_next.tv64) if (expires.tv64 >= cpu_base->expires_next.tv64)
return 0; return 0;
/*
* When the target cpu of the timer is currently executing
* hrtimer_interrupt(), then we do not touch the clock event
* device. hrtimer_interrupt() will reevaluate all clock bases
* before reprogramming the device.
*/
if (cpu_base->in_hrtirq)
return 0;
/* /*
* If a hang was detected in the last timer interrupt then we * If a hang was detected in the last timer interrupt then we
* do not schedule a timer which is earlier than the expiry * do not schedule a timer which is earlier than the expiry
...@@ -1104,29 +1119,14 @@ EXPORT_SYMBOL_GPL(hrtimer_get_remaining); ...@@ -1104,29 +1119,14 @@ EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
ktime_t hrtimer_get_next_event(void) ktime_t hrtimer_get_next_event(void)
{ {
struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases); struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
struct hrtimer_clock_base *base = cpu_base->clock_base; ktime_t mindelta = { .tv64 = KTIME_MAX };
ktime_t delta, mindelta = { .tv64 = KTIME_MAX };
unsigned long flags; unsigned long flags;
int i;
raw_spin_lock_irqsave(&cpu_base->lock, flags); raw_spin_lock_irqsave(&cpu_base->lock, flags);
if (!hrtimer_hres_active()) { if (!hrtimer_hres_active())
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) { mindelta = ktime_sub(__hrtimer_get_next_event(cpu_base),
struct hrtimer *timer; ktime_get());
struct timerqueue_node *next;
next = timerqueue_getnext(&base->active);
if (!next)
continue;
timer = container_of(next, struct hrtimer, node);
delta.tv64 = hrtimer_get_expires_tv64(timer);
delta = ktime_sub(delta, base->get_time());
if (delta.tv64 < mindelta.tv64)
mindelta.tv64 = delta.tv64;
}
}
raw_spin_unlock_irqrestore(&cpu_base->lock, flags); raw_spin_unlock_irqrestore(&cpu_base->lock, flags);
...@@ -1253,7 +1253,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) ...@@ -1253,7 +1253,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
raw_spin_lock(&cpu_base->lock); raw_spin_lock(&cpu_base->lock);
entry_time = now = hrtimer_update_base(cpu_base); entry_time = now = hrtimer_update_base(cpu_base);
retry: retry:
expires_next.tv64 = KTIME_MAX; cpu_base->in_hrtirq = 1;
/* /*
* We set expires_next to KTIME_MAX here with cpu_base->lock * We set expires_next to KTIME_MAX here with cpu_base->lock
* held to prevent that a timer is enqueued in our queue via * held to prevent that a timer is enqueued in our queue via
...@@ -1291,28 +1291,20 @@ void hrtimer_interrupt(struct clock_event_device *dev) ...@@ -1291,28 +1291,20 @@ void hrtimer_interrupt(struct clock_event_device *dev)
* are right-of a not yet expired timer, because that * are right-of a not yet expired timer, because that
* timer will have to trigger a wakeup anyway. * timer will have to trigger a wakeup anyway.
*/ */
if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))
if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
ktime_t expires;
expires = ktime_sub(hrtimer_get_expires(timer),
base->offset);
if (expires.tv64 < 0)
expires.tv64 = KTIME_MAX;
if (expires.tv64 < expires_next.tv64)
expires_next = expires;
break; break;
}
__run_hrtimer(timer, &basenow); __run_hrtimer(timer, &basenow);
} }
} }
/* Reevaluate the clock bases for the next expiry */
expires_next = __hrtimer_get_next_event(cpu_base);
/* /*
* Store the new expiry value so the migration code can verify * Store the new expiry value so the migration code can verify
* against it. * against it.
*/ */
cpu_base->expires_next = expires_next; cpu_base->expires_next = expires_next;
cpu_base->in_hrtirq = 0;
raw_spin_unlock(&cpu_base->lock); raw_spin_unlock(&cpu_base->lock);
/* Reprogramming necessary ? */ /* Reprogramming necessary ? */
......
...@@ -488,13 +488,13 @@ static void sync_cmos_clock(struct work_struct *work) ...@@ -488,13 +488,13 @@ static void sync_cmos_clock(struct work_struct *work)
getnstimeofday64(&now); getnstimeofday64(&now);
if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) { if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) {
struct timespec adjust = timespec64_to_timespec(now); struct timespec64 adjust = now;
fail = -ENODEV; fail = -ENODEV;
if (persistent_clock_is_local) if (persistent_clock_is_local)
adjust.tv_sec -= (sys_tz.tz_minuteswest * 60); adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
#ifdef CONFIG_GENERIC_CMOS_UPDATE #ifdef CONFIG_GENERIC_CMOS_UPDATE
fail = update_persistent_clock(adjust); fail = update_persistent_clock(timespec64_to_timespec(adjust));
#endif #endif
#ifdef CONFIG_RTC_SYSTOHC #ifdef CONFIG_RTC_SYSTOHC
if (fail == -ENODEV) if (fail == -ENODEV)
......
...@@ -1659,24 +1659,24 @@ void update_wall_time(void) ...@@ -1659,24 +1659,24 @@ void update_wall_time(void)
} }
/** /**
* getboottime - Return the real time of system boot. * getboottime64 - Return the real time of system boot.
* @ts: pointer to the timespec to be set * @ts: pointer to the timespec64 to be set
* *
* Returns the wall-time of boot in a timespec. * Returns the wall-time of boot in a timespec64.
* *
* This is based on the wall_to_monotonic offset and the total suspend * This is based on the wall_to_monotonic offset and the total suspend
* time. Calls to settimeofday will affect the value returned (which * time. Calls to settimeofday will affect the value returned (which
* basically means that however wrong your real time clock is at boot time, * basically means that however wrong your real time clock is at boot time,
* you get the right time here). * you get the right time here).
*/ */
void getboottime(struct timespec *ts) void getboottime64(struct timespec64 *ts)
{ {
struct timekeeper *tk = &tk_core.timekeeper; struct timekeeper *tk = &tk_core.timekeeper;
ktime_t t = ktime_sub(tk->offs_real, tk->offs_boot); ktime_t t = ktime_sub(tk->offs_real, tk->offs_boot);
*ts = ktime_to_timespec(t); *ts = ktime_to_timespec64(t);
} }
EXPORT_SYMBOL_GPL(getboottime); EXPORT_SYMBOL_GPL(getboottime64);
unsigned long get_seconds(void) unsigned long get_seconds(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment