Skip to content

Commit

Permalink
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed Feb 10, 2015
2 parents 5b9b28a + 4ebbda5 commit 0ba97bc
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 104 deletions.
18 changes: 5 additions & 13 deletions drivers/rtc/hctosys.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static int __init rtc_hctosys(void)
{
int err = -ENODEV;
struct rtc_time tm;
struct timespec tv = {
struct timespec64 tv64 = {
.tv_nsec = NSEC_PER_SEC >> 1,
};
struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
Expand All @@ -45,25 +45,17 @@ static int __init rtc_hctosys(void)

}

err = rtc_valid_tm(&tm);
if (err) {
dev_err(rtc->dev.parent,
"hctosys: invalid date/time\n");
goto err_invalid;
}

rtc_tm_to_time(&tm, &tv.tv_sec);
tv64.tv_sec = rtc_tm_to_time64(&tm);

err = do_settimeofday(&tv);
err = do_settimeofday64(&tv64);

dev_info(rtc->dev.parent,
"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_hour, tm.tm_min, tm.tm_sec,
(unsigned int) tv.tv_sec);
(long long) tv64.tv_sec);

err_invalid:
err_read:
rtc_class_close(rtc);

Expand Down
22 changes: 10 additions & 12 deletions drivers/rtc/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
else if (rtc->ops->set_time)
err = rtc->ops->set_time(rtc->dev.parent, tm);
else if (rtc->ops->set_mmss) {
unsigned long secs;
err = rtc_tm_to_time(tm, &secs);
if (err == 0)
err = rtc->ops->set_mmss(rtc->dev.parent, secs);
time64_t secs64 = rtc_tm_to_time64(tm);
err = rtc->ops->set_mmss(rtc->dev.parent, secs64);
} else
err = -EINVAL;

Expand Down Expand Up @@ -105,7 +103,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)

err = rtc->ops->read_time(rtc->dev.parent, &old);
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
Expand Down Expand Up @@ -157,7 +155,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
int err;
struct rtc_time before, now;
int first_time = 1;
unsigned long t_now, t_alm;
time64_t t_now, t_alm;
enum { none, day, month, year } missing = none;
unsigned days;

Expand Down Expand Up @@ -258,8 +256,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}

/* with luck, no rollover is needed */
rtc_tm_to_time(&now, &t_now);
rtc_tm_to_time(&alarm->time, &t_alm);
t_now = rtc_tm_to_time64(&now);
t_alm = rtc_tm_to_time64(&alarm->time);
if (t_now < t_alm)
goto done;

Expand All @@ -273,7 +271,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
case day:
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
t_alm += 24 * 60 * 60;
rtc_time_to_tm(t_alm, &alarm->time);
rtc_time64_to_tm(t_alm, &alarm->time);
break;

/* Month rollover ... if it's the 31th, an alarm on the 3rd will
Expand Down Expand Up @@ -346,19 +344,19 @@ EXPORT_SYMBOL_GPL(rtc_read_alarm);
static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
struct rtc_time tm;
long now, scheduled;
time64_t now, scheduled;
int err;

err = rtc_valid_tm(&alarm->time);
if (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 */
err = __rtc_read_time(rtc, &tm);
if (err)
return err;
rtc_tm_to_time(&tm, &now);
now = rtc_tm_to_time64(&tm);
if (scheduled <= now)
return -ETIME;
/*
Expand Down
8 changes: 4 additions & 4 deletions drivers/rtc/rtc-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,24 +304,24 @@ static long rtc_dev_ioctl(struct file *file,
* Not supported here.
*/
{
unsigned long now, then;
time64_t now, then;

err = rtc_read_time(rtc, &tm);
if (err < 0)
return err;
rtc_tm_to_time(&tm, &now);
now = rtc_tm_to_time64(&tm);

alarm.time.tm_mday = tm.tm_mday;
alarm.time.tm_mon = tm.tm_mon;
alarm.time.tm_year = tm.tm_year;
err = rtc_valid_tm(&alarm.time);
if (err < 0)
return err;
rtc_tm_to_time(&alarm.time, &then);
then = rtc_tm_to_time64(&alarm.time);

/* alarm may need to wrap into tomorrow */
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_mon = tm.tm_mon;
alarm.time.tm_year = tm.tm_year;
Expand Down
6 changes: 3 additions & 3 deletions drivers/rtc/systohc.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
*
* 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_time tm;
int err = -ENODEV;

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
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);
if (rtc) {
Expand Down
2 changes: 2 additions & 0 deletions include/linux/hrtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ enum hrtimer_base_type {
* @clock_was_set: Indicates that clock was set from irq context.
* @expires_next: absolute time of the next event which was scheduled
* via clock_set_next_event()
* @in_hrtirq: hrtimer_interrupt() is currently executing
* @hres_active: State of high resolution mode
* @hang_detected: The last hrtimer interrupt detected a hang
* @nr_events: Total number of hrtimer interrupt events
Expand All @@ -185,6 +186,7 @@ struct hrtimer_cpu_base {
unsigned int clock_was_set;
#ifdef CONFIG_HIGH_RES_TIMERS
ktime_t expires_next;
int in_hrtirq;
int hres_active;
int hang_detected;
unsigned long nr_events;
Expand Down
17 changes: 16 additions & 1 deletion include/linux/ktime.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,17 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
}

#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 */
# define ktime_divns(kt, div) (u64)((kt).tv64 / (div))
#endif
Expand All @@ -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));
}

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)
{
return ktime_add_ns(kt, usec * NSEC_PER_USEC);
Expand Down
2 changes: 1 addition & 1 deletion include/linux/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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);
extern int rtc_read_alarm(struct rtc_device *rtc,
struct rtc_wkalrm *alrm);
Expand Down
21 changes: 19 additions & 2 deletions include/linux/timekeeping.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern time64_t ktime_get_real_seconds(void);

extern int __getnstimeofday64(struct timespec64 *tv);
extern void getnstimeofday64(struct timespec64 *tv);
extern void getboottime64(struct timespec64 *ts);

#if BITS_PER_LONG == 64
/**
Expand Down Expand Up @@ -72,6 +73,11 @@ static inline struct timespec get_monotonic_coarse(void)
{
return get_monotonic_coarse64();
}

static inline void getboottime(struct timespec *ts)
{
return getboottime64(ts);
}
#else
/**
* Deprecated. Use do_settimeofday64().
Expand Down Expand Up @@ -129,9 +135,15 @@ static inline struct timespec get_monotonic_coarse(void)
{
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 ktime_get_real_ts64(ts) getnstimeofday64(ts)
Expand Down Expand Up @@ -217,6 +229,11 @@ static inline void get_monotonic_boottime(struct timespec *ts)
*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)
{
*ts = ktime_to_timespec(ktime_get_clocktai());
Expand Down
Loading

0 comments on commit 0ba97bc

Please sign in to comment.