aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/time.c')
-rw-r--r--arch/s390/kernel/time.c256
1 files changed, 73 insertions, 183 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 925f9dc0b0a0..17c4de9e1b6b 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -30,7 +30,7 @@
30#include <linux/timex.h> 30#include <linux/timex.h>
31#include <linux/notifier.h> 31#include <linux/notifier.h>
32#include <linux/clocksource.h> 32#include <linux/clocksource.h>
33 33#include <linux/clockchips.h>
34#include <asm/uaccess.h> 34#include <asm/uaccess.h>
35#include <asm/delay.h> 35#include <asm/delay.h>
36#include <asm/s390_ext.h> 36#include <asm/s390_ext.h>
@@ -57,9 +57,9 @@
57 57
58static ext_int_info_t ext_int_info_cc; 58static ext_int_info_t ext_int_info_cc;
59static ext_int_info_t ext_int_etr_cc; 59static ext_int_info_t ext_int_etr_cc;
60static u64 init_timer_cc;
61static u64 jiffies_timer_cc; 60static u64 jiffies_timer_cc;
62static u64 xtime_cc; 61
62static DEFINE_PER_CPU(struct clock_event_device, comparators);
63 63
64/* 64/*
65 * Scheduler clock - returns current time in nanosec units. 65 * Scheduler clock - returns current time in nanosec units.
@@ -95,162 +95,40 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime)
95#define s390_do_profile() do { ; } while(0) 95#define s390_do_profile() do { ; } while(0)
96#endif /* CONFIG_PROFILING */ 96#endif /* CONFIG_PROFILING */
97 97
98/* 98void clock_comparator_work(void)
99 * Advance the per cpu tick counter up to the time given with the
100 * "time" argument. The per cpu update consists of accounting
101 * the virtual cpu time, calling update_process_times and calling
102 * the profiling hook. If xtime is before time it is advanced as well.
103 */
104void account_ticks(u64 time)
105{ 99{
106 __u32 ticks; 100 struct clock_event_device *cd;
107 __u64 tmp;
108
109 /* Calculate how many ticks have passed. */
110 if (time < S390_lowcore.jiffy_timer)
111 return;
112 tmp = time - S390_lowcore.jiffy_timer;
113 if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */
114 ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
115 S390_lowcore.jiffy_timer +=
116 CLK_TICKS_PER_JIFFY * (__u64) ticks;
117 } else if (tmp >= CLK_TICKS_PER_JIFFY) {
118 ticks = 2;
119 S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
120 } else {
121 ticks = 1;
122 S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
123 }
124
125#ifdef CONFIG_SMP
126 /*
127 * Do not rely on the boot cpu to do the calls to do_timer.
128 * Spread it over all cpus instead.
129 */
130 write_seqlock(&xtime_lock);
131 if (S390_lowcore.jiffy_timer > xtime_cc) {
132 __u32 xticks;
133 tmp = S390_lowcore.jiffy_timer - xtime_cc;
134 if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
135 xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
136 xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
137 } else {
138 xticks = 1;
139 xtime_cc += CLK_TICKS_PER_JIFFY;
140 }
141 do_timer(xticks);
142 }
143 write_sequnlock(&xtime_lock);
144#else
145 do_timer(ticks);
146#endif
147
148 while (ticks--)
149 update_process_times(user_mode(get_irq_regs()));
150 101
102 S390_lowcore.clock_comparator = -1ULL;
103 set_clock_comparator(S390_lowcore.clock_comparator);
104 cd = &__get_cpu_var(comparators);
105 cd->event_handler(cd);
151 s390_do_profile(); 106 s390_do_profile();
152} 107}
153 108
154#ifdef CONFIG_NO_IDLE_HZ
155
156#ifdef CONFIG_NO_IDLE_HZ_INIT
157int sysctl_hz_timer = 0;
158#else
159int sysctl_hz_timer = 1;
160#endif
161
162/*
163 * Stop the HZ tick on the current CPU.
164 * Only cpu_idle may call this function.
165 */
166static void stop_hz_timer(void)
167{
168 unsigned long flags;
169 unsigned long seq, next;
170 __u64 timer, todval;
171 int cpu = smp_processor_id();
172
173 if (sysctl_hz_timer != 0)
174 return;
175
176 cpu_set(cpu, nohz_cpu_mask);
177
178 /*
179 * Leave the clock comparator set up for the next timer
180 * tick if either rcu or a softirq is pending.
181 */
182 if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
183 cpu_clear(cpu, nohz_cpu_mask);
184 return;
185 }
186
187 /*
188 * This cpu is going really idle. Set up the clock comparator
189 * for the next event.
190 */
191 next = next_timer_interrupt();
192 do {
193 seq = read_seqbegin_irqsave(&xtime_lock, flags);
194 timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64;
195 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
196 todval = -1ULL;
197 /* Be careful about overflows. */
198 if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
199 timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
200 if (timer >= jiffies_timer_cc)
201 todval = timer;
202 }
203 set_clock_comparator(todval);
204}
205
206/* 109/*
207 * Start the HZ tick on the current CPU. 110 * Fixup the clock comparator.
208 * Only cpu_idle may call this function.
209 */ 111 */
210static void start_hz_timer(void) 112static void fixup_clock_comparator(unsigned long long delta)
211{ 113{
212 if (!cpu_isset(smp_processor_id(), nohz_cpu_mask)) 114 /* If nobody is waiting there's nothing to fix. */
115 if (S390_lowcore.clock_comparator == -1ULL)
213 return; 116 return;
214 account_ticks(get_clock()); 117 S390_lowcore.clock_comparator += delta;
215 set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); 118 set_clock_comparator(S390_lowcore.clock_comparator);
216 cpu_clear(smp_processor_id(), nohz_cpu_mask);
217}
218
219static int nohz_idle_notify(struct notifier_block *self,
220 unsigned long action, void *hcpu)
221{
222 switch (action) {
223 case S390_CPU_IDLE:
224 stop_hz_timer();
225 break;
226 case S390_CPU_NOT_IDLE:
227 start_hz_timer();
228 break;
229 }
230 return NOTIFY_OK;
231} 119}
232 120
233static struct notifier_block nohz_idle_nb = { 121static int s390_next_event(unsigned long delta,
234 .notifier_call = nohz_idle_notify, 122 struct clock_event_device *evt)
235};
236
237static void __init nohz_init(void)
238{ 123{
239 if (register_idle_notifier(&nohz_idle_nb)) 124 S390_lowcore.clock_comparator = get_clock() + delta;
240 panic("Couldn't register idle notifier"); 125 set_clock_comparator(S390_lowcore.clock_comparator);
126 return 0;
241} 127}
242 128
243#endif 129static void s390_set_mode(enum clock_event_mode mode,
244 130 struct clock_event_device *evt)
245/*
246 * Set up per cpu jiffy timer and set the clock comparator.
247 */
248static void setup_jiffy_timer(void)
249{ 131{
250 /* Set up clock comparator to next jiffy. */
251 S390_lowcore.jiffy_timer =
252 jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY;
253 set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
254} 132}
255 133
256/* 134/*
@@ -259,7 +137,26 @@ static void setup_jiffy_timer(void)
259 */ 137 */
260void init_cpu_timer(void) 138void init_cpu_timer(void)
261{ 139{
262 setup_jiffy_timer(); 140 struct clock_event_device *cd;
141 int cpu;
142
143 S390_lowcore.clock_comparator = -1ULL;
144 set_clock_comparator(S390_lowcore.clock_comparator);
145
146 cpu = smp_processor_id();
147 cd = &per_cpu(comparators, cpu);
148 cd->name = "comparator";
149 cd->features = CLOCK_EVT_FEAT_ONESHOT;
150 cd->mult = 16777;
151 cd->shift = 12;
152 cd->min_delta_ns = 1;
153 cd->max_delta_ns = LONG_MAX;
154 cd->rating = 400;
155 cd->cpumask = cpumask_of_cpu(cpu);
156 cd->set_next_event = s390_next_event;
157 cd->set_mode = s390_set_mode;
158
159 clockevents_register_device(cd);
263 160
264 /* Enable clock comparator timer interrupt. */ 161 /* Enable clock comparator timer interrupt. */
265 __ctl_set_bit(0,11); 162 __ctl_set_bit(0,11);
@@ -270,8 +167,6 @@ void init_cpu_timer(void)
270 167
271static void clock_comparator_interrupt(__u16 code) 168static void clock_comparator_interrupt(__u16 code)
272{ 169{
273 /* set clock comparator for next tick */
274 set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
275} 170}
276 171
277static void etr_reset(void); 172static void etr_reset(void);
@@ -316,8 +211,9 @@ static struct clocksource clocksource_tod = {
316 */ 211 */
317void __init time_init(void) 212void __init time_init(void)
318{ 213{
214 u64 init_timer_cc;
215
319 init_timer_cc = reset_tod_clock(); 216 init_timer_cc = reset_tod_clock();
320 xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
321 jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY; 217 jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
322 218
323 /* set xtime */ 219 /* set xtime */
@@ -342,10 +238,6 @@ void __init time_init(void)
342 /* Enable TOD clock interrupts on the boot cpu. */ 238 /* Enable TOD clock interrupts on the boot cpu. */
343 init_cpu_timer(); 239 init_cpu_timer();
344 240
345#ifdef CONFIG_NO_IDLE_HZ
346 nohz_init();
347#endif
348
349#ifdef CONFIG_VIRT_TIMER 241#ifdef CONFIG_VIRT_TIMER
350 vtime_init(); 242 vtime_init();
351#endif 243#endif
@@ -699,53 +591,49 @@ static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p)
699} 591}
700 592
701/* 593/*
702 * The time is "clock". xtime is what we think the time is. 594 * The time is "clock". old is what we think the time is.
703 * Adjust the value by a multiple of jiffies and add the delta to ntp. 595 * Adjust the value by a multiple of jiffies and add the delta to ntp.
704 * "delay" is an approximation how long the synchronization took. If 596 * "delay" is an approximation how long the synchronization took. If
705 * the time correction is positive, then "delay" is subtracted from 597 * the time correction is positive, then "delay" is subtracted from
706 * the time difference and only the remaining part is passed to ntp. 598 * the time difference and only the remaining part is passed to ntp.
707 */ 599 */
708static void etr_adjust_time(unsigned long long clock, unsigned long long delay) 600static unsigned long long etr_adjust_time(unsigned long long old,
601 unsigned long long clock,
602 unsigned long long delay)
709{ 603{
710 unsigned long long delta, ticks; 604 unsigned long long delta, ticks;
711 struct timex adjust; 605 struct timex adjust;
712 606
713 /* 607 if (clock > old) {
714 * We don't have to take the xtime lock because the cpu
715 * executing etr_adjust_time is running disabled in
716 * tasklet context and all other cpus are looping in
717 * etr_sync_cpu_start.
718 */
719 if (clock > xtime_cc) {
720 /* It is later than we thought. */ 608 /* It is later than we thought. */
721 delta = ticks = clock - xtime_cc; 609 delta = ticks = clock - old;
722 delta = ticks = (delta < delay) ? 0 : delta - delay; 610 delta = ticks = (delta < delay) ? 0 : delta - delay;
723 delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); 611 delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
724 init_timer_cc = init_timer_cc + delta;
725 jiffies_timer_cc = jiffies_timer_cc + delta;
726 xtime_cc = xtime_cc + delta;
727 adjust.offset = ticks * (1000000 / HZ); 612 adjust.offset = ticks * (1000000 / HZ);
728 } else { 613 } else {
729 /* It is earlier than we thought. */ 614 /* It is earlier than we thought. */
730 delta = ticks = xtime_cc - clock; 615 delta = ticks = old - clock;
731 delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); 616 delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
732 init_timer_cc = init_timer_cc - delta; 617 delta = -delta;
733 jiffies_timer_cc = jiffies_timer_cc - delta;
734 xtime_cc = xtime_cc - delta;
735 adjust.offset = -ticks * (1000000 / HZ); 618 adjust.offset = -ticks * (1000000 / HZ);
736 } 619 }
620 jiffies_timer_cc += delta;
737 if (adjust.offset != 0) { 621 if (adjust.offset != 0) {
738 printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n", 622 printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
739 adjust.offset); 623 adjust.offset);
740 adjust.modes = ADJ_OFFSET_SINGLESHOT; 624 adjust.modes = ADJ_OFFSET_SINGLESHOT;
741 do_adjtimex(&adjust); 625 do_adjtimex(&adjust);
742 } 626 }
627 return delta;
743} 628}
744 629
630static struct {
631 int in_sync;
632 unsigned long long fixup_cc;
633} etr_sync;
634
745static void etr_sync_cpu_start(void *dummy) 635static void etr_sync_cpu_start(void *dummy)
746{ 636{
747 int *in_sync = dummy;
748
749 etr_enable_sync_clock(); 637 etr_enable_sync_clock();
750 /* 638 /*
751 * This looks like a busy wait loop but it isn't. etr_sync_cpus 639 * This looks like a busy wait loop but it isn't. etr_sync_cpus
@@ -753,7 +641,7 @@ static void etr_sync_cpu_start(void *dummy)
753 * __udelay will stop the cpu on an enabled wait psw until the 641 * __udelay will stop the cpu on an enabled wait psw until the
754 * TOD is running again. 642 * TOD is running again.
755 */ 643 */
756 while (*in_sync == 0) { 644 while (etr_sync.in_sync == 0) {
757 __udelay(1); 645 __udelay(1);
758 /* 646 /*
759 * A different cpu changes *in_sync. Therefore use 647 * A different cpu changes *in_sync. Therefore use
@@ -761,14 +649,14 @@ static void etr_sync_cpu_start(void *dummy)
761 */ 649 */
762 barrier(); 650 barrier();
763 } 651 }
764 if (*in_sync != 1) 652 if (etr_sync.in_sync != 1)
765 /* Didn't work. Clear per-cpu in sync bit again. */ 653 /* Didn't work. Clear per-cpu in sync bit again. */
766 etr_disable_sync_clock(NULL); 654 etr_disable_sync_clock(NULL);
767 /* 655 /*
768 * This round of TOD syncing is done. Set the clock comparator 656 * This round of TOD syncing is done. Set the clock comparator
769 * to the next tick and let the processor continue. 657 * to the next tick and let the processor continue.
770 */ 658 */
771 setup_jiffy_timer(); 659 fixup_clock_comparator(etr_sync.fixup_cc);
772} 660}
773 661
774static void etr_sync_cpu_end(void *dummy) 662static void etr_sync_cpu_end(void *dummy)
@@ -783,8 +671,8 @@ static void etr_sync_cpu_end(void *dummy)
783static int etr_sync_clock(struct etr_aib *aib, int port) 671static int etr_sync_clock(struct etr_aib *aib, int port)
784{ 672{
785 struct etr_aib *sync_port; 673 struct etr_aib *sync_port;
786 unsigned long long clock, delay; 674 unsigned long long clock, old_clock, delay, delta;
787 int in_sync, follows; 675 int follows;
788 int rc; 676 int rc;
789 677
790 /* Check if the current aib is adjacent to the sync port aib. */ 678 /* Check if the current aib is adjacent to the sync port aib. */
@@ -799,9 +687,9 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
799 * successfully synced the clock. smp_call_function will 687 * successfully synced the clock. smp_call_function will
800 * return after all other cpus are in etr_sync_cpu_start. 688 * return after all other cpus are in etr_sync_cpu_start.
801 */ 689 */
802 in_sync = 0; 690 memset(&etr_sync, 0, sizeof(etr_sync));
803 preempt_disable(); 691 preempt_disable();
804 smp_call_function(etr_sync_cpu_start,&in_sync,0,0); 692 smp_call_function(etr_sync_cpu_start, NULL, 0, 0);
805 local_irq_disable(); 693 local_irq_disable();
806 etr_enable_sync_clock(); 694 etr_enable_sync_clock();
807 695
@@ -809,6 +697,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
809 __ctl_set_bit(14, 21); 697 __ctl_set_bit(14, 21);
810 __ctl_set_bit(0, 29); 698 __ctl_set_bit(0, 29);
811 clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32; 699 clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32;
700 old_clock = get_clock();
812 if (set_clock(clock) == 0) { 701 if (set_clock(clock) == 0) {
813 __udelay(1); /* Wait for the clock to start. */ 702 __udelay(1); /* Wait for the clock to start. */
814 __ctl_clear_bit(0, 29); 703 __ctl_clear_bit(0, 29);
@@ -817,16 +706,17 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
817 /* Adjust Linux timing variables. */ 706 /* Adjust Linux timing variables. */
818 delay = (unsigned long long) 707 delay = (unsigned long long)
819 (aib->edf2.etv - sync_port->edf2.etv) << 32; 708 (aib->edf2.etv - sync_port->edf2.etv) << 32;
820 etr_adjust_time(clock, delay); 709 delta = etr_adjust_time(old_clock, clock, delay);
821 setup_jiffy_timer(); 710 etr_sync.fixup_cc = delta;
711 fixup_clock_comparator(delta);
822 /* Verify that the clock is properly set. */ 712 /* Verify that the clock is properly set. */
823 if (!etr_aib_follows(sync_port, aib, port)) { 713 if (!etr_aib_follows(sync_port, aib, port)) {
824 /* Didn't work. */ 714 /* Didn't work. */
825 etr_disable_sync_clock(NULL); 715 etr_disable_sync_clock(NULL);
826 in_sync = -EAGAIN; 716 etr_sync.in_sync = -EAGAIN;
827 rc = -EAGAIN; 717 rc = -EAGAIN;
828 } else { 718 } else {
829 in_sync = 1; 719 etr_sync.in_sync = 1;
830 rc = 0; 720 rc = 0;
831 } 721 }
832 } else { 722 } else {
@@ -834,7 +724,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
834 __ctl_clear_bit(0, 29); 724 __ctl_clear_bit(0, 29);
835 __ctl_clear_bit(14, 21); 725 __ctl_clear_bit(14, 21);
836 etr_disable_sync_clock(NULL); 726 etr_disable_sync_clock(NULL);
837 in_sync = -EAGAIN; 727 etr_sync.in_sync = -EAGAIN;
838 rc = -EAGAIN; 728 rc = -EAGAIN;
839 } 729 }
840 local_irq_enable(); 730 local_irq_enable();