aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2013-04-03 06:27:29 -0400
committerThomas Gleixner <tglx@linutronix.de>2013-04-03 06:27:29 -0400
commit0ed2aef9b3bffe598045b62a31a50d912eee92d8 (patch)
treed7dda12955c838f531727d2775d09c4e04bdf066 /arch
parentcfea7d7e452f57682a0bb55a55e9f79c569558c2 (diff)
parent8011657b9e63cb2e914b9a0f75233b910c1854cb (diff)
Merge branch 'fortglx/3.10/time' of git://git.linaro.org/people/jstultz/linux into timers/core
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-bcm/Kconfig1
-rw-r--r--arch/arm/mach-bcm/board_bcm.c7
-rw-r--r--arch/s390/include/asm/cpu_mf.h1
-rw-r--r--arch/um/drivers/chan.h2
-rw-r--r--arch/um/drivers/chan_kern.c4
-rw-r--r--arch/um/drivers/chan_user.c12
-rw-r--r--arch/um/drivers/chan_user.h6
-rw-r--r--arch/um/drivers/line.c42
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/um/drivers/ssl.c1
-rw-r--r--arch/um/drivers/stdio_console.c1
-rw-r--r--arch/um/os-Linux/signal.c2
-rw-r--r--arch/um/os-Linux/start_up.c2
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/cpufeature.h1
-rw-r--r--arch/x86/kernel/cpu/intel.c12
-rw-r--r--arch/x86/kernel/rtc.c69
-rw-r--r--arch/x86/kernel/tsc.c6
-rw-r--r--arch/x86/platform/efi/efi.c24
-rw-r--r--arch/x86/platform/mrst/vrtc.c44
20 files changed, 118 insertions, 122 deletions
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index bf02471d7e7c..f11289519c39 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -6,6 +6,7 @@ config ARCH_BCM
6 select ARM_ERRATA_764369 if SMP 6 select ARM_ERRATA_764369 if SMP
7 select ARM_GIC 7 select ARM_GIC
8 select CPU_V7 8 select CPU_V7
9 select CLKSRC_OF
9 select GENERIC_CLOCKEVENTS 10 select GENERIC_CLOCKEVENTS
10 select GENERIC_TIME 11 select GENERIC_TIME
11 select GPIO_BCM 12 select GPIO_BCM
diff --git a/arch/arm/mach-bcm/board_bcm.c b/arch/arm/mach-bcm/board_bcm.c
index f0f9abafad29..259593540477 100644
--- a/arch/arm/mach-bcm/board_bcm.c
+++ b/arch/arm/mach-bcm/board_bcm.c
@@ -16,14 +16,11 @@
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/irqchip.h> 18#include <linux/irqchip.h>
19#include <linux/clocksource.h>
19 20
20#include <asm/mach/arch.h> 21#include <asm/mach/arch.h>
21#include <asm/mach/time.h> 22#include <asm/mach/time.h>
22 23
23static void timer_init(void)
24{
25}
26
27 24
28static void __init board_init(void) 25static void __init board_init(void)
29{ 26{
@@ -35,7 +32,7 @@ static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, };
35 32
36DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor") 33DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor")
37 .init_irq = irqchip_init, 34 .init_irq = irqchip_init,
38 .init_time = timer_init, 35 .init_time = clocksource_of_init,
39 .init_machine = board_init, 36 .init_machine = board_init,
40 .dt_compat = bcm11351_dt_compat, 37 .dt_compat = bcm11351_dt_compat,
41MACHINE_END 38MACHINE_END
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h
index f1eddd150dd7..c879fad404c8 100644
--- a/arch/s390/include/asm/cpu_mf.h
+++ b/arch/s390/include/asm/cpu_mf.h
@@ -12,6 +12,7 @@
12#ifndef _ASM_S390_CPU_MF_H 12#ifndef _ASM_S390_CPU_MF_H
13#define _ASM_S390_CPU_MF_H 13#define _ASM_S390_CPU_MF_H
14 14
15#include <linux/errno.h>
15#include <asm/facility.h> 16#include <asm/facility.h>
16 17
17#define CPU_MF_INT_SF_IAE (1 << 31) /* invalid entry address */ 18#define CPU_MF_INT_SF_IAE (1 << 31) /* invalid entry address */
diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h
index 78f1b8999964..c512b0306dd4 100644
--- a/arch/um/drivers/chan.h
+++ b/arch/um/drivers/chan.h
@@ -37,7 +37,7 @@ extern int console_write_chan(struct chan *chan, const char *buf,
37extern int console_open_chan(struct line *line, struct console *co); 37extern int console_open_chan(struct line *line, struct console *co);
38extern void deactivate_chan(struct chan *chan, int irq); 38extern void deactivate_chan(struct chan *chan, int irq);
39extern void reactivate_chan(struct chan *chan, int irq); 39extern void reactivate_chan(struct chan *chan, int irq);
40extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty); 40extern void chan_enable_winch(struct chan *chan, struct tty_port *port);
41extern int enable_chan(struct line *line); 41extern int enable_chan(struct line *line);
42extern void close_chan(struct line *line); 42extern void close_chan(struct line *line);
43extern int chan_window_size(struct line *line, 43extern int chan_window_size(struct line *line,
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 15c553c239a1..80b47cb71e0a 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -122,10 +122,10 @@ static int open_chan(struct list_head *chans)
122 return err; 122 return err;
123} 123}
124 124
125void chan_enable_winch(struct chan *chan, struct tty_struct *tty) 125void chan_enable_winch(struct chan *chan, struct tty_port *port)
126{ 126{
127 if (chan && chan->primary && chan->ops->winch) 127 if (chan && chan->primary && chan->ops->winch)
128 register_winch(chan->fd, tty); 128 register_winch(chan->fd, port);
129} 129}
130 130
131static void line_timer_cb(struct work_struct *work) 131static void line_timer_cb(struct work_struct *work)
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 9be670ad23b5..3fd7c3efdb18 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -216,7 +216,7 @@ static int winch_thread(void *arg)
216 } 216 }
217} 217}
218 218
219static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, 219static int winch_tramp(int fd, struct tty_port *port, int *fd_out,
220 unsigned long *stack_out) 220 unsigned long *stack_out)
221{ 221{
222 struct winch_data data; 222 struct winch_data data;
@@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
271 return err; 271 return err;
272} 272}
273 273
274void register_winch(int fd, struct tty_struct *tty) 274void register_winch(int fd, struct tty_port *port)
275{ 275{
276 unsigned long stack; 276 unsigned long stack;
277 int pid, thread, count, thread_fd = -1; 277 int pid, thread, count, thread_fd = -1;
@@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty)
281 return; 281 return;
282 282
283 pid = tcgetpgrp(fd); 283 pid = tcgetpgrp(fd);
284 if (is_skas_winch(pid, fd, tty)) { 284 if (is_skas_winch(pid, fd, port)) {
285 register_winch_irq(-1, fd, -1, tty, 0); 285 register_winch_irq(-1, fd, -1, port, 0);
286 return; 286 return;
287 } 287 }
288 288
289 if (pid == -1) { 289 if (pid == -1) {
290 thread = winch_tramp(fd, tty, &thread_fd, &stack); 290 thread = winch_tramp(fd, port, &thread_fd, &stack);
291 if (thread < 0) 291 if (thread < 0)
292 return; 292 return;
293 293
294 register_winch_irq(thread_fd, fd, thread, tty, stack); 294 register_winch_irq(thread_fd, fd, thread, port, stack);
295 295
296 count = write(thread_fd, &c, sizeof(c)); 296 count = write(thread_fd, &c, sizeof(c));
297 if (count != sizeof(c)) 297 if (count != sizeof(c))
diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h
index dc693298eb8f..03f1b565c5f9 100644
--- a/arch/um/drivers/chan_user.h
+++ b/arch/um/drivers/chan_user.h
@@ -38,10 +38,10 @@ extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
38 unsigned short *cols_out); 38 unsigned short *cols_out);
39extern void generic_free(void *data); 39extern void generic_free(void *data);
40 40
41struct tty_struct; 41struct tty_port;
42extern void register_winch(int fd, struct tty_struct *tty); 42extern void register_winch(int fd, struct tty_port *port);
43extern void register_winch_irq(int fd, int tty_fd, int pid, 43extern void register_winch_irq(int fd, int tty_fd, int pid,
44 struct tty_struct *tty, unsigned long stack); 44 struct tty_port *port, unsigned long stack);
45 45
46#define __channel_help(fn, prefix) \ 46#define __channel_help(fn, prefix) \
47__uml_help(fn, prefix "[0-9]*=<channel description>\n" \ 47__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index f1b38571f94e..be541cf69fd2 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -305,7 +305,7 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty)
305 return ret; 305 return ret;
306 306
307 if (!line->sigio) { 307 if (!line->sigio) {
308 chan_enable_winch(line->chan_out, tty); 308 chan_enable_winch(line->chan_out, port);
309 line->sigio = 1; 309 line->sigio = 1;
310 } 310 }
311 311
@@ -315,8 +315,22 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty)
315 return 0; 315 return 0;
316} 316}
317 317
318static void unregister_winch(struct tty_struct *tty);
319
320static void line_destruct(struct tty_port *port)
321{
322 struct tty_struct *tty = tty_port_tty_get(port);
323 struct line *line = tty->driver_data;
324
325 if (line->sigio) {
326 unregister_winch(tty);
327 line->sigio = 0;
328 }
329}
330
318static const struct tty_port_operations line_port_ops = { 331static const struct tty_port_operations line_port_ops = {
319 .activate = line_activate, 332 .activate = line_activate,
333 .destruct = line_destruct,
320}; 334};
321 335
322int line_open(struct tty_struct *tty, struct file *filp) 336int line_open(struct tty_struct *tty, struct file *filp)
@@ -340,18 +354,6 @@ int line_install(struct tty_driver *driver, struct tty_struct *tty,
340 return 0; 354 return 0;
341} 355}
342 356
343static void unregister_winch(struct tty_struct *tty);
344
345void line_cleanup(struct tty_struct *tty)
346{
347 struct line *line = tty->driver_data;
348
349 if (line->sigio) {
350 unregister_winch(tty);
351 line->sigio = 0;
352 }
353}
354
355void line_close(struct tty_struct *tty, struct file * filp) 357void line_close(struct tty_struct *tty, struct file * filp)
356{ 358{
357 struct line *line = tty->driver_data; 359 struct line *line = tty->driver_data;
@@ -601,7 +603,7 @@ struct winch {
601 int fd; 603 int fd;
602 int tty_fd; 604 int tty_fd;
603 int pid; 605 int pid;
604 struct tty_struct *tty; 606 struct tty_port *port;
605 unsigned long stack; 607 unsigned long stack;
606 struct work_struct work; 608 struct work_struct work;
607}; 609};
@@ -655,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
655 goto out; 657 goto out;
656 } 658 }
657 } 659 }
658 tty = winch->tty; 660 tty = tty_port_tty_get(winch->port);
659 if (tty != NULL) { 661 if (tty != NULL) {
660 line = tty->driver_data; 662 line = tty->driver_data;
661 if (line != NULL) { 663 if (line != NULL) {
@@ -663,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
663 &tty->winsize.ws_col); 665 &tty->winsize.ws_col);
664 kill_pgrp(tty->pgrp, SIGWINCH, 1); 666 kill_pgrp(tty->pgrp, SIGWINCH, 1);
665 } 667 }
668 tty_kref_put(tty);
666 } 669 }
667 out: 670 out:
668 if (winch->fd != -1) 671 if (winch->fd != -1)
@@ -670,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
670 return IRQ_HANDLED; 673 return IRQ_HANDLED;
671} 674}
672 675
673void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, 676void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
674 unsigned long stack) 677 unsigned long stack)
675{ 678{
676 struct winch *winch; 679 struct winch *winch;
@@ -685,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
685 .fd = fd, 688 .fd = fd,
686 .tty_fd = tty_fd, 689 .tty_fd = tty_fd,
687 .pid = pid, 690 .pid = pid,
688 .tty = tty, 691 .port = port,
689 .stack = stack }); 692 .stack = stack });
690 693
691 if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 694 if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
@@ -714,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty)
714{ 717{
715 struct list_head *ele, *next; 718 struct list_head *ele, *next;
716 struct winch *winch; 719 struct winch *winch;
720 struct tty_struct *wtty;
717 721
718 spin_lock(&winch_handler_lock); 722 spin_lock(&winch_handler_lock);
719 723
720 list_for_each_safe(ele, next, &winch_handlers) { 724 list_for_each_safe(ele, next, &winch_handlers) {
721 winch = list_entry(ele, struct winch, list); 725 winch = list_entry(ele, struct winch, list);
722 if (winch->tty == tty) { 726 wtty = tty_port_tty_get(winch->port);
727 if (wtty == tty) {
723 free_winch(winch); 728 free_winch(winch);
724 break; 729 break;
725 } 730 }
731 tty_kref_put(wtty);
726 } 732 }
727 spin_unlock(&winch_handler_lock); 733 spin_unlock(&winch_handler_lock);
728} 734}
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index d8926c303629..39f186252e02 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -218,6 +218,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
218 spin_lock_irqsave(&lp->lock, flags); 218 spin_lock_irqsave(&lp->lock, flags);
219 219
220 len = (*lp->write)(lp->fd, skb, lp); 220 len = (*lp->write)(lp->fd, skb, lp);
221 skb_tx_timestamp(skb);
221 222
222 if (len == skb->len) { 223 if (len == skb->len) {
223 dev->stats.tx_packets++; 224 dev->stats.tx_packets++;
@@ -281,6 +282,7 @@ static void uml_net_get_drvinfo(struct net_device *dev,
281static const struct ethtool_ops uml_net_ethtool_ops = { 282static const struct ethtool_ops uml_net_ethtool_ops = {
282 .get_drvinfo = uml_net_get_drvinfo, 283 .get_drvinfo = uml_net_get_drvinfo,
283 .get_link = ethtool_op_get_link, 284 .get_link = ethtool_op_get_link,
285 .get_ts_info = ethtool_op_get_ts_info,
284}; 286};
285 287
286static void uml_net_user_timer_expire(unsigned long _conn) 288static void uml_net_user_timer_expire(unsigned long _conn)
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 16fdd0a0f9d6..b8d14fa52059 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -105,7 +105,6 @@ static const struct tty_operations ssl_ops = {
105 .throttle = line_throttle, 105 .throttle = line_throttle,
106 .unthrottle = line_unthrottle, 106 .unthrottle = line_unthrottle,
107 .install = ssl_install, 107 .install = ssl_install,
108 .cleanup = line_cleanup,
109 .hangup = line_hangup, 108 .hangup = line_hangup,
110}; 109};
111 110
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 827777af3f6d..7b361f36ca96 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -110,7 +110,6 @@ static const struct tty_operations console_ops = {
110 .set_termios = line_set_termios, 110 .set_termios = line_set_termios,
111 .throttle = line_throttle, 111 .throttle = line_throttle,
112 .unthrottle = line_unthrottle, 112 .unthrottle = line_unthrottle,
113 .cleanup = line_cleanup,
114 .hangup = line_hangup, 113 .hangup = line_hangup,
115}; 114};
116 115
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index b1469fe93295..9d9f1b4bf826 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,7 +15,7 @@
15#include <sysdep/mcontext.h> 15#include <sysdep/mcontext.h>
16#include "internal.h" 16#include "internal.h"
17 17
18void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { 18void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
19 [SIGTRAP] = relay_signal, 19 [SIGTRAP] = relay_signal,
20 [SIGFPE] = relay_signal, 20 [SIGFPE] = relay_signal,
21 [SIGILL] = relay_signal, 21 [SIGILL] = relay_signal,
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index da4b9e9999fd..337518c5042a 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -15,6 +15,8 @@
15#include <sys/mman.h> 15#include <sys/mman.h>
16#include <sys/stat.h> 16#include <sys/stat.h>
17#include <sys/wait.h> 17#include <sys/wait.h>
18#include <sys/time.h>
19#include <sys/resource.h>
18#include <asm/unistd.h> 20#include <asm/unistd.h>
19#include <init.h> 21#include <init.h>
20#include <os.h> 22#include <os.h>
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index a4f24f5b1218..26bd79261532 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -120,6 +120,7 @@ config X86
120 select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION 120 select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
121 select OLD_SIGACTION if X86_32 121 select OLD_SIGACTION if X86_32
122 select COMPAT_OLD_SIGACTION if IA32_EMULATION 122 select COMPAT_OLD_SIGACTION if IA32_EMULATION
123 select RTC_LIB
123 124
124config INSTRUCTION_DECODER 125config INSTRUCTION_DECODER
125 def_bool y 126 def_bool y
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 93fe929d1cee..a8466f203e62 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -100,6 +100,7 @@
100#define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ 100#define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */
101#define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */ 101#define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */
102#define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */ 102#define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */
103#define X86_FEATURE_NONSTOP_TSC_S3 (3*32+30) /* TSC doesn't stop in S3 state */
103 104
104/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ 105/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
105#define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ 106#define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1905ce98bee0..e7ae0d89e7e0 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -96,6 +96,18 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
96 sched_clock_stable = 1; 96 sched_clock_stable = 1;
97 } 97 }
98 98
99 /* Penwell and Cloverview have the TSC which doesn't sleep on S3 */
100 if (c->x86 == 6) {
101 switch (c->x86_model) {
102 case 0x27: /* Penwell */
103 case 0x35: /* Cloverview */
104 set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3);
105 break;
106 default:
107 break;
108 }
109 }
110
99 /* 111 /*
100 * There is a known erratum on Pentium III and Core Solo 112 * There is a known erratum on Pentium III and Core Solo
101 * and Core Duo CPUs. 113 * and Core Duo CPUs.
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 2e8f3d3b5641..198eb201ed3b 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -13,6 +13,7 @@
13#include <asm/x86_init.h> 13#include <asm/x86_init.h>
14#include <asm/time.h> 14#include <asm/time.h>
15#include <asm/mrst.h> 15#include <asm/mrst.h>
16#include <asm/rtc.h>
16 17
17#ifdef CONFIG_X86_32 18#ifdef CONFIG_X86_32
18/* 19/*
@@ -36,70 +37,24 @@ EXPORT_SYMBOL(rtc_lock);
36 * nowtime is written into the registers of the CMOS clock, it will 37 * nowtime is written into the registers of the CMOS clock, it will
37 * jump to the next second precisely 500 ms later. Check the Motorola 38 * jump to the next second precisely 500 ms later. Check the Motorola
38 * MC146818A or Dallas DS12887 data sheet for details. 39 * MC146818A or Dallas DS12887 data sheet for details.
39 *
40 * BUG: This routine does not handle hour overflow properly; it just
41 * sets the minutes. Usually you'll only notice that after reboot!
42 */ 40 */
43int mach_set_rtc_mmss(unsigned long nowtime) 41int mach_set_rtc_mmss(unsigned long nowtime)
44{ 42{
45 int real_seconds, real_minutes, cmos_minutes; 43 struct rtc_time tm;
46 unsigned char save_control, save_freq_select;
47 unsigned long flags;
48 int retval = 0; 44 int retval = 0;
49 45
50 spin_lock_irqsave(&rtc_lock, flags); 46 rtc_time_to_tm(nowtime, &tm);
51 47 if (!rtc_valid_tm(&tm)) {
52 /* tell the clock it's being set */ 48 retval = set_rtc_time(&tm);
53 save_control = CMOS_READ(RTC_CONTROL); 49 if (retval)
54 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 50 printk(KERN_ERR "%s: RTC write failed with error %d\n",
55 51 __FUNCTION__, retval);
56 /* stop and reset prescaler */
57 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
58 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
59
60 cmos_minutes = CMOS_READ(RTC_MINUTES);
61 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
62 cmos_minutes = bcd2bin(cmos_minutes);
63
64 /*
65 * since we're only adjusting minutes and seconds,
66 * don't interfere with hour overflow. This avoids
67 * messing with unknown time zones but requires your
68 * RTC not to be off by more than 15 minutes
69 */
70 real_seconds = nowtime % 60;
71 real_minutes = nowtime / 60;
72 /* correct for half hour time zone */
73 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
74 real_minutes += 30;
75 real_minutes %= 60;
76
77 if (abs(real_minutes - cmos_minutes) < 30) {
78 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
79 real_seconds = bin2bcd(real_seconds);
80 real_minutes = bin2bcd(real_minutes);
81 }
82 CMOS_WRITE(real_seconds, RTC_SECONDS);
83 CMOS_WRITE(real_minutes, RTC_MINUTES);
84 } else { 52 } else {
85 printk_once(KERN_NOTICE 53 printk(KERN_ERR
86 "set_rtc_mmss: can't update from %d to %d\n", 54 "%s: Invalid RTC value: write of %lx to RTC failed\n",
87 cmos_minutes, real_minutes); 55 __FUNCTION__, nowtime);
88 retval = -1; 56 retval = -EINVAL;
89 } 57 }
90
91 /* The following flags have to be released exactly in this order,
92 * otherwise the DS12887 (popular MC146818A clone with integrated
93 * battery and quartz) will not reset the oscillator and will not
94 * update precisely 500 ms later. You won't find this mentioned in
95 * the Dallas Semiconductor data sheets, but who believes data
96 * sheets anyway ... -- Markus Kuhn
97 */
98 CMOS_WRITE(save_control, RTC_CONTROL);
99 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
100
101 spin_unlock_irqrestore(&rtc_lock, flags);
102
103 return retval; 58 return retval;
104} 59}
105 60
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 4b9ea101fe3b..098b3cfda72e 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -768,7 +768,8 @@ static cycle_t read_tsc(struct clocksource *cs)
768 768
769static void resume_tsc(struct clocksource *cs) 769static void resume_tsc(struct clocksource *cs)
770{ 770{
771 clocksource_tsc.cycle_last = 0; 771 if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
772 clocksource_tsc.cycle_last = 0;
772} 773}
773 774
774static struct clocksource clocksource_tsc = { 775static struct clocksource clocksource_tsc = {
@@ -939,6 +940,9 @@ static int __init init_tsc_clocksource(void)
939 clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; 940 clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
940 } 941 }
941 942
943 if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
944 clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
945
942 /* 946 /*
943 * Trust the results of the earlier calibration on systems 947 * Trust the results of the earlier calibration on systems
944 * exporting a reliable TSC. 948 * exporting a reliable TSC.
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5f2ecaf3f9d8..28d9efacc9b6 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -48,6 +48,7 @@
48#include <asm/cacheflush.h> 48#include <asm/cacheflush.h>
49#include <asm/tlbflush.h> 49#include <asm/tlbflush.h>
50#include <asm/x86_init.h> 50#include <asm/x86_init.h>
51#include <asm/rtc.h>
51 52
52#define EFI_DEBUG 1 53#define EFI_DEBUG 1
53 54
@@ -258,10 +259,10 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
258 259
259int efi_set_rtc_mmss(unsigned long nowtime) 260int efi_set_rtc_mmss(unsigned long nowtime)
260{ 261{
261 int real_seconds, real_minutes;
262 efi_status_t status; 262 efi_status_t status;
263 efi_time_t eft; 263 efi_time_t eft;
264 efi_time_cap_t cap; 264 efi_time_cap_t cap;
265 struct rtc_time tm;
265 266
266 status = efi.get_time(&eft, &cap); 267 status = efi.get_time(&eft, &cap);
267 if (status != EFI_SUCCESS) { 268 if (status != EFI_SUCCESS) {
@@ -269,13 +270,20 @@ int efi_set_rtc_mmss(unsigned long nowtime)
269 return -1; 270 return -1;
270 } 271 }
271 272
272 real_seconds = nowtime % 60; 273 rtc_time_to_tm(nowtime, &tm);
273 real_minutes = nowtime / 60; 274 if (!rtc_valid_tm(&tm)) {
274 if (((abs(real_minutes - eft.minute) + 15)/30) & 1) 275 eft.year = tm.tm_year + 1900;
275 real_minutes += 30; 276 eft.month = tm.tm_mon + 1;
276 real_minutes %= 60; 277 eft.day = tm.tm_mday;
277 eft.minute = real_minutes; 278 eft.minute = tm.tm_min;
278 eft.second = real_seconds; 279 eft.second = tm.tm_sec;
280 eft.nanosecond = 0;
281 } else {
282 printk(KERN_ERR
283 "%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
284 __FUNCTION__, nowtime);
285 return -1;
286 }
279 287
280 status = efi.set_time(&eft); 288 status = efi.set_time(&eft);
281 if (status != EFI_SUCCESS) { 289 if (status != EFI_SUCCESS) {
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
index 225bd0f0f675..d62b0a3b5c14 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -85,27 +85,35 @@ unsigned long vrtc_get_time(void)
85 return mktime(year, mon, mday, hour, min, sec); 85 return mktime(year, mon, mday, hour, min, sec);
86} 86}
87 87
88/* Only care about the minutes and seconds */
89int vrtc_set_mmss(unsigned long nowtime) 88int vrtc_set_mmss(unsigned long nowtime)
90{ 89{
91 int real_sec, real_min;
92 unsigned long flags; 90 unsigned long flags;
93 int vrtc_min; 91 struct rtc_time tm;
94 92 int year;
95 spin_lock_irqsave(&rtc_lock, flags); 93 int retval = 0;
96 vrtc_min = vrtc_cmos_read(RTC_MINUTES); 94
97 95 rtc_time_to_tm(nowtime, &tm);
98 real_sec = nowtime % 60; 96 if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {
99 real_min = nowtime / 60; 97 /*
100 if (((abs(real_min - vrtc_min) + 15)/30) & 1) 98 * tm.year is the number of years since 1900, and the
101 real_min += 30; 99 * vrtc need the years since 1972.
102 real_min %= 60; 100 */
103 101 year = tm.tm_year - 72;
104 vrtc_cmos_write(real_sec, RTC_SECONDS); 102 spin_lock_irqsave(&rtc_lock, flags);
105 vrtc_cmos_write(real_min, RTC_MINUTES); 103 vrtc_cmos_write(year, RTC_YEAR);
106 spin_unlock_irqrestore(&rtc_lock, flags); 104 vrtc_cmos_write(tm.tm_mon, RTC_MONTH);
107 105 vrtc_cmos_write(tm.tm_mday, RTC_DAY_OF_MONTH);
108 return 0; 106 vrtc_cmos_write(tm.tm_hour, RTC_HOURS);
107 vrtc_cmos_write(tm.tm_min, RTC_MINUTES);
108 vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
109 spin_unlock_irqrestore(&rtc_lock, flags);
110 } else {
111 printk(KERN_ERR
112 "%s: Invalid vRTC value: write of %lx to vRTC failed\n",
113 __FUNCTION__, nowtime);
114 retval = -EINVAL;
115 }
116 return retval;
109} 117}
110 118
111void __init mrst_rtc_init(void) 119void __init mrst_rtc_init(void)