Commit 680014d6 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 time(r) updates from Thomas Gleixner:
 "A small set of updates for timers and timekeeping:

   - The most interesting change is the consolidation of clock MONOTONIC
     and clock BOOTTIME.

     Clock MONOTONIC behaves now exactly like clock BOOTTIME and does
     not longer ignore the time spent in suspend. A new clock
     MONOTONIC_ACTIVE is provived which behaves like clock MONOTONIC in
     kernels before this change. This allows applications to
     programmatically check for the clock MONOTONIC behaviour.

     As discussed in the review thread, this has the potential of
     breaking user space and we might have to revert this. Knock on wood
     that we can avoid that exercise.

   - Updates to the NTP mechanism to improve accuracy

   - A new kernel internal data structure to aid the ongoing Y2038 work.

   - Cleanups and simplifications of the clocksource code.

   - Make the alarmtimer code play nicely with debugobjects"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  alarmtimer: Init nanosleep alarm timer on stack
  y2038: Introduce struct __kernel_old_timeval
  tracing: Unify the "boot" and "mono" tracing clocks
  hrtimer: Unify MONOTONIC and BOOTTIME clock behavior
  posix-timers: Unify MONOTONIC and BOOTTIME clock behavior
  timekeeping: Remove boot time specific code
  Input: Evdev - unify MONOTONIC and BOOTTIME clock behavior
  timekeeping: Make the MONOTONIC clock behave like the BOOTTIME clock
  timekeeping: Add the new CLOCK_MONOTONIC_ACTIVE clock
  timekeeping/ntp: Determine the multiplier directly from NTP tick length
  timekeeping/ntp: Don't align NTP frequency adjustments to ticks
  clocksource: Use ATTRIBUTE_GROUPS
  clocksource: Use DEVICE_ATTR_RW/RO/WO to define device attributes
  clocksource: Don't walk the clocksource list for empty override
parents 0c21fd6e bd031430
...@@ -461,21 +461,13 @@ of ftrace. Here is a list of some of the key files: ...@@ -461,21 +461,13 @@ of ftrace. Here is a list of some of the key files:
and ticks at the same rate as the hardware clocksource. and ticks at the same rate as the hardware clocksource.
boot: boot:
This is the boot clock (CLOCK_BOOTTIME) and is based on the Same as mono. Used to be a separate clock which accounted
fast monotonic clock, but also accounts for time spent in for the time spent in suspend while CLOCK_MONOTONIC did
suspend. Since the clock access is designed for use in not.
tracing in the suspend path, some side effects are possible
if clock is accessed after the suspend time is accounted before To set a clock, simply echo the clock name into this file::
the fast mono clock is updated. In this case, the clock update
appears to happen slightly sooner than it normally would have. # echo global > trace_clock
Also on 32-bit systems, it's possible that the 64-bit boot offset
sees a partial update. These effects are rare and post
processing should be able to handle them. See comments in the
ktime_get_boot_fast_ns() function for more information.
To set a clock, simply echo the clock name into this file::
echo global > trace_clock
trace_marker: trace_marker:
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
enum evdev_clock_type { enum evdev_clock_type {
EV_CLK_REAL = 0, EV_CLK_REAL = 0,
EV_CLK_MONO, EV_CLK_MONO,
EV_CLK_BOOT,
EV_CLK_MAX EV_CLK_MAX
}; };
...@@ -198,12 +197,10 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) ...@@ -198,12 +197,10 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
case CLOCK_REALTIME: case CLOCK_REALTIME:
clk_type = EV_CLK_REAL; clk_type = EV_CLK_REAL;
break; break;
case CLOCK_BOOTTIME:
case CLOCK_MONOTONIC: case CLOCK_MONOTONIC:
clk_type = EV_CLK_MONO; clk_type = EV_CLK_MONO;
break; break;
case CLOCK_BOOTTIME:
clk_type = EV_CLK_BOOT;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -314,8 +311,6 @@ static void evdev_events(struct input_handle *handle, ...@@ -314,8 +311,6 @@ static void evdev_events(struct input_handle *handle,
ev_time[EV_CLK_MONO] = ktime_get(); ev_time[EV_CLK_MONO] = ktime_get();
ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
TK_OFFS_BOOT);
rcu_read_lock(); rcu_read_lock();
......
...@@ -161,11 +161,9 @@ struct hrtimer_clock_base { ...@@ -161,11 +161,9 @@ struct hrtimer_clock_base {
enum hrtimer_base_type { enum hrtimer_base_type {
HRTIMER_BASE_MONOTONIC, HRTIMER_BASE_MONOTONIC,
HRTIMER_BASE_REALTIME, HRTIMER_BASE_REALTIME,
HRTIMER_BASE_BOOTTIME,
HRTIMER_BASE_TAI, HRTIMER_BASE_TAI,
HRTIMER_BASE_MONOTONIC_SOFT, HRTIMER_BASE_MONOTONIC_SOFT,
HRTIMER_BASE_REALTIME_SOFT, HRTIMER_BASE_REALTIME_SOFT,
HRTIMER_BASE_BOOTTIME_SOFT,
HRTIMER_BASE_TAI_SOFT, HRTIMER_BASE_TAI_SOFT,
HRTIMER_MAX_CLOCK_BASES, HRTIMER_MAX_CLOCK_BASES,
}; };
......
...@@ -217,5 +217,6 @@ static inline s64 timeval_to_ns(const struct timeval *tv) ...@@ -217,5 +217,6 @@ static inline s64 timeval_to_ns(const struct timeval *tv)
* Returns the timeval representation of the nsec parameter. * Returns the timeval representation of the nsec parameter.
*/ */
extern struct timeval ns_to_timeval(const s64 nsec); extern struct timeval ns_to_timeval(const s64 nsec);
extern struct __kernel_old_timeval ns_to_kernel_old_timeval(s64 nsec);
#endif #endif
...@@ -52,6 +52,7 @@ struct tk_read_base { ...@@ -52,6 +52,7 @@ struct tk_read_base {
* @offs_real: Offset clock monotonic -> clock realtime * @offs_real: Offset clock monotonic -> clock realtime
* @offs_boot: Offset clock monotonic -> clock boottime * @offs_boot: Offset clock monotonic -> clock boottime
* @offs_tai: Offset clock monotonic -> clock tai * @offs_tai: Offset clock monotonic -> clock tai
* @time_suspended: Accumulated suspend time
* @tai_offset: The current UTC to TAI offset in seconds * @tai_offset: The current UTC to TAI offset in seconds
* @clock_was_set_seq: The sequence number of clock was set events * @clock_was_set_seq: The sequence number of clock was set events
* @cs_was_changed_seq: The sequence number of clocksource change events * @cs_was_changed_seq: The sequence number of clocksource change events
...@@ -94,6 +95,7 @@ struct timekeeper { ...@@ -94,6 +95,7 @@ struct timekeeper {
ktime_t offs_real; ktime_t offs_real;
ktime_t offs_boot; ktime_t offs_boot;
ktime_t offs_tai; ktime_t offs_tai;
ktime_t time_suspended;
s32 tai_offset; s32 tai_offset;
unsigned int clock_was_set_seq; unsigned int clock_was_set_seq;
u8 cs_was_changed_seq; u8 cs_was_changed_seq;
...@@ -117,6 +119,8 @@ struct timekeeper { ...@@ -117,6 +119,8 @@ struct timekeeper {
s64 ntp_error; s64 ntp_error;
u32 ntp_error_shift; u32 ntp_error_shift;
u32 ntp_err_mult; u32 ntp_err_mult;
/* Flag used to avoid updating NTP twice with same second */
u32 skip_second_overflow;
#ifdef CONFIG_DEBUG_TIMEKEEPING #ifdef CONFIG_DEBUG_TIMEKEEPING
long last_warning; long last_warning;
/* /*
......
...@@ -32,20 +32,25 @@ extern void getrawmonotonic64(struct timespec64 *ts); ...@@ -32,20 +32,25 @@ extern void getrawmonotonic64(struct timespec64 *ts);
extern void ktime_get_ts64(struct timespec64 *ts); extern void ktime_get_ts64(struct timespec64 *ts);
extern time64_t ktime_get_seconds(void); extern time64_t ktime_get_seconds(void);
extern time64_t ktime_get_real_seconds(void); extern time64_t ktime_get_real_seconds(void);
extern void ktime_get_active_ts64(struct timespec64 *ts);
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); extern void getboottime64(struct timespec64 *ts);
#define ktime_get_real_ts64(ts) getnstimeofday64(ts) #define ktime_get_real_ts64(ts) getnstimeofday64(ts)
/* Clock BOOTTIME compatibility wrappers */
static inline void get_monotonic_boottime64(struct timespec64 *ts)
{
ktime_get_ts64(ts);
}
/* /*
* ktime_t based interfaces * ktime_t based interfaces
*/ */
enum tk_offsets { enum tk_offsets {
TK_OFFS_REAL, TK_OFFS_REAL,
TK_OFFS_BOOT,
TK_OFFS_TAI, TK_OFFS_TAI,
TK_OFFS_MAX, TK_OFFS_MAX,
}; };
...@@ -56,6 +61,10 @@ extern ktime_t ktime_mono_to_any(ktime_t tmono, enum tk_offsets offs); ...@@ -56,6 +61,10 @@ extern ktime_t ktime_mono_to_any(ktime_t tmono, enum tk_offsets offs);
extern ktime_t ktime_get_raw(void); extern ktime_t ktime_get_raw(void);
extern u32 ktime_get_resolution_ns(void); extern u32 ktime_get_resolution_ns(void);
/* Clock BOOTTIME compatibility wrappers */
static inline ktime_t ktime_get_boottime(void) { return ktime_get(); }
static inline u64 ktime_get_boot_ns(void) { return ktime_get(); }
/** /**
* ktime_get_real - get the real (wall-) time in ktime_t format * ktime_get_real - get the real (wall-) time in ktime_t format
*/ */
...@@ -64,17 +73,6 @@ static inline ktime_t ktime_get_real(void) ...@@ -64,17 +73,6 @@ static inline ktime_t ktime_get_real(void)
return ktime_get_with_offset(TK_OFFS_REAL); return ktime_get_with_offset(TK_OFFS_REAL);
} }
/**
* ktime_get_boottime - Returns monotonic time since boot in ktime_t format
*
* This is similar to CLOCK_MONTONIC/ktime_get, but also includes the
* time spent in suspend.
*/
static inline ktime_t ktime_get_boottime(void)
{
return ktime_get_with_offset(TK_OFFS_BOOT);
}
/** /**
* ktime_get_clocktai - Returns the TAI time of day in ktime_t format * ktime_get_clocktai - Returns the TAI time of day in ktime_t format
*/ */
...@@ -101,11 +99,6 @@ static inline u64 ktime_get_real_ns(void) ...@@ -101,11 +99,6 @@ static inline u64 ktime_get_real_ns(void)
return ktime_to_ns(ktime_get_real()); return ktime_to_ns(ktime_get_real());
} }
static inline u64 ktime_get_boot_ns(void)
{
return ktime_to_ns(ktime_get_boottime());
}
static inline u64 ktime_get_tai_ns(void) static inline u64 ktime_get_tai_ns(void)
{ {
return ktime_to_ns(ktime_get_clocktai()); return ktime_to_ns(ktime_get_clocktai());
...@@ -118,17 +111,11 @@ static inline u64 ktime_get_raw_ns(void) ...@@ -118,17 +111,11 @@ static inline u64 ktime_get_raw_ns(void)
extern u64 ktime_get_mono_fast_ns(void); extern u64 ktime_get_mono_fast_ns(void);
extern u64 ktime_get_raw_fast_ns(void); extern u64 ktime_get_raw_fast_ns(void);
extern u64 ktime_get_boot_fast_ns(void);
extern u64 ktime_get_real_fast_ns(void); extern u64 ktime_get_real_fast_ns(void);
/* /*
* timespec64 interfaces utilizing the ktime based ones * timespec64 interfaces utilizing the ktime based ones
*/ */
static inline void get_monotonic_boottime64(struct timespec64 *ts)
{
*ts = ktime_to_timespec64(ktime_get_boottime());
}
static inline void timekeeping_clocktai64(struct timespec64 *ts) static inline void timekeeping_clocktai64(struct timespec64 *ts)
{ {
*ts = ktime_to_timespec64(ktime_get_clocktai()); *ts = ktime_to_timespec64(ktime_get_clocktai());
......
...@@ -42,6 +42,18 @@ struct itimerval { ...@@ -42,6 +42,18 @@ struct itimerval {
struct timeval it_value; /* current value */ struct timeval it_value; /* current value */
}; };
/*
* legacy timeval structure, only embedded in structures that
* traditionally used 'timeval' to pass time intervals (not absolute
* times). Do not add new users. If user space fails to compile
* here, this is probably because it is not y2038 safe and needs to
* be changed to use another interface.
*/
struct __kernel_old_timeval {
__kernel_long_t tv_sec;
__kernel_long_t tv_usec;
};
/* /*
* The IDs of the various system clocks (for POSIX.1b interval timers): * The IDs of the various system clocks (for POSIX.1b interval timers):
*/ */
...@@ -61,6 +73,7 @@ struct itimerval { ...@@ -61,6 +73,7 @@ struct itimerval {
*/ */
#define CLOCK_SGI_CYCLE 10 #define CLOCK_SGI_CYCLE 10
#define CLOCK_TAI 11 #define CLOCK_TAI 11
#define CLOCK_MONOTONIC_ACTIVE 12
#define MAX_CLOCKS 16 #define MAX_CLOCKS 16
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC) #define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)
......
...@@ -326,6 +326,17 @@ static int alarmtimer_resume(struct device *dev) ...@@ -326,6 +326,17 @@ static int alarmtimer_resume(struct device *dev)
} }
#endif #endif
static void
__alarm_init(struct alarm *alarm, enum alarmtimer_type type,
enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
{
timerqueue_init(&alarm->node);
alarm->timer.function = alarmtimer_fired;
alarm->function = function;
alarm->type = type;
alarm->state = ALARMTIMER_STATE_INACTIVE;
}
/** /**
* alarm_init - Initialize an alarm structure * alarm_init - Initialize an alarm structure
* @alarm: ptr to alarm to be initialized * @alarm: ptr to alarm to be initialized
...@@ -335,13 +346,9 @@ static int alarmtimer_resume(struct device *dev) ...@@ -335,13 +346,9 @@ static int alarmtimer_resume(struct device *dev)
void alarm_init(struct alarm *alarm, enum alarmtimer_type type, void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
enum alarmtimer_restart (*function)(struct alarm *, ktime_t)) enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
{ {
timerqueue_init(&alarm->node);
hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid, hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
HRTIMER_MODE_ABS); HRTIMER_MODE_ABS);
alarm->timer.function = alarmtimer_fired; __alarm_init(alarm, type, function);
alarm->function = function;
alarm->type = type;
alarm->state = ALARMTIMER_STATE_INACTIVE;
} }
EXPORT_SYMBOL_GPL(alarm_init); EXPORT_SYMBOL_GPL(alarm_init);
...@@ -719,6 +726,8 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, ...@@ -719,6 +726,8 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
destroy_hrtimer_on_stack(&alarm->timer);
if (!alarm->data) if (!alarm->data)
return 0; return 0;
...@@ -740,6 +749,15 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, ...@@ -740,6 +749,15 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
return -ERESTART_RESTARTBLOCK; return -ERESTART_RESTARTBLOCK;
} }
static void
alarm_init_on_stack(struct alarm *alarm, enum alarmtimer_type type,
enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
{
hrtimer_init_on_stack(&alarm->timer, alarm_bases[type].base_clockid,
HRTIMER_MODE_ABS);
__alarm_init(alarm, type, function);
}
/** /**
* alarm_timer_nsleep_restart - restartblock alarmtimer nsleep * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
* @restart: ptr to restart block * @restart: ptr to restart block
...@@ -752,7 +770,7 @@ static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) ...@@ -752,7 +770,7 @@ static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
ktime_t exp = restart->nanosleep.expires; ktime_t exp = restart->nanosleep.expires;
struct alarm alarm; struct alarm alarm;
alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); alarm_init_on_stack(&alarm, type, alarmtimer_nsleep_wakeup);
return alarmtimer_do_nsleep(&alarm, exp, type); return alarmtimer_do_nsleep(&alarm, exp, type);
} }
...@@ -784,7 +802,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, ...@@ -784,7 +802,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
if (!capable(CAP_WAKE_ALARM)) if (!capable(CAP_WAKE_ALARM))
return -EPERM; return -EPERM;
alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); alarm_init_on_stack(&alarm, type, alarmtimer_nsleep_wakeup);
exp = timespec64_to_ktime(*tsreq); exp = timespec64_to_ktime(*tsreq);
/* Convert (if necessary) to absolute time */ /* Convert (if necessary) to absolute time */
......
...@@ -594,6 +594,9 @@ static void __clocksource_select(bool skipcur) ...@@ -594,6 +594,9 @@ static void __clocksource_select(bool skipcur)
if (!best) if (!best)
return; return;
if (!strlen(override_name))
goto found;
/* Check for the override clocksource. */ /* Check for the override clocksource. */
list_for_each_entry(cs, &clocksource_list, list) { list_for_each_entry(cs, &clocksource_list, list) {
if (skipcur && cs == curr_clocksource) if (skipcur && cs == curr_clocksource)
...@@ -625,6 +628,7 @@ static void __clocksource_select(bool skipcur) ...@@ -625,6 +628,7 @@ static void __clocksource_select(bool skipcur)
break; break;
} }
found:
if (curr_clocksource != best && !timekeeping_notify(best)) { if (curr_clocksource != best && !timekeeping_notify(best)) {
pr_info("Switched to clocksource %s\n", best->name); pr_info("Switched to clocksource %s\n", best->name);
curr_clocksource = best; curr_clocksource = best;
...@@ -853,16 +857,16 @@ EXPORT_SYMBOL(clocksource_unregister); ...@@ -853,16 +857,16 @@ EXPORT_SYMBOL(clocksource_unregister);
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
/** /**
* sysfs_show_current_clocksources - sysfs interface for current clocksource * current_clocksource_show - sysfs interface for current clocksource
* @dev: unused * @dev: unused
* @attr: unused * @attr: unused
* @buf: char buffer to be filled with clocksource list * @buf: char buffer to be filled with clocksource list
* *
* Provides sysfs interface for listing current clocksource. * Provides sysfs interface for listing current clocksource.
*/ */
static ssize_t static ssize_t current_clocksource_show(struct device *dev,
sysfs_show_current_clocksources(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf) char *buf)
{ {
ssize_t count = 0; ssize_t count = 0;
...@@ -891,7 +895,7 @@ ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt) ...@@ -891,7 +895,7 @@ ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt)
} }
/** /**
* sysfs_override_clocksource - interface for manually overriding clocksource * current_clocksource_store - interface for manually overriding clocksource
* @dev: unused * @dev: unused
* @attr: unused * @attr: unused
* @buf: name of override clocksource * @buf: name of override clocksource
...@@ -900,9 +904,9 @@ ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt) ...@@ -900,9 +904,9 @@ ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt)
* Takes input from sysfs interface for manually overriding the default * Takes input from sysfs interface for manually overriding the default
* clocksource selection. * clocksource selection.
*/ */
static ssize_t sysfs_override_clocksource(struct device *dev, static ssize_t current_clocksource_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
ssize_t ret; ssize_t ret;
...@@ -916,9 +920,10 @@ static ssize_t sysfs_override_clocksource(struct device *dev, ...@@ -916,9 +920,10 @@ static ssize_t sysfs_override_clocksource(struct device *dev,
return ret; return ret;
} }
static DEVICE_ATTR_RW(current_clocksource);
/** /**
* sysfs_unbind_current_clocksource - interface for manually unbinding clocksource * unbind_clocksource_store - interface for manually unbinding clocksource
* @dev: unused * @dev: unused
* @attr: unused * @attr: unused
* @buf: unused * @buf: unused
...@@ -926,7 +931,7 @@ static ssize_t sysfs_override_clocksource(struct device *dev, ...@@ -926,7 +931,7 @@ static ssize_t sysfs_override_clocksource(struct device *dev,
* *
* Takes input from sysfs interface for manually unbinding a clocksource. * Takes input from sysfs interface for manually unbinding a clocksource.
*/ */
static ssize_t sysfs_unbind_clocksource(struct device *dev, static ssize_t unbind_clocksource_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
...@@ -950,19 +955,19 @@ static ssize_t sysfs_unbind_clocksource(struct device *dev, ...@@ -950,19 +955,19 @@ static ssize_t sysfs_unbind_clocksource(struct device *dev,
return ret ? ret : count; return ret ? ret : count;
} }
static DEVICE_ATTR_WO(unbind_clocksource);
/** /**
* sysfs_show_available_clocksources - sysfs interface for listing clocksource * available_clocksource_show - sysfs interface for listing clocksource
* @dev: unused * @dev: unused
* @attr: unused * @attr: unused
* @buf: char buffer to be filled with clocksource list * @buf: char buffer to be filled with clocksource list
* *
* Provides sysfs interface for listing registered clocksources * Provides sysfs interface for listing registered clocksources
*/ */
static ssize_t static ssize_t available_clocksource_show(struct device *dev,
sysfs_show_available_clocksources(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, char *buf)
char *buf)
{ {
struct clocksource *src; struct clocksource *src;
ssize_t count = 0; ssize_t count = 0;
...@@ -986,17 +991,15 @@ sysfs_show_available_clocksources(struct device *dev, ...@@ -986,17 +991,15 @@ sysfs_show_available_clocksources(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR_RO(available_clocksource);
/* static struct attribute *clocksource_attrs[] = {
* Sysfs setup bits: &dev_attr_current_clocksource.attr,
*/ &dev_attr_unbind_clocksource.attr,
static DEVICE_ATTR(current_clocksource, 0644, sysfs_show_current_clocksources, &dev_attr_available_clocksource.attr,
sysfs_override_clocksource); NULL
};
static DEVICE_ATTR(unbind_clocksource, 0200, NULL, sysfs_unbind_clocksource); ATTRIBUTE_GROUPS(clocksource);
static DEVICE_ATTR(available_clocksource, 0444,
sysfs_show_available_clocksources, NULL);
static struct bus_type clocksource_subsys = { static struct bus_type clocksource_subsys = {
.name = "clocksource", .name = "clocksource",
...@@ -1006,6 +1009,7 @@ static struct bus_type clocksource_subsys = { ...@@ -1006,6 +1009,7 @@ static struct bus_type clocksource_subsys = {
static struct device device_clocksource = { static struct device device_clocksource = {
.id = 0, .id = 0,
.bus = &clocksource_subsys, .bus = &clocksource_subsys,
.groups = clocksource_groups,
}; };
static int __init init_clocksource_sysfs(void) static int __init init_clocksource_sysfs(void)
...@@ -1014,17 +1018,7 @@ static int __init init_clocksource_sysfs(void) ...@@ -1014,17 +1018,7 @@ static int __init init_clocksource_sysfs(void)
if (!error) if (!error)
error = device_register(&device_clocksource); error = device_register(&device_clocksource);
if (!error)
error = device_create_file(
&device_clocksource,
&dev_attr_current_clocksource);
if (!error)
error = device_create_file(&device_clocksource,
&dev_attr_unbind_clocksource);
if (!error)
error = device_create_file(
&device_clocksource,
&dev_attr_available_clocksource);
return error; return error;
} }
......
...@@ -90,11 +90,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = ...@@ -90,11 +90,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
.clockid = CLOCK_REALTIME, .clockid = CLOCK_REALTIME,
.get_time = &ktime_get_real, .get_time = &ktime_get_real,
}, },
{
.index = HRTIMER_BASE_BOOTTIME,
.clockid = CLOCK_BOOTTIME,
.get_time = &ktime_get_boottime,
},
{ {
.index = HRTIMER_BASE_TAI, .index = HRTIMER_BASE_TAI,
.clockid = CLOCK_TAI, .clockid = CLOCK_TAI,
...@@ -110,11 +105,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = ...@@ -110,11 +105,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
.clockid = CLOCK_REALTIME, .clockid = CLOCK_REALTIME,
.get_time = &ktime_get_real, .get_time = &ktime_get_real,
}, },
{
.index = HRTIMER_BASE_BOOTTIME_SOFT,
.clockid = CLOCK_BOOTTIME,
.get_time = &ktime_get_boottime,
},
{ {
.index = HRTIMER_BASE_TAI_SOFT, .index = HRTIMER_BASE_TAI_SOFT,
.clockid = CLOCK_TAI, .clockid = CLOCK_TAI,
...@@ -129,7 +119,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { ...@@ -129,7 +119,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, [CLOCK_BOOTTIME] = HRTIMER_BASE_MONOTONIC,
[CLOCK_TAI] = HRTIMER_BASE_TAI, [CLOCK_TAI] = HRTIMER_BASE_TAI,
}; };
...@@ -565,14 +555,12 @@ __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base, unsigned int active_ ...@@ -565,14 +555,12 @@ __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base, unsigned int active_
static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
{ {
ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset;
ktime_t *offs_tai = &base->clock_base[HRTIMER_BASE_TAI].offset; ktime_t *offs_tai = &base->clock_base[HRTIMER_BASE_TAI].offset;
ktime_t now = ktime_get_update_offsets_now(&base->clock_was_set_seq, ktime_t now = ktime_get_update_offsets_now(&base->clock_was_set_seq,
offs_real, offs_boot, offs_tai); offs_real, offs_tai);
base->clock_base[HRTIMER_BASE_REALTIME_SOFT].offset = *offs_real; base->clock_base[HRTIMER_BASE_REALTIME_SOFT].offset = *offs_real;
base->clock_base[HRTIMER_BASE_BOOTTIME_SOFT].offset = *offs_boot;
base->clock_base[HRTIMER_BASE_TAI_SOFT].offset = *offs_tai; base->clock_base[HRTIMER_BASE_TAI_SOFT].offset = *offs_tai;
return now; return now;
......
...@@ -73,6 +73,8 @@ int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp) ...@@ -73,6 +73,8 @@ int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
case CLOCK_BOOTTIME: case CLOCK_BOOTTIME:
get_monotonic_boottime64(tp); get_monotonic_boottime64(tp);
break; break;
case CLOCK_MONOTONIC_ACTIVE:
ktime_get_active_ts64(tp);
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -252,15 +252,16 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 * ...@@ -252,15 +252,16 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *
return 0; return 0;
} }
static int posix_get_boottime(const clockid_t which_clock, struct timespec64 *tp) static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
{ {
get_monotonic_boottime64(tp); timekeeping_clocktai64(tp);
return 0; return 0;
} }
static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp) static int posix_get_monotonic_active(clockid_t which_clock,
struct timespec64 *tp)
{ {
timekeeping_clocktai64(tp); ktime_get_active_ts64(tp);
return 0; return 0;
} }
...@@ -1316,19 +1317,9 @@ static const struct k_clock clock_tai = { ...@@ -1316,19 +1317,9 @@ static const struct k_clock clock_tai = {
.timer_arm = common_hrtimer_arm, .timer_arm = common_hrtimer_arm,
}; };
static const struct k_clock clock_boottime = { static const struct k_clock clock_monotonic_active = {
.clock_getres = posix_get_hrtimer_res, .clock_getres = posix_get_hrtimer_res,
.clock_get = posix_get_boottime, .clock_get = posix_get_monotonic_active,
.nsleep = common_nsleep,
.timer_create = common_timer_create,
.timer_set = common_timer_set,
.timer_get = common_timer_get,
.timer_del = common_timer_del,
.timer_rearm = common_hrtimer_rearm,
.timer_forward = common_hrtimer_forward,
.timer_remaining = common_hrtimer_remaining,
.timer_try_to_cancel = common_hrtimer_try_to_cancel,
.timer_arm = common_hrtimer_arm,
}; };
static const struct k_clock * const posix_clocks[] = { static const struct k_clock * const posix_clocks[] = {
...@@ -1339,10 +1330,11 @@ static const struct k_clock * const posix_clocks[] = { ...@@ -1339,10 +1330,11 @@ static const struct k_clock * const posix_clocks[] = {
[CLOCK_MONOTONIC_RAW] = &clock_monotonic_raw, [CLOCK_MONOTONIC_RAW] = &clock_monotonic_raw,
[CLOCK_REALTIME_COARSE] = &clock_realtime_coarse, [CLOCK_REALTIME_COARSE] = &clock_realtime_coarse,
[CLOCK_MONOTONIC_COARSE] = &clock_monotonic_coarse, [CLOCK_MONOTONIC_COARSE] = &clock_monotonic_coarse,
[CLOCK_BOOTTIME] = &clock_boottime, [CLOCK_BOOTTIME] = &clock_monotonic,
[CLOCK_REALTIME_ALARM] = &alarm_clock, [CLOCK_REALTIME_ALARM] = &alarm_clock,
[CLOCK_BOOTTIME_ALARM] = &alarm_clock, [CLOCK_BOOTTIME_ALARM] = &alarm_clock,
[CLOCK_TAI] = &clock_tai, [CLOCK_TAI] = &clock_tai,
[CLOCK_MONOTONIC_ACTIVE] = &clock_monotonic_active,
}; };
static const struct k_clock *clockid_to_kclock(const clockid_t id) static const struct k_clock *clockid_to_kclock(const clockid_t id)
......
...@@ -419,6 +419,19 @@ void tick_suspend_local(void) ...@@ -419,6 +419,19 @@ void tick_suspend_local(void)
clockevents_shutdown(td->evtdev); clockevents_shutdown(td->evtdev);
} }
static void tick_forward_next_period(void)
{
ktime_t delta, now = ktime_get();
u64 n;
delta = ktime_sub(now, tick_next_period);
n = ktime_divns(delta, tick_period);
tick_next_period += n * tick_period;
if (tick_next_period < now)
tick_next_period += tick_period;
tick_sched_forward_next_period();
}
/** /**
* tick_resume_local - Resume the local tick device * tick_resume_local - Resume the local tick device
* *
...@@ -431,6 +444,8 @@ void tick_resume_local(void) ...@@ -431,6 +444,8 @@ void tick_resume_local(void)
struct tick_device *td = this_cpu_ptr(&tick_cpu_device); struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
bool broadcast = tick_resume_check_broadcast(); bool broadcast = tick_resume_check_broadcast();
tick_forward_next_period();
clockevents_tick_resume(td->evtdev); clockevents_tick_resume(td->evtdev);
if (!broadcast) { if (!broadcast) {
if (td->mode == TICKDEV_MODE_PERIODIC) if (td->mode == TICKDEV_MODE_PERIODIC)
......
...@@ -141,6 +141,12 @@ static inline void tick_check_oneshot_broadcast_this_cpu(void) { } ...@@ -141,6 +141,12 @@ static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); } static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
#endif /* !(BROADCAST && ONESHOT) */ #endif /* !(BROADCAST && ONESHOT) */
#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
extern void tick_sched_forward_next_period(void);
#else
static inline void tick_sched_forward_next_period(void) { }
#endif
/* NO_HZ_FULL internal */ /* NO_HZ_FULL internal */
#ifdef CONFIG_NO_HZ_FULL #ifdef CONFIG_NO_HZ_FULL
extern void tick_nohz_init(void); extern void tick_nohz_init(void);
......
...@@ -51,6 +51,15 @@ struct tick_sched *tick_get_tick_sched(int cpu) ...@@ -51,6 +51,15 @@ struct tick_sched *tick_get_tick_sched(int cpu)
*/ */
static ktime_t last_jiffies_update; static ktime_t last_jiffies_update;
/*
* Called after resume. Make sure that jiffies are not fast forwarded due to
* clock monotonic being forwarded by the suspended time.
*/
void tick_sched_forward_next_period(void)
{
last_jiffies_update = tick_next_period;
}
/* /*
* Must be called with interrupts disabled ! * Must be called with interrupts disabled !
*/ */
......
...@@ -488,6 +488,18 @@ struct timeval ns_to_timeval(const s64 nsec) ...@@ -488,6 +488,18 @@ struct timeval ns_to_timeval(const s64 nsec)
} }
EXPORT_SYMBOL(ns_to_timeval); EXPORT_SYMBOL(ns_to_timeval);
struct __kernel_old_timeval ns_to_kernel_old_timeval(const s64 nsec)
{
struct timespec64 ts = ns_to_timespec64(nsec);
struct __kernel_old_timeval tv;
tv.tv_sec = ts.tv_sec;
tv.tv_usec = (suseconds_t)ts.tv_nsec / 1000;
return tv;
}
EXPORT_SYMBOL(ns_to_kernel_old_timeval);
/** /**
* set_normalized_timespec - set timespec sec and nsec parts and normalize * set_normalized_timespec - set timespec sec and nsec parts and normalize
* *
......
This diff is collapsed.
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
extern ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, extern ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq,
ktime_t *offs_real, ktime_t *offs_real,
ktime_t *offs_boot,
ktime_t *offs_tai); ktime_t *offs_tai);
extern int timekeeping_valid_for_hres(void); extern int timekeeping_valid_for_hres(void);
......
...@@ -1164,7 +1164,7 @@ static struct { ...@@ -1164,7 +1164,7 @@ static struct {
{ trace_clock, "perf", 1 }, { trace_clock, "perf", 1 },
{ ktime_get_mono_fast_ns, "mono", 1 }, { ktime_get_mono_fast_ns, "mono", 1 },
{ ktime_get_raw_fast_ns, "mono_raw", 1 }, { ktime_get_raw_fast_ns, "mono_raw", 1 },
{ ktime_get_boot_fast_ns, "boot", 1 }, { ktime_get_mono_fast_ns, "boot", 1 },
ARCH_TRACE_CLOCKS ARCH_TRACE_CLOCKS
}; };
......
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