aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/time.h2
-rw-r--r--init/main.c1
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/time/clocksource.c4
-rw-r--r--kernel/timer.c93
5 files changed, 86 insertions, 15 deletions
diff --git a/include/linux/time.h b/include/linux/time.h
index 0cd696cee998..88d3b812841e 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -77,6 +77,8 @@ extern struct timespec xtime;
77extern struct timespec wall_to_monotonic; 77extern struct timespec wall_to_monotonic;
78extern seqlock_t xtime_lock; 78extern seqlock_t xtime_lock;
79 79
80void timekeeping_init(void);
81
80static inline unsigned long get_seconds(void) 82static inline unsigned long get_seconds(void)
81{ 83{
82 return xtime.tv_sec; 84 return xtime.tv_sec;
diff --git a/init/main.c b/init/main.c
index f715b9b89753..9a970d317ea5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -490,6 +490,7 @@ asmlinkage void __init start_kernel(void)
490 hrtimers_init(); 490 hrtimers_init();
491 softirq_init(); 491 softirq_init();
492 time_init(); 492 time_init();
493 timekeeping_init();
493 494
494 /* 495 /*
495 * HACK ALERT! This is early. We're enabling the console before 496 * HACK ALERT! This is early. We're enabling the console before
diff --git a/kernel/Makefile b/kernel/Makefile
index f6ef00f4f90f..bc4b8a7161ff 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,6 +10,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ 10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
11 hrtimer.o 11 hrtimer.o
12 12
13obj-y += time/
13obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o 14obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
14obj-$(CONFIG_FUTEX) += futex.o 15obj-$(CONFIG_FUTEX) += futex.o
15ifeq ($(CONFIG_COMPAT),y) 16ifeq ($(CONFIG_COMPAT),y)
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 95dd2200a109..4288bfa12c3f 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -56,7 +56,7 @@ static int finished_booting;
56 * 56 *
57 * Hack to avoid lots of clocksource churn at boot time 57 * Hack to avoid lots of clocksource churn at boot time
58 */ 58 */
59static int clocksource_done_booting(void) 59static int __init clocksource_done_booting(void)
60{ 60{
61 finished_booting = 1; 61 finished_booting = 1;
62 return 0; 62 return 0;
@@ -289,7 +289,7 @@ static struct sys_device device_clocksource = {
289 .cls = &clocksource_sysclass, 289 .cls = &clocksource_sysclass,
290}; 290};
291 291
292static int init_clocksource_sysfs(void) 292static int __init init_clocksource_sysfs(void)
293{ 293{
294 int error = sysdev_class_register(&clocksource_sysclass); 294 int error = sysdev_class_register(&clocksource_sysclass);
295 295
diff --git a/kernel/timer.c b/kernel/timer.c
index eb97371b87d8..524c7f638365 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -792,24 +792,93 @@ u64 current_tick_length(void)
792 return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj; 792 return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj;
793} 793}
794 794
795/* XXX - all of this timekeeping code should be later moved to time.c */
796#include <linux/clocksource.h>
797static struct clocksource *clock; /* pointer to current clocksource */
798static cycle_t last_clock_cycle; /* cycle value at last update_wall_time */
795/* 799/*
796 * Using a loop looks inefficient, but "ticks" is 800 * timekeeping_init - Initializes the clocksource and common timekeeping values
797 * usually just one (we shouldn't be losing ticks,
798 * we're doing this this way mainly for interrupt
799 * latency reasons, not because we think we'll
800 * have lots of lost timer ticks
801 */ 801 */
802static void update_wall_time(unsigned long ticks) 802void __init timekeeping_init(void)
803{ 803{
804 do { 804 unsigned long flags;
805 ticks--; 805
806 write_seqlock_irqsave(&xtime_lock, flags);
807 clock = get_next_clocksource();
808 calculate_clocksource_interval(clock, tick_nsec);
809 last_clock_cycle = read_clocksource(clock);
810 ntp_clear();
811 write_sequnlock_irqrestore(&xtime_lock, flags);
812}
813
814
815/*
816 * timekeeping_resume - Resumes the generic timekeeping subsystem.
817 * @dev: unused
818 *
819 * This is for the generic clocksource timekeeping.
820 * xtime/wall_to_monotonic/jiffies/wall_jiffies/etc are
821 * still managed by arch specific suspend/resume code.
822 */
823static int timekeeping_resume(struct sys_device *dev)
824{
825 unsigned long flags;
826
827 write_seqlock_irqsave(&xtime_lock, flags);
828 /* restart the last cycle value */
829 last_clock_cycle = read_clocksource(clock);
830 write_sequnlock_irqrestore(&xtime_lock, flags);
831 return 0;
832}
833
834/* sysfs resume/suspend bits for timekeeping */
835static struct sysdev_class timekeeping_sysclass = {
836 .resume = timekeeping_resume,
837 set_kset_name("timekeeping"),
838};
839
840static struct sys_device device_timer = {
841 .id = 0,
842 .cls = &timekeeping_sysclass,
843};
844
845static int __init timekeeping_init_device(void)
846{
847 int error = sysdev_class_register(&timekeeping_sysclass);
848 if (!error)
849 error = sysdev_register(&device_timer);
850 return error;
851}
852
853device_initcall(timekeeping_init_device);
854
855/*
856 * update_wall_time - Uses the current clocksource to increment the wall time
857 *
858 * Called from the timer interrupt, must hold a write on xtime_lock.
859 */
860static void update_wall_time(void)
861{
862 cycle_t now, offset;
863
864 now = read_clocksource(clock);
865 offset = (now - last_clock_cycle)&clock->mask;
866
867 /* normally this loop will run just once, however in the
868 * case of lost or late ticks, it will accumulate correctly.
869 */
870 while (offset > clock->interval_cycles) {
871 /* accumulate one interval */
872 last_clock_cycle += clock->interval_cycles;
873 offset -= clock->interval_cycles;
874
806 update_wall_time_one_tick(); 875 update_wall_time_one_tick();
807 if (xtime.tv_nsec >= 1000000000) { 876 if (xtime.tv_nsec >= 1000000000) {
808 xtime.tv_nsec -= 1000000000; 877 xtime.tv_nsec -= 1000000000;
809 xtime.tv_sec++; 878 xtime.tv_sec++;
810 second_overflow(); 879 second_overflow();
811 } 880 }
812 } while (ticks); 881 }
813} 882}
814 883
815/* 884/*
@@ -915,10 +984,8 @@ static inline void update_times(void)
915 unsigned long ticks; 984 unsigned long ticks;
916 985
917 ticks = jiffies - wall_jiffies; 986 ticks = jiffies - wall_jiffies;
918 if (ticks) { 987 wall_jiffies += ticks;
919 wall_jiffies += ticks; 988 update_wall_time();
920 update_wall_time(ticks);
921 }
922 calc_load(ticks); 989 calc_load(ticks);
923} 990}
924 991