diff options
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r-- | arch/s390/kernel/vtime.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 38ea92ff04f..c41bb0d416e 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -23,15 +23,11 @@ #include <asm/s390_ext.h> #include <asm/timer.h> #include <asm/irq_regs.h> -#include <asm/cpu.h> - -static ext_int_info_t ext_int_info_timer; +#include <asm/cputime.h> static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); -DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { - .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) -}; +DEFINE_PER_CPU(struct s390_idle_data, s390_idle); static inline __u64 get_vtimer(void) { @@ -153,11 +149,13 @@ void vtime_start_cpu(void) vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; } - spin_lock(&idle->lock); + idle->sequence++; + smp_wmb(); idle->idle_time += idle_time; idle->idle_enter = 0ULL; idle->idle_count++; - spin_unlock(&idle->lock); + smp_wmb(); + idle->sequence++; } void vtime_stop_cpu(void) @@ -240,6 +238,30 @@ void vtime_stop_cpu(void) } } +cputime64_t s390_get_idle_time(int cpu) +{ + struct s390_idle_data *idle; + unsigned long long now, idle_time, idle_enter; + unsigned int sequence; + + idle = &per_cpu(s390_idle, cpu); + + now = get_clock(); +repeat: + sequence = idle->sequence; + smp_rmb(); + if (sequence & 1) + goto repeat; + idle_time = 0; + idle_enter = idle->idle_enter; + if (idle_enter != 0ULL && idle_enter < now) + idle_time = now - idle_enter; + smp_rmb(); + if (idle->sequence != sequence) + goto repeat; + return idle_time; +} + /* * Sorted add to a list. List is linear searched until first bigger * element is found. @@ -541,8 +563,7 @@ void init_cpu_vtimer(void) void __init vtime_init(void) { /* request the cpu timer external interrupt */ - if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt, - &ext_int_info_timer) != 0) + if (register_external_interrupt(0x1005, do_cpu_timer_interrupt)) panic("Couldn't request external interrupt 0x1005"); /* Enable cpu timer interrupts on the boot cpu. */ |