diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/kprobes.c | 18 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 28 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 16 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 27 |
4 files changed, 46 insertions, 43 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 9bb2f6241d9..86783efa24e 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -154,39 +154,35 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) static int __kprobes swap_instruction(void *aref) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + unsigned long status = kcb->kprobe_status; struct ins_replace_args *args = aref; + int rc; - return probe_kernel_write(args->ptr, &args->new, sizeof(args->new)); + kcb->kprobe_status = KPROBE_SWAP_INST; + rc = probe_kernel_write(args->ptr, &args->new, sizeof(args->new)); + kcb->kprobe_status = status; + return rc; } void __kprobes arch_arm_kprobe(struct kprobe *p) { - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - unsigned long status = kcb->kprobe_status; struct ins_replace_args args; args.ptr = p->addr; args.old = p->opcode; args.new = BREAKPOINT_INSTRUCTION; - - kcb->kprobe_status = KPROBE_SWAP_INST; stop_machine(swap_instruction, &args, NULL); - kcb->kprobe_status = status; } void __kprobes arch_disarm_kprobe(struct kprobe *p) { - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - unsigned long status = kcb->kprobe_status; struct ins_replace_args args; args.ptr = p->addr; args.old = BREAKPOINT_INSTRUCTION; args.new = p->opcode; - - kcb->kprobe_status = KPROBE_SWAP_INST; stop_machine(swap_instruction, &args, NULL); - kcb->kprobe_status = status; } void __kprobes arch_remove_kprobe(struct kprobe *p) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index fd8e3111a4e..2270730f535 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -856,13 +856,20 @@ static ssize_t show_idle_count(struct sys_device *dev, { struct s390_idle_data *idle; unsigned long long idle_count; + unsigned int sequence; idle = &per_cpu(s390_idle, dev->id); - spin_lock(&idle->lock); +repeat: + sequence = idle->sequence; + smp_rmb(); + if (sequence & 1) + goto repeat; idle_count = idle->idle_count; if (idle->idle_enter) idle_count++; - spin_unlock(&idle->lock); + smp_rmb(); + if (idle->sequence != sequence) + goto repeat; return sprintf(buf, "%llu\n", idle_count); } static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); @@ -872,15 +879,22 @@ static ssize_t show_idle_time(struct sys_device *dev, { struct s390_idle_data *idle; unsigned long long now, idle_time, idle_enter; + unsigned int sequence; idle = &per_cpu(s390_idle, dev->id); - spin_lock(&idle->lock); now = get_clock(); +repeat: + sequence = idle->sequence; + smp_rmb(); + if (sequence & 1) + goto repeat; idle_time = idle->idle_time; idle_enter = idle->idle_enter; if (idle_enter != 0ULL && idle_enter < now) idle_time += now - idle_enter; - spin_unlock(&idle->lock); + smp_rmb(); + if (idle->sequence != sequence) + goto repeat; return sprintf(buf, "%llu\n", idle_time >> 12); } static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); @@ -908,11 +922,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, case CPU_ONLINE: case CPU_ONLINE_FROZEN: idle = &per_cpu(s390_idle, cpu); - spin_lock_irq(&idle->lock); - idle->idle_enter = 0; - idle->idle_time = 0; - idle->idle_count = 0; - spin_unlock_irq(&idle->lock); + memset(idle, 0, sizeof(struct s390_idle_data)); if (sysfs_create_group(&s->kobj, &cpu_online_attr_group)) return NOTIFY_BAD; break; diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 215330a2c12..d4c8e9c47c8 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -36,7 +36,6 @@ #include <linux/notifier.h> #include <linux/clocksource.h> #include <linux/clockchips.h> -#include <linux/bootmem.h> #include <asm/uaccess.h> #include <asm/delay.h> #include <asm/s390_ext.h> @@ -62,9 +61,6 @@ u64 sched_clock_base_cc = -1; /* Force to data section. */ -static ext_int_info_t ext_int_info_cc; -static ext_int_info_t ext_int_etr_cc; - static DEFINE_PER_CPU(struct clock_event_device, comparators); /* @@ -255,15 +251,11 @@ void __init time_init(void) stp_reset(); /* request the clock comparator external interrupt */ - if (register_early_external_interrupt(0x1004, - clock_comparator_interrupt, - &ext_int_info_cc) != 0) + if (register_external_interrupt(0x1004, clock_comparator_interrupt)) panic("Couldn't request external interrupt 0x1004"); /* request the timing alert external interrupt */ - if (register_early_external_interrupt(0x1406, - timing_alert_interrupt, - &ext_int_etr_cc) != 0) + if (register_external_interrupt(0x1406, timing_alert_interrupt)) panic("Couldn't request external interrupt 0x1406"); if (clocksource_register(&clocksource_tod) != 0) @@ -1445,14 +1437,14 @@ static void __init stp_reset(void) { int rc; - stp_page = alloc_bootmem_pages(PAGE_SIZE); + stp_page = (void *) get_zeroed_page(GFP_ATOMIC); rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); if (rc == 0) set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags); else if (stp_online) { pr_warning("The real or virtual hardware system does " "not provide an STP interface\n"); - free_bootmem((unsigned long) stp_page, PAGE_SIZE); + free_page((unsigned long) stp_page); stp_page = NULL; stp_online = 0; } diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index c8eb7255332..c41bb0d416e 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -25,13 +25,9 @@ #include <asm/irq_regs.h> #include <asm/cputime.h> -static ext_int_info_t ext_int_info_timer; - 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) @@ -244,15 +242,23 @@ 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); - spin_lock(&idle->lock); + 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; - spin_unlock(&idle->lock); + smp_rmb(); + if (idle->sequence != sequence) + goto repeat; return idle_time; } @@ -557,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. */ |