mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-01 12:04:08 +00:00
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
This commit is contained in:
commit
0ba97bc4b4
11 changed files with 120 additions and 104 deletions
|
@ -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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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_settimeofday64(&tv64);
|
||||||
|
|
||||||
err = do_settimeofday(&tv);
|
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
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);
|
||||||
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,
|
||||||
* 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,
|
||||||
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 @@
|
||||||
*
|
*
|
||||||
* 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 {
|
||||||
* @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 {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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)
|
||||||
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,
|
||||||
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);
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
*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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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);
|
||||||
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)
|
||||||
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 @@ retry:
|
||||||
* 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)
|
||||||
|
|
||||||
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 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue