diff options
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r-- | arch/s390/kernel/vtime.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index c8eb7255332b..c41bb0d416e1 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -25,13 +25,9 @@ | |||
25 | #include <asm/irq_regs.h> | 25 | #include <asm/irq_regs.h> |
26 | #include <asm/cputime.h> | 26 | #include <asm/cputime.h> |
27 | 27 | ||
28 | static ext_int_info_t ext_int_info_timer; | ||
29 | |||
30 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); | 28 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); |
31 | 29 | ||
32 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { | 30 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle); |
33 | .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) | ||
34 | }; | ||
35 | 31 | ||
36 | static inline __u64 get_vtimer(void) | 32 | static inline __u64 get_vtimer(void) |
37 | { | 33 | { |
@@ -153,11 +149,13 @@ void vtime_start_cpu(void) | |||
153 | vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; | 149 | vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; |
154 | } | 150 | } |
155 | 151 | ||
156 | spin_lock(&idle->lock); | 152 | idle->sequence++; |
153 | smp_wmb(); | ||
157 | idle->idle_time += idle_time; | 154 | idle->idle_time += idle_time; |
158 | idle->idle_enter = 0ULL; | 155 | idle->idle_enter = 0ULL; |
159 | idle->idle_count++; | 156 | idle->idle_count++; |
160 | spin_unlock(&idle->lock); | 157 | smp_wmb(); |
158 | idle->sequence++; | ||
161 | } | 159 | } |
162 | 160 | ||
163 | void vtime_stop_cpu(void) | 161 | void vtime_stop_cpu(void) |
@@ -244,15 +242,23 @@ cputime64_t s390_get_idle_time(int cpu) | |||
244 | { | 242 | { |
245 | struct s390_idle_data *idle; | 243 | struct s390_idle_data *idle; |
246 | unsigned long long now, idle_time, idle_enter; | 244 | unsigned long long now, idle_time, idle_enter; |
245 | unsigned int sequence; | ||
247 | 246 | ||
248 | idle = &per_cpu(s390_idle, cpu); | 247 | idle = &per_cpu(s390_idle, cpu); |
249 | spin_lock(&idle->lock); | 248 | |
250 | now = get_clock(); | 249 | now = get_clock(); |
250 | repeat: | ||
251 | sequence = idle->sequence; | ||
252 | smp_rmb(); | ||
253 | if (sequence & 1) | ||
254 | goto repeat; | ||
251 | idle_time = 0; | 255 | idle_time = 0; |
252 | idle_enter = idle->idle_enter; | 256 | idle_enter = idle->idle_enter; |
253 | if (idle_enter != 0ULL && idle_enter < now) | 257 | if (idle_enter != 0ULL && idle_enter < now) |
254 | idle_time = now - idle_enter; | 258 | idle_time = now - idle_enter; |
255 | spin_unlock(&idle->lock); | 259 | smp_rmb(); |
260 | if (idle->sequence != sequence) | ||
261 | goto repeat; | ||
256 | return idle_time; | 262 | return idle_time; |
257 | } | 263 | } |
258 | 264 | ||
@@ -557,8 +563,7 @@ void init_cpu_vtimer(void) | |||
557 | void __init vtime_init(void) | 563 | void __init vtime_init(void) |
558 | { | 564 | { |
559 | /* request the cpu timer external interrupt */ | 565 | /* request the cpu timer external interrupt */ |
560 | if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt, | 566 | if (register_external_interrupt(0x1005, do_cpu_timer_interrupt)) |
561 | &ext_int_info_timer) != 0) | ||
562 | panic("Couldn't request external interrupt 0x1005"); | 567 | panic("Couldn't request external interrupt 0x1005"); |
563 | 568 | ||
564 | /* Enable cpu timer interrupts on the boot cpu. */ | 569 | /* Enable cpu timer interrupts on the boot cpu. */ |