Commit 78c4def6 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'timers-core-for-linus' of...

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

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  hrtimer: Make lookup table const
  RTC: Disable CONFIG_RTC_CLASS from being built as a module
  timers: Fix alarmtimer build issues when CONFIG_RTC_CLASS=n
  timers: Remove delayed irqwork from alarmtimers implementation
  timers: Improve alarmtimer comments and minor fixes
  timers: Posix interface for alarm-timers
  timers: Introduce in-kernel alarm-timer interface
  timers: Add rb_init_node() to allow for stack allocated rb nodes
  time: Add timekeeping_inject_sleeptime
parents 7e6628e4 942c3c5c
......@@ -3,10 +3,10 @@
#
config RTC_LIB
tristate
bool
menuconfig RTC_CLASS
tristate "Real Time Clock"
bool "Real Time Clock"
default n
depends on !S390
select RTC_LIB
......@@ -15,9 +15,6 @@ menuconfig RTC_CLASS
be allowed to plug one or more RTCs to your system. You will
probably want to enable one or more of the interfaces below.
This driver can also be built as a module. If so, the module
will be called rtc-core.
if RTC_CLASS
config RTC_HCTOSYS
......
......@@ -41,26 +41,21 @@ static void rtc_device_release(struct device *dev)
* system's wall clock; restore it on resume().
*/
static struct timespec delta;
static time_t oldtime;
static struct timespec oldts;
static int rtc_suspend(struct device *dev, pm_message_t mesg)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
struct timespec ts = current_kernel_time();
if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
rtc_read_time(rtc, &tm);
ktime_get_ts(&oldts);
rtc_tm_to_time(&tm, &oldtime);
/* RTC precision is 1 second; adjust delta for avg 1/2 sec err */
set_normalized_timespec(&delta,
ts.tv_sec - oldtime,
ts.tv_nsec - (NSEC_PER_SEC >> 1));
return 0;
}
......@@ -70,10 +65,12 @@ static int rtc_resume(struct device *dev)
struct rtc_time tm;
time_t newtime;
struct timespec time;
struct timespec newts;
if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
ktime_get_ts(&newts);
rtc_read_time(rtc, &tm);
if (rtc_valid_tm(&tm) != 0) {
pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev));
......@@ -85,15 +82,13 @@ static int rtc_resume(struct device *dev)
pr_debug("%s: time travel!\n", dev_name(&rtc->dev));
return 0;
}
/* calculate the RTC time delta */
set_normalized_timespec(&time, newtime - oldtime, 0);
/* restore wall clock using delta against this RTC;
* adjust again for avg 1/2 second RTC sampling error
*/
set_normalized_timespec(&time,
newtime + delta.tv_sec,
(NSEC_PER_SEC >> 1) + delta.tv_nsec);
do_settimeofday(&time);
/* subtract kernel time between rtc_suspend to rtc_resume */
time = timespec_sub(time, timespec_sub(newts, oldts));
timekeeping_inject_sleeptime(&time);
return 0;
}
......
#ifndef _LINUX_ALARMTIMER_H
#define _LINUX_ALARMTIMER_H
#include <linux/time.h>
#include <linux/hrtimer.h>
#include <linux/timerqueue.h>
#include <linux/rtc.h>
enum alarmtimer_type {
ALARM_REALTIME,
ALARM_BOOTTIME,
ALARM_NUMTYPE,
};
/**
* struct alarm - Alarm timer structure
* @node: timerqueue node for adding to the event list this value
* also includes the expiration time.
* @period: Period for recuring alarms
* @function: Function pointer to be executed when the timer fires.
* @type: Alarm type (BOOTTIME/REALTIME)
* @enabled: Flag that represents if the alarm is set to fire or not
* @data: Internal data value.
*/
struct alarm {
struct timerqueue_node node;
ktime_t period;
void (*function)(struct alarm *);
enum alarmtimer_type type;
bool enabled;
void *data;
};
void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
void (*function)(struct alarm *));
void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period);
void alarm_cancel(struct alarm *alarm);
#endif
......@@ -355,7 +355,12 @@ struct cpu_vfs_cap_data {
#define CAP_SYSLOG 34
#define CAP_LAST_CAP CAP_SYSLOG
/* Allow triggering something that will wake the system */
#define CAP_WAKE_ALARM 35
#define CAP_LAST_CAP CAP_WAKE_ALARM
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
......
......@@ -5,6 +5,7 @@
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/timex.h>
#include <linux/alarmtimer.h>
union cpu_time_count {
cputime_t cpu;
......@@ -80,6 +81,7 @@ struct k_itimer {
unsigned long incr;
unsigned long expires;
} mmtimer;
struct alarm alarmtimer;
} it;
};
......
......@@ -136,6 +136,14 @@ static inline void rb_set_color(struct rb_node *rb, int color)
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
static inline void rb_init_node(struct rb_node *rb)
{
rb->rb_parent_color = 0;
rb->rb_right = NULL;
rb->rb_left = NULL;
RB_CLEAR_NODE(rb);
}
extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);
......
......@@ -126,6 +126,7 @@ struct timespec __current_kernel_time(void); /* does not take xtime_lock */
struct timespec get_monotonic_coarse(void);
void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
struct timespec *wtom, struct timespec *sleep);
void timekeeping_inject_sleeptime(struct timespec *delta);
#define CURRENT_TIME (current_kernel_time())
#define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 })
......@@ -294,6 +295,8 @@ struct itimerval {
#define CLOCK_REALTIME_COARSE 5
#define CLOCK_MONOTONIC_COARSE 6
#define CLOCK_BOOTTIME 7
#define CLOCK_REALTIME_ALARM 8
#define CLOCK_BOOTTIME_ALARM 9
/*
* The IDs of various hardware clocks:
......
......@@ -39,7 +39,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head)
static inline void timerqueue_init(struct timerqueue_node *node)
{
RB_CLEAR_NODE(&node->node);
rb_init_node(&node->node);
}
static inline void timerqueue_init_head(struct timerqueue_head *head)
......
......@@ -81,7 +81,7 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
}
};
static int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,
......
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o
obj-y += timeconv.o posix-clock.o
obj-y += timeconv.o posix-clock.o alarmtimer.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o
......
This diff is collapsed.
......@@ -595,6 +595,58 @@ void __init timekeeping_init(void)
/* time in seconds when suspend began */
static struct timespec timekeeping_suspend_time;
/**
* __timekeeping_inject_sleeptime - Internal function to add sleep interval
* @delta: pointer to a timespec delta value
*
* Takes a timespec offset measuring a suspend interval and properly
* adds the sleep offset to the timekeeping variables.
*/
static void __timekeeping_inject_sleeptime(struct timespec *delta)
{
xtime = timespec_add(xtime, *delta);
wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta);
total_sleep_time = timespec_add(total_sleep_time, *delta);
}
/**
* timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values
* @delta: pointer to a timespec delta value
*
* This hook is for architectures that cannot support read_persistent_clock
* because their RTC/persistent clock is only accessible when irqs are enabled.
*
* This function should only be called by rtc_resume(), and allows
* a suspend offset to be injected into the timekeeping values.
*/
void timekeeping_inject_sleeptime(struct timespec *delta)
{
unsigned long flags;
struct timespec ts;
/* Make sure we don't set the clock twice */
read_persistent_clock(&ts);
if (!(ts.tv_sec == 0 && ts.tv_nsec == 0))
return;
write_seqlock_irqsave(&xtime_lock, flags);
timekeeping_forward_now();
__timekeeping_inject_sleeptime(delta);
timekeeper.ntp_error = 0;
ntp_clear();
update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
timekeeper.mult);
write_sequnlock_irqrestore(&xtime_lock, flags);
/* signal hrtimers about time change */
clock_was_set();
}
/**
* timekeeping_resume - Resumes the generic timekeeping subsystem.
*
......@@ -615,9 +667,7 @@ static void timekeeping_resume(void)
if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) {
ts = timespec_sub(ts, timekeeping_suspend_time);
xtime = timespec_add(xtime, ts);
wall_to_monotonic = timespec_sub(wall_to_monotonic, ts);
total_sleep_time = timespec_add(total_sleep_time, ts);
__timekeeping_inject_sleeptime(&ts);
}
/* re-base the last cycle value */
timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
......
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