diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-18 12:15:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-18 12:15:24 -0400 |
commit | a03fdb7612874834d6847107198712d18b5242c7 (patch) | |
tree | 9ae81170509fd8b1c23d1b7e8edfa7a2203ffce3 /arch | |
parent | 202c4675c55ddf6b443c7e057d2dff6b42ef71aa (diff) | |
parent | 12e09337fe238981cb0c87543306e23775d1a143 (diff) |
Merge branch 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (34 commits)
time: Prevent 32 bit overflow with set_normalized_timespec()
clocksource: Delay clocksource down rating to late boot
clocksource: clocksource_select must be called with mutex locked
clocksource: Resolve cpu hotplug dead lock with TSC unstable, fix crash
timers: Drop a function prototype
clocksource: Resolve cpu hotplug dead lock with TSC unstable
timer.c: Fix S/390 comments
timekeeping: Fix invalid getboottime() value
timekeeping: Fix up read_persistent_clock() breakage on sh
timekeeping: Increase granularity of read_persistent_clock(), build fix
time: Introduce CLOCK_REALTIME_COARSE
x86: Do not unregister PIT clocksource on PIT oneshot setup/shutdown
clocksource: Avoid clocksource watchdog circular locking dependency
clocksource: Protect the watchdog rating changes with clocksource_mutex
clocksource: Call clocksource_change_rating() outside of watchdog_lock
timekeeping: Introduce read_boot_clock
timekeeping: Increase granularity of read_persistent_clock()
timekeeping: Update clocksource with stop_machine
timekeeping: Add timekeeper read_clock helper functions
timekeeping: Move NTP adjusted clock multiplier to struct timekeeper
...
Fix trivial conflict due to MIPS lemote -> loongson renaming.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/plat-omap/common.c | 7 | ||||
-rw-r--r-- | arch/m68knommu/kernel/time.c | 5 | ||||
-rw-r--r-- | arch/mips/dec/time.c | 5 | ||||
-rw-r--r-- | arch/mips/lasat/ds1603.c | 5 | ||||
-rw-r--r-- | arch/mips/lasat/sysctl.c | 8 | ||||
-rw-r--r-- | arch/mips/loongson/common/time.c | 5 | ||||
-rw-r--r-- | arch/mips/mti-malta/malta-time.c | 5 | ||||
-rw-r--r-- | arch/mips/pmc-sierra/yosemite/setup.c | 5 | ||||
-rw-r--r-- | arch/mips/sibyte/swarm/setup.c | 15 | ||||
-rw-r--r-- | arch/mips/sni/time.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 19 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 38 | ||||
-rw-r--r-- | arch/sh/kernel/time.c | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/vgtod.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/i8253.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/rtc.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/tsc.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/vsyscall_64.c | 1 | ||||
-rw-r--r-- | arch/x86/vdso/vclock_gettime.c | 39 | ||||
-rw-r--r-- | arch/xtensa/kernel/time.c | 5 |
20 files changed, 118 insertions, 94 deletions
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index ebcf006406f9..95587b6c0259 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c | |||
@@ -253,11 +253,8 @@ static struct clocksource clocksource_32k = { | |||
253 | */ | 253 | */ |
254 | unsigned long long sched_clock(void) | 254 | unsigned long long sched_clock(void) |
255 | { | 255 | { |
256 | unsigned long long ret; | 256 | return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k), |
257 | 257 | clocksource_32k.mult, clocksource_32k.shift); | |
258 | ret = (unsigned long long)clocksource_32k.read(&clocksource_32k); | ||
259 | ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift; | ||
260 | return ret; | ||
261 | } | 258 | } |
262 | 259 | ||
263 | static int __init omap_init_clocksource_32k(void) | 260 | static int __init omap_init_clocksource_32k(void) |
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c index c2aa717de08a..a90acf5b0cde 100644 --- a/arch/m68knommu/kernel/time.c +++ b/arch/m68knommu/kernel/time.c | |||
@@ -72,9 +72,10 @@ static unsigned long read_rtc_mmss(void) | |||
72 | return mktime(year, mon, day, hour, min, sec); | 72 | return mktime(year, mon, day, hour, min, sec); |
73 | } | 73 | } |
74 | 74 | ||
75 | unsigned long read_persistent_clock(void) | 75 | void read_persistent_clock(struct timespec *ts) |
76 | { | 76 | { |
77 | return read_rtc_mmss(); | 77 | ts->tv_sec = read_rtc_mmss(); |
78 | ts->tv_nsec = 0; | ||
78 | } | 79 | } |
79 | 80 | ||
80 | int update_persistent_clock(struct timespec now) | 81 | int update_persistent_clock(struct timespec now) |
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 463136e6685a..02f505f23c32 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <asm/dec/ioasic.h> | 18 | #include <asm/dec/ioasic.h> |
19 | #include <asm/dec/machtype.h> | 19 | #include <asm/dec/machtype.h> |
20 | 20 | ||
21 | unsigned long read_persistent_clock(void) | 21 | void read_persistent_clock(struct timespec *ts) |
22 | { | 22 | { |
23 | unsigned int year, mon, day, hour, min, sec, real_year; | 23 | unsigned int year, mon, day, hour, min, sec, real_year; |
24 | unsigned long flags; | 24 | unsigned long flags; |
@@ -53,7 +53,8 @@ unsigned long read_persistent_clock(void) | |||
53 | 53 | ||
54 | year += real_year - 72 + 2000; | 54 | year += real_year - 72 + 2000; |
55 | 55 | ||
56 | return mktime(year, mon, day, hour, min, sec); | 56 | ts->tv_sec = mktime(year, mon, day, hour, min, sec); |
57 | ts->tv_nsec = 0; | ||
57 | } | 58 | } |
58 | 59 | ||
59 | /* | 60 | /* |
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c index 52cb1436a12a..c6fd96ff118d 100644 --- a/arch/mips/lasat/ds1603.c +++ b/arch/mips/lasat/ds1603.c | |||
@@ -135,7 +135,7 @@ static void rtc_end_op(void) | |||
135 | lasat_ndelay(1000); | 135 | lasat_ndelay(1000); |
136 | } | 136 | } |
137 | 137 | ||
138 | unsigned long read_persistent_clock(void) | 138 | void read_persistent_clock(struct timespec *ts) |
139 | { | 139 | { |
140 | unsigned long word; | 140 | unsigned long word; |
141 | unsigned long flags; | 141 | unsigned long flags; |
@@ -147,7 +147,8 @@ unsigned long read_persistent_clock(void) | |||
147 | rtc_end_op(); | 147 | rtc_end_op(); |
148 | spin_unlock_irqrestore(&rtc_lock, flags); | 148 | spin_unlock_irqrestore(&rtc_lock, flags); |
149 | 149 | ||
150 | return word; | 150 | ts->tv_sec = word; |
151 | ts->tv_nsec = 0; | ||
151 | } | 152 | } |
152 | 153 | ||
153 | int rtc_mips_set_mmss(unsigned long time) | 154 | int rtc_mips_set_mmss(unsigned long time) |
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c index 8f88886feb12..3f04d4c406b7 100644 --- a/arch/mips/lasat/sysctl.c +++ b/arch/mips/lasat/sysctl.c | |||
@@ -92,10 +92,12 @@ static int rtctmp; | |||
92 | int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, | 92 | int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, |
93 | void *buffer, size_t *lenp, loff_t *ppos) | 93 | void *buffer, size_t *lenp, loff_t *ppos) |
94 | { | 94 | { |
95 | struct timespec ts; | ||
95 | int r; | 96 | int r; |
96 | 97 | ||
97 | if (!write) { | 98 | if (!write) { |
98 | rtctmp = read_persistent_clock(); | 99 | read_persistent_clock(&ts); |
100 | rtctmp = ts.tv_sec; | ||
99 | /* check for time < 0 and set to 0 */ | 101 | /* check for time < 0 and set to 0 */ |
100 | if (rtctmp < 0) | 102 | if (rtctmp < 0) |
101 | rtctmp = 0; | 103 | rtctmp = 0; |
@@ -134,9 +136,11 @@ int sysctl_lasat_rtc(ctl_table *table, | |||
134 | void *oldval, size_t *oldlenp, | 136 | void *oldval, size_t *oldlenp, |
135 | void *newval, size_t newlen) | 137 | void *newval, size_t newlen) |
136 | { | 138 | { |
139 | struct timespec ts; | ||
137 | int r; | 140 | int r; |
138 | 141 | ||
139 | rtctmp = read_persistent_clock(); | 142 | read_persistent_clock(&ts); |
143 | rtctmp = ts.tv_sec; | ||
140 | if (rtctmp < 0) | 144 | if (rtctmp < 0) |
141 | rtctmp = 0; | 145 | rtctmp = 0; |
142 | r = sysctl_intvec(table, oldval, oldlenp, newval, newlen); | 146 | r = sysctl_intvec(table, oldval, oldlenp, newval, newlen); |
diff --git a/arch/mips/loongson/common/time.c b/arch/mips/loongson/common/time.c index b13d17174654..0edbef32b862 100644 --- a/arch/mips/loongson/common/time.c +++ b/arch/mips/loongson/common/time.c | |||
@@ -21,7 +21,8 @@ void __init plat_time_init(void) | |||
21 | mips_hpt_frequency = cpu_clock_freq / 2; | 21 | mips_hpt_frequency = cpu_clock_freq / 2; |
22 | } | 22 | } |
23 | 23 | ||
24 | unsigned long read_persistent_clock(void) | 24 | void read_persistent_clock(struct timespec *ts) |
25 | { | 25 | { |
26 | return mc146818_get_cmos_time(); | 26 | ts->tv_sec = return mc146818_get_cmos_time(); |
27 | ts->tv_nsec = 0; | ||
27 | } | 28 | } |
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 0b97d47691fc..3c6f190aa61c 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c | |||
@@ -100,9 +100,10 @@ static unsigned int __init estimate_cpu_frequency(void) | |||
100 | return count; | 100 | return count; |
101 | } | 101 | } |
102 | 102 | ||
103 | unsigned long read_persistent_clock(void) | 103 | void read_persistent_clock(struct timespec *ts) |
104 | { | 104 | { |
105 | return mc146818_get_cmos_time(); | 105 | ts->tv_sec = mc146818_get_cmos_time(); |
106 | ts->tv_nsec = 0; | ||
106 | } | 107 | } |
107 | 108 | ||
108 | static void __init plat_perf_setup(void) | 109 | static void __init plat_perf_setup(void) |
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 2d3c0dca275d..3498ac9c35af 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c | |||
@@ -70,7 +70,7 @@ void __init bus_error_init(void) | |||
70 | } | 70 | } |
71 | 71 | ||
72 | 72 | ||
73 | unsigned long read_persistent_clock(void) | 73 | void read_persistent_clock(struct timespec *ts) |
74 | { | 74 | { |
75 | unsigned int year, month, day, hour, min, sec; | 75 | unsigned int year, month, day, hour, min, sec; |
76 | unsigned long flags; | 76 | unsigned long flags; |
@@ -92,7 +92,8 @@ unsigned long read_persistent_clock(void) | |||
92 | m48t37_base->control = 0x00; | 92 | m48t37_base->control = 0x00; |
93 | spin_unlock_irqrestore(&rtc_lock, flags); | 93 | spin_unlock_irqrestore(&rtc_lock, flags); |
94 | 94 | ||
95 | return mktime(year, month, day, hour, min, sec); | 95 | ts->tv_sec = mktime(year, month, day, hour, min, sec); |
96 | ts->tv_nsec = 0; | ||
96 | } | 97 | } |
97 | 98 | ||
98 | int rtc_mips_set_time(unsigned long tim) | 99 | int rtc_mips_set_time(unsigned long tim) |
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index 672e45d495a9..623ffc933c4c 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c | |||
@@ -87,19 +87,26 @@ enum swarm_rtc_type { | |||
87 | 87 | ||
88 | enum swarm_rtc_type swarm_rtc_type; | 88 | enum swarm_rtc_type swarm_rtc_type; |
89 | 89 | ||
90 | unsigned long read_persistent_clock(void) | 90 | void read_persistent_clock(struct timespec *ts) |
91 | { | 91 | { |
92 | unsigned long sec; | ||
93 | |||
92 | switch (swarm_rtc_type) { | 94 | switch (swarm_rtc_type) { |
93 | case RTC_XICOR: | 95 | case RTC_XICOR: |
94 | return xicor_get_time(); | 96 | sec = xicor_get_time(); |
97 | break; | ||
95 | 98 | ||
96 | case RTC_M4LT81: | 99 | case RTC_M4LT81: |
97 | return m41t81_get_time(); | 100 | sec = m41t81_get_time(); |
101 | break; | ||
98 | 102 | ||
99 | case RTC_NONE: | 103 | case RTC_NONE: |
100 | default: | 104 | default: |
101 | return mktime(2000, 1, 1, 0, 0, 0); | 105 | sec = mktime(2000, 1, 1, 0, 0, 0); |
106 | break; | ||
102 | } | 107 | } |
108 | ts->tv_sec = sec; | ||
109 | tv->tv_nsec = 0; | ||
103 | } | 110 | } |
104 | 111 | ||
105 | int rtc_mips_set_time(unsigned long sec) | 112 | int rtc_mips_set_time(unsigned long sec) |
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index 0d9ec1a5c24a..62df6a598e0a 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c | |||
@@ -182,7 +182,8 @@ void __init plat_time_init(void) | |||
182 | setup_pit_timer(); | 182 | setup_pit_timer(); |
183 | } | 183 | } |
184 | 184 | ||
185 | unsigned long read_persistent_clock(void) | 185 | void read_persistent_clock(struct timespec *ts) |
186 | { | 186 | { |
187 | return -1; | 187 | ts->tv_sec = -1; |
188 | ts->tv_nsec = 0; | ||
188 | } | 189 | } |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index a180b4f9a4f6..465e498bcb33 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -774,11 +774,12 @@ int update_persistent_clock(struct timespec now) | |||
774 | return ppc_md.set_rtc_time(&tm); | 774 | return ppc_md.set_rtc_time(&tm); |
775 | } | 775 | } |
776 | 776 | ||
777 | unsigned long read_persistent_clock(void) | 777 | void read_persistent_clock(struct timespec *ts) |
778 | { | 778 | { |
779 | struct rtc_time tm; | 779 | struct rtc_time tm; |
780 | static int first = 1; | 780 | static int first = 1; |
781 | 781 | ||
782 | ts->tv_nsec = 0; | ||
782 | /* XXX this is a litle fragile but will work okay in the short term */ | 783 | /* XXX this is a litle fragile but will work okay in the short term */ |
783 | if (first) { | 784 | if (first) { |
784 | first = 0; | 785 | first = 0; |
@@ -786,14 +787,18 @@ unsigned long read_persistent_clock(void) | |||
786 | timezone_offset = ppc_md.time_init(); | 787 | timezone_offset = ppc_md.time_init(); |
787 | 788 | ||
788 | /* get_boot_time() isn't guaranteed to be safe to call late */ | 789 | /* get_boot_time() isn't guaranteed to be safe to call late */ |
789 | if (ppc_md.get_boot_time) | 790 | if (ppc_md.get_boot_time) { |
790 | return ppc_md.get_boot_time() -timezone_offset; | 791 | ts->tv_sec = ppc_md.get_boot_time() - timezone_offset; |
792 | return; | ||
793 | } | ||
794 | } | ||
795 | if (!ppc_md.get_rtc_time) { | ||
796 | ts->tv_sec = 0; | ||
797 | return; | ||
791 | } | 798 | } |
792 | if (!ppc_md.get_rtc_time) | ||
793 | return 0; | ||
794 | ppc_md.get_rtc_time(&tm); | 799 | ppc_md.get_rtc_time(&tm); |
795 | return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, | 800 | ts->tv_sec = mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, |
796 | tm.tm_hour, tm.tm_min, tm.tm_sec); | 801 | tm.tm_hour, tm.tm_min, tm.tm_sec); |
797 | } | 802 | } |
798 | 803 | ||
799 | /* clocksource code */ | 804 | /* clocksource code */ |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index e3dc28b8075d..34162a0b2caa 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -184,12 +184,14 @@ static void timing_alert_interrupt(__u16 code) | |||
184 | static void etr_reset(void); | 184 | static void etr_reset(void); |
185 | static void stp_reset(void); | 185 | static void stp_reset(void); |
186 | 186 | ||
187 | unsigned long read_persistent_clock(void) | 187 | void read_persistent_clock(struct timespec *ts) |
188 | { | 188 | { |
189 | struct timespec ts; | 189 | tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, ts); |
190 | } | ||
190 | 191 | ||
191 | tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, &ts); | 192 | void read_boot_clock(struct timespec *ts) |
192 | return ts.tv_sec; | 193 | { |
194 | tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, ts); | ||
193 | } | 195 | } |
194 | 196 | ||
195 | static cycle_t read_tod_clock(struct clocksource *cs) | 197 | static cycle_t read_tod_clock(struct clocksource *cs) |
@@ -207,6 +209,10 @@ static struct clocksource clocksource_tod = { | |||
207 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 209 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
208 | }; | 210 | }; |
209 | 211 | ||
212 | struct clocksource * __init clocksource_default_clock(void) | ||
213 | { | ||
214 | return &clocksource_tod; | ||
215 | } | ||
210 | 216 | ||
211 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) | 217 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) |
212 | { | 218 | { |
@@ -244,10 +250,6 @@ void update_vsyscall_tz(void) | |||
244 | */ | 250 | */ |
245 | void __init time_init(void) | 251 | void __init time_init(void) |
246 | { | 252 | { |
247 | struct timespec ts; | ||
248 | unsigned long flags; | ||
249 | cycle_t now; | ||
250 | |||
251 | /* Reset time synchronization interfaces. */ | 253 | /* Reset time synchronization interfaces. */ |
252 | etr_reset(); | 254 | etr_reset(); |
253 | stp_reset(); | 255 | stp_reset(); |
@@ -263,26 +265,6 @@ void __init time_init(void) | |||
263 | if (clocksource_register(&clocksource_tod) != 0) | 265 | if (clocksource_register(&clocksource_tod) != 0) |
264 | panic("Could not register TOD clock source"); | 266 | panic("Could not register TOD clock source"); |
265 | 267 | ||
266 | /* | ||
267 | * The TOD clock is an accurate clock. The xtime should be | ||
268 | * initialized in a way that the difference between TOD and | ||
269 | * xtime is reasonably small. Too bad that timekeeping_init | ||
270 | * sets xtime.tv_nsec to zero. In addition the clock source | ||
271 | * change from the jiffies clock source to the TOD clock | ||
272 | * source add another error of up to 1/HZ second. The same | ||
273 | * function sets wall_to_monotonic to a value that is too | ||
274 | * small for /proc/uptime to be accurate. | ||
275 | * Reset xtime and wall_to_monotonic to sane values. | ||
276 | */ | ||
277 | write_seqlock_irqsave(&xtime_lock, flags); | ||
278 | now = get_clock(); | ||
279 | tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime); | ||
280 | clocksource_tod.cycle_last = now; | ||
281 | clocksource_tod.raw_time = xtime; | ||
282 | tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts); | ||
283 | set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec); | ||
284 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
285 | |||
286 | /* Enable TOD clock interrupts on the boot cpu. */ | 268 | /* Enable TOD clock interrupts on the boot cpu. */ |
287 | init_cpu_timer(); | 269 | init_cpu_timer(); |
288 | 270 | ||
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 9b352a1e3fb4..0e0e8581cf7a 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c | |||
@@ -39,11 +39,9 @@ void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; | |||
39 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; | 39 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; |
40 | 40 | ||
41 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | 41 | #ifdef CONFIG_GENERIC_CMOS_UPDATE |
42 | unsigned long read_persistent_clock(void) | 42 | void read_persistent_clock(struct timespec *ts) |
43 | { | 43 | { |
44 | struct timespec tv; | 44 | rtc_sh_get_time(ts); |
45 | rtc_sh_get_time(&tv); | ||
46 | return tv.tv_sec; | ||
47 | } | 45 | } |
48 | 46 | ||
49 | int update_persistent_clock(struct timespec now) | 47 | int update_persistent_clock(struct timespec now) |
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index dc27a69e5d2a..3d61e204826f 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h | |||
@@ -21,6 +21,7 @@ struct vsyscall_gtod_data { | |||
21 | u32 shift; | 21 | u32 shift; |
22 | } clock; | 22 | } clock; |
23 | struct timespec wall_to_monotonic; | 23 | struct timespec wall_to_monotonic; |
24 | struct timespec wall_time_coarse; | ||
24 | }; | 25 | }; |
25 | extern struct vsyscall_gtod_data __vsyscall_gtod_data | 26 | extern struct vsyscall_gtod_data __vsyscall_gtod_data |
26 | __section_vsyscall_gtod_data; | 27 | __section_vsyscall_gtod_data; |
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 5cf36c053ac4..23c167925a5c 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c | |||
@@ -19,12 +19,6 @@ | |||
19 | DEFINE_SPINLOCK(i8253_lock); | 19 | DEFINE_SPINLOCK(i8253_lock); |
20 | EXPORT_SYMBOL(i8253_lock); | 20 | EXPORT_SYMBOL(i8253_lock); |
21 | 21 | ||
22 | #ifdef CONFIG_X86_32 | ||
23 | static void pit_disable_clocksource(void); | ||
24 | #else | ||
25 | static inline void pit_disable_clocksource(void) { } | ||
26 | #endif | ||
27 | |||
28 | /* | 22 | /* |
29 | * HPET replaces the PIT, when enabled. So we need to know, which of | 23 | * HPET replaces the PIT, when enabled. So we need to know, which of |
30 | * the two timers is used | 24 | * the two timers is used |
@@ -57,12 +51,10 @@ static void init_pit_timer(enum clock_event_mode mode, | |||
57 | outb_pit(0, PIT_CH0); | 51 | outb_pit(0, PIT_CH0); |
58 | outb_pit(0, PIT_CH0); | 52 | outb_pit(0, PIT_CH0); |
59 | } | 53 | } |
60 | pit_disable_clocksource(); | ||
61 | break; | 54 | break; |
62 | 55 | ||
63 | case CLOCK_EVT_MODE_ONESHOT: | 56 | case CLOCK_EVT_MODE_ONESHOT: |
64 | /* One shot setup */ | 57 | /* One shot setup */ |
65 | pit_disable_clocksource(); | ||
66 | outb_pit(0x38, PIT_MODE); | 58 | outb_pit(0x38, PIT_MODE); |
67 | break; | 59 | break; |
68 | 60 | ||
@@ -200,17 +192,6 @@ static struct clocksource pit_cs = { | |||
200 | .shift = 20, | 192 | .shift = 20, |
201 | }; | 193 | }; |
202 | 194 | ||
203 | static void pit_disable_clocksource(void) | ||
204 | { | ||
205 | /* | ||
206 | * Use mult to check whether it is registered or not | ||
207 | */ | ||
208 | if (pit_cs.mult) { | ||
209 | clocksource_unregister(&pit_cs); | ||
210 | pit_cs.mult = 0; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static int __init init_pit_clocksource(void) | 195 | static int __init init_pit_clocksource(void) |
215 | { | 196 | { |
216 | /* | 197 | /* |
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 5d465b207e72..bf67dcb4a44c 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c | |||
@@ -178,7 +178,7 @@ static int set_rtc_mmss(unsigned long nowtime) | |||
178 | } | 178 | } |
179 | 179 | ||
180 | /* not static: needed by APM */ | 180 | /* not static: needed by APM */ |
181 | unsigned long read_persistent_clock(void) | 181 | void read_persistent_clock(struct timespec *ts) |
182 | { | 182 | { |
183 | unsigned long retval, flags; | 183 | unsigned long retval, flags; |
184 | 184 | ||
@@ -186,7 +186,8 @@ unsigned long read_persistent_clock(void) | |||
186 | retval = get_wallclock(); | 186 | retval = get_wallclock(); |
187 | spin_unlock_irqrestore(&rtc_lock, flags); | 187 | spin_unlock_irqrestore(&rtc_lock, flags); |
188 | 188 | ||
189 | return retval; | 189 | ts->tv_sec = retval; |
190 | ts->tv_nsec = 0; | ||
190 | } | 191 | } |
191 | 192 | ||
192 | int update_persistent_clock(struct timespec now) | 193 | int update_persistent_clock(struct timespec now) |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 71f4368b357e..fc3672a303d6 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -744,10 +744,16 @@ static cycle_t __vsyscall_fn vread_tsc(void) | |||
744 | } | 744 | } |
745 | #endif | 745 | #endif |
746 | 746 | ||
747 | static void resume_tsc(void) | ||
748 | { | ||
749 | clocksource_tsc.cycle_last = 0; | ||
750 | } | ||
751 | |||
747 | static struct clocksource clocksource_tsc = { | 752 | static struct clocksource clocksource_tsc = { |
748 | .name = "tsc", | 753 | .name = "tsc", |
749 | .rating = 300, | 754 | .rating = 300, |
750 | .read = read_tsc, | 755 | .read = read_tsc, |
756 | .resume = resume_tsc, | ||
751 | .mask = CLOCKSOURCE_MASK(64), | 757 | .mask = CLOCKSOURCE_MASK(64), |
752 | .shift = 22, | 758 | .shift = 22, |
753 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | | 759 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | |
@@ -761,12 +767,14 @@ void mark_tsc_unstable(char *reason) | |||
761 | { | 767 | { |
762 | if (!tsc_unstable) { | 768 | if (!tsc_unstable) { |
763 | tsc_unstable = 1; | 769 | tsc_unstable = 1; |
764 | printk("Marking TSC unstable due to %s\n", reason); | 770 | printk(KERN_INFO "Marking TSC unstable due to %s\n", reason); |
765 | /* Change only the rating, when not registered */ | 771 | /* Change only the rating, when not registered */ |
766 | if (clocksource_tsc.mult) | 772 | if (clocksource_tsc.mult) |
767 | clocksource_change_rating(&clocksource_tsc, 0); | 773 | clocksource_mark_unstable(&clocksource_tsc); |
768 | else | 774 | else { |
775 | clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE; | ||
769 | clocksource_tsc.rating = 0; | 776 | clocksource_tsc.rating = 0; |
777 | } | ||
770 | } | 778 | } |
771 | } | 779 | } |
772 | 780 | ||
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 25ee06a80aad..cf53a78e2dcf 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c | |||
@@ -87,6 +87,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) | |||
87 | vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; | 87 | vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; |
88 | vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; | 88 | vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; |
89 | vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic; | 89 | vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic; |
90 | vsyscall_gtod_data.wall_time_coarse = __current_kernel_time(); | ||
90 | write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); | 91 | write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); |
91 | } | 92 | } |
92 | 93 | ||
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 6a40b78b46aa..ee55754cc3c5 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c | |||
@@ -86,14 +86,47 @@ notrace static noinline int do_monotonic(struct timespec *ts) | |||
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | notrace static noinline int do_realtime_coarse(struct timespec *ts) | ||
90 | { | ||
91 | unsigned long seq; | ||
92 | do { | ||
93 | seq = read_seqbegin(>od->lock); | ||
94 | ts->tv_sec = gtod->wall_time_coarse.tv_sec; | ||
95 | ts->tv_nsec = gtod->wall_time_coarse.tv_nsec; | ||
96 | } while (unlikely(read_seqretry(>od->lock, seq))); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | notrace static noinline int do_monotonic_coarse(struct timespec *ts) | ||
101 | { | ||
102 | unsigned long seq, ns, secs; | ||
103 | do { | ||
104 | seq = read_seqbegin(>od->lock); | ||
105 | secs = gtod->wall_time_coarse.tv_sec; | ||
106 | ns = gtod->wall_time_coarse.tv_nsec; | ||
107 | secs += gtod->wall_to_monotonic.tv_sec; | ||
108 | ns += gtod->wall_to_monotonic.tv_nsec; | ||
109 | } while (unlikely(read_seqretry(>od->lock, seq))); | ||
110 | vset_normalized_timespec(ts, secs, ns); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
89 | notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts) | 114 | notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts) |
90 | { | 115 | { |
91 | if (likely(gtod->sysctl_enabled && gtod->clock.vread)) | 116 | if (likely(gtod->sysctl_enabled)) |
92 | switch (clock) { | 117 | switch (clock) { |
93 | case CLOCK_REALTIME: | 118 | case CLOCK_REALTIME: |
94 | return do_realtime(ts); | 119 | if (likely(gtod->clock.vread)) |
120 | return do_realtime(ts); | ||
121 | break; | ||
95 | case CLOCK_MONOTONIC: | 122 | case CLOCK_MONOTONIC: |
96 | return do_monotonic(ts); | 123 | if (likely(gtod->clock.vread)) |
124 | return do_monotonic(ts); | ||
125 | break; | ||
126 | case CLOCK_REALTIME_COARSE: | ||
127 | return do_realtime_coarse(ts); | ||
128 | case CLOCK_MONOTONIC_COARSE: | ||
129 | return do_monotonic_coarse(ts); | ||
97 | } | 130 | } |
98 | return vdso_fallback_gettime(clock, ts); | 131 | return vdso_fallback_gettime(clock, ts); |
99 | } | 132 | } |
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 8848120d291b..19085ff0484a 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
@@ -59,9 +59,8 @@ static struct irqaction timer_irqaction = { | |||
59 | 59 | ||
60 | void __init time_init(void) | 60 | void __init time_init(void) |
61 | { | 61 | { |
62 | xtime.tv_nsec = 0; | 62 | /* FIXME: xtime&wall_to_monotonic are set in timekeeping_init. */ |
63 | xtime.tv_sec = read_persistent_clock(); | 63 | read_persistent_clock(&xtime); |
64 | |||
65 | set_normalized_timespec(&wall_to_monotonic, | 64 | set_normalized_timespec(&wall_to_monotonic, |
66 | -xtime.tv_sec, -xtime.tv_nsec); | 65 | -xtime.tv_sec, -xtime.tv_nsec); |
67 | 66 | ||