s390/idle: consolidate idle functions and definitions
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 1 Oct 2014 08:57:57 +0000 (10:57 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 9 Oct 2014 07:14:03 +0000 (09:14 +0200)
Move the C functions and definitions related to the idle state handling
to arch/s390/include/asm/idle.h and arch/s390/kernel/idle.c. The function
s390_get_idle_time is renamed to arch_cpu_idle_time and vtime_stop_cpu to
enabled_wait.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
12 files changed:
arch/s390/include/asm/cputime.h
arch/s390/include/asm/idle.h [new file with mode: 0644]
arch/s390/include/asm/processor.h
arch/s390/include/asm/vtimer.h
arch/s390/kernel/Makefile
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.h
arch/s390/kernel/idle.c [new file with mode: 0644]
arch/s390/kernel/process.c
arch/s390/kernel/smp.c
arch/s390/kernel/vtime.c
arch/s390/lib/delay.c

index 01887b1fade593d8d0627b620872e6f23edbee62..1c016a5fa97ef607e9ee2cbc5480caf742e726a1 100644 (file)
@@ -8,8 +8,6 @@
 #define _S390_CPUTIME_H
 
 #include <linux/types.h>
-#include <linux/percpu.h>
-#include <linux/spinlock.h>
 #include <asm/div64.h>
 
 
@@ -165,20 +163,8 @@ static inline clock_t cputime64_to_clock_t(cputime64_t cputime)
        return clock;
 }
 
-struct s390_idle_data {
-       unsigned int sequence;
-       unsigned long long idle_count;
-       unsigned long long idle_time;
-       unsigned long long clock_idle_enter;
-       unsigned long long clock_idle_exit;
-       unsigned long long timer_idle_enter;
-       unsigned long long timer_idle_exit;
-};
+cputime64_t arch_cpu_idle_time(int cpu);
 
-DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
-
-cputime64_t s390_get_idle_time(int cpu);
-
-#define arch_idle_time(cpu) s390_get_idle_time(cpu)
+#define arch_idle_time(cpu) arch_cpu_idle_time(cpu)
 
 #endif /* _S390_CPUTIME_H */
diff --git a/arch/s390/include/asm/idle.h b/arch/s390/include/asm/idle.h
new file mode 100644 (file)
index 0000000..6af037f
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  Copyright IBM Corp. 2014
+ *
+ *  Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _S390_IDLE_H
+#define _S390_IDLE_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+
+struct s390_idle_data {
+       unsigned int sequence;
+       unsigned long long idle_count;
+       unsigned long long idle_time;
+       unsigned long long clock_idle_enter;
+       unsigned long long clock_idle_exit;
+       unsigned long long timer_idle_enter;
+       unsigned long long timer_idle_exit;
+};
+
+extern struct device_attribute dev_attr_idle_count;
+extern struct device_attribute dev_attr_idle_time_us;
+
+#endif /* _S390_IDLE_H */
index bc796d73129bf1668cf1f0dda8a44a19b486fe2d..3d08710583063a7c4fd74ff1131e64e04cf9aa42 100644 (file)
@@ -289,7 +289,12 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
        return (psw.addr - ilc) & mask;
 #endif
 }
+
+/*
+ * Function to stop a processor until the next interrupt occurs
+ */
+void enabled_wait(void);
+
 /*
  * Function to drop a processor into disabled wait state
  */
index bfe25d513ad26462f22fce6e66dd3f688e25c352..10a179af62d8c3f512a253752494b61c1801310f 100644 (file)
@@ -28,6 +28,4 @@ extern int del_virt_timer(struct vtimer_list *timer);
 extern void init_cpu_vtimer(void);
 extern void vtime_init(void);
 
-extern void vtime_stop_cpu(void);
-
 #endif /* _ASM_S390_TIMER_H */
index 3249e1f36d55ba013433b9f132ff4e507f6b8db7..c249785669f3d8b7ca60a3f19363f7ed0f21374c 100644 (file)
@@ -28,7 +28,7 @@ CFLAGS_ptrace.o               += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 
-obj-y  := traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y  := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o
 obj-y  += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
 obj-y  += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
 obj-y  += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
index 3e9e479d9b49a939aabd2bb4961f354cffe81c36..ef279a1368012e67fbbbbb3092783b461e1b98c0 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kbuild.h>
 #include <linux/kvm_host.h>
 #include <linux/sched.h>
-#include <asm/cputime.h>
+#include <asm/idle.h>
 #include <asm/vdso.h>
 #include <asm/pgtable.h>
 
index 58541633b8d6197f4169565c3a7e7d6cc73d64e9..cd68869f95048508c9c4d793c1e140c8e72b5ef5 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/types.h>
 #include <linux/signal.h>
 #include <asm/ptrace.h>
-#include <asm/cputime.h>
+#include <asm/idle.h>
 
 extern void *restart_stack;
 extern unsigned long suspend_zero_pages;
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
new file mode 100644 (file)
index 0000000..c846aee
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Idle functions for s390.
+ *
+ * Copyright IBM Corp. 2014
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/kprobes.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <asm/cputime.h>
+#include <asm/nmi.h>
+#include <asm/smp.h>
+#include "entry.h"
+
+static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+
+void __kprobes enabled_wait(void)
+{
+       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+       unsigned long long idle_time;
+       unsigned long psw_mask;
+
+       trace_hardirqs_on();
+
+       /* Wait for external, I/O or machine check interrupt. */
+       psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
+               PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
+       clear_cpu_flag(CIF_NOHZ_DELAY);
+
+       /* Call the assembler magic in entry.S */
+       psw_idle(idle, psw_mask);
+
+       /* Account time spent with enabled wait psw loaded as idle time. */
+       idle->sequence++;
+       smp_wmb();
+       idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
+       idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
+       idle->idle_time += idle_time;
+       idle->idle_count++;
+       account_idle_time(idle_time);
+       smp_wmb();
+       idle->sequence++;
+}
+
+static ssize_t show_idle_count(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
+       unsigned long long idle_count;
+       unsigned int sequence;
+
+       do {
+               sequence = ACCESS_ONCE(idle->sequence);
+               idle_count = ACCESS_ONCE(idle->idle_count);
+               if (ACCESS_ONCE(idle->clock_idle_enter))
+                       idle_count++;
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       return sprintf(buf, "%llu\n", idle_count);
+}
+DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
+
+static ssize_t show_idle_time(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
+       unsigned long long now, idle_time, idle_enter, idle_exit;
+       unsigned int sequence;
+
+       do {
+               now = get_tod_clock();
+               sequence = ACCESS_ONCE(idle->sequence);
+               idle_time = ACCESS_ONCE(idle->idle_time);
+               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
+               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
+       return sprintf(buf, "%llu\n", idle_time >> 12);
+}
+DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
+
+cputime64_t arch_cpu_idle_time(int cpu)
+{
+       struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
+       unsigned long long now, idle_enter, idle_exit;
+       unsigned int sequence;
+
+       do {
+               now = get_tod_clock();
+               sequence = ACCESS_ONCE(idle->sequence);
+               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
+               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
+}
+
+void arch_cpu_idle_enter(void)
+{
+       local_mcck_disable();
+}
+
+void arch_cpu_idle(void)
+{
+       if (!test_cpu_flag(CIF_MCCK_PENDING))
+               /* Halt the cpu and keep track of cpu time accounting. */
+               enabled_wait();
+       local_irq_enable();
+}
+
+void arch_cpu_idle_exit(void)
+{
+       local_mcck_enable();
+       if (test_cpu_flag(CIF_MCCK_PENDING))
+               s390_handle_mcck();
+}
+
+void arch_cpu_idle_dead(void)
+{
+       cpu_die();
+}
index 93b9ca42e5c0ace2ac209789befa3242850b0043..ed84cc224899ff76ca30e5755d7cf7f2a734d981 100644 (file)
@@ -61,30 +61,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sf->gprs[8];
 }
 
-void arch_cpu_idle(void)
-{
-       local_mcck_disable();
-       if (test_cpu_flag(CIF_MCCK_PENDING)) {
-               local_mcck_enable();
-               local_irq_enable();
-               return;
-       }
-       /* Halt the cpu and keep track of cpu time accounting. */
-       vtime_stop_cpu();
-       local_irq_enable();
-}
-
-void arch_cpu_idle_exit(void)
-{
-       if (test_cpu_flag(CIF_MCCK_PENDING))
-               s390_handle_mcck();
-}
-
-void arch_cpu_idle_dead(void)
-{
-       cpu_die();
-}
-
 extern void __kprobes kernel_thread_starter(void);
 
 /*
index 46317d6951c4f10c5db30c1d7c6f8386da4481a6..bba0e24692542152998e4d1702187bc4329f3875 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/debug.h>
 #include <asm/os_info.h>
 #include <asm/sigp.h>
+#include <asm/idle.h>
 #include "entry.h"
 
 enum {
@@ -661,7 +662,7 @@ static void smp_start_secondary(void *cpuvoid)
        cpu_init();
        preempt_disable();
        init_cpu_timer();
-       init_cpu_vtimer();
+       vtime_init();
        pfault_init();
        notify_cpu_starting(smp_processor_id());
        set_cpu_online(smp_processor_id(), true);
@@ -893,42 +894,6 @@ static struct attribute_group cpu_common_attr_group = {
        .attrs = cpu_common_attrs,
 };
 
-static ssize_t show_idle_count(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
-       unsigned long long idle_count;
-       unsigned int sequence;
-
-       do {
-               sequence = ACCESS_ONCE(idle->sequence);
-               idle_count = ACCESS_ONCE(idle->idle_count);
-               if (ACCESS_ONCE(idle->clock_idle_enter))
-                       idle_count++;
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
-       return sprintf(buf, "%llu\n", idle_count);
-}
-static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
-
-static ssize_t show_idle_time(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
-       unsigned long long now, idle_time, idle_enter, idle_exit;
-       unsigned int sequence;
-
-       do {
-               now = get_tod_clock();
-               sequence = ACCESS_ONCE(idle->sequence);
-               idle_time = ACCESS_ONCE(idle->idle_time);
-               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
-               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
-       idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
-       return sprintf(buf, "%llu\n", idle_time >> 12);
-}
-static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
-
 static struct attribute *cpu_online_attrs[] = {
        &dev_attr_idle_count.attr,
        &dev_attr_idle_time_us.attr,
index 40709821abde61b614370d83158087e4c82de48e..416f2a323ba5e3a3d59a806a921751749ccb7a46 100644 (file)
@@ -6,27 +6,18 @@
  */
 
 #include <linux/kernel_stat.h>
-#include <linux/notifier.h>
-#include <linux/kprobes.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/timex.h>
 #include <linux/types.h>
 #include <linux/time.h>
-#include <linux/cpu.h>
-#include <linux/smp.h>
 
-#include <asm/irq_regs.h>
 #include <asm/cputime.h>
 #include <asm/vtimer.h>
 #include <asm/vtime.h>
-#include <asm/irq.h>
-#include "entry.h"
 
 static void virt_timer_expire(void);
 
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
-
 static LIST_HEAD(virt_timer_list);
 static DEFINE_SPINLOCK(virt_timer_lock);
 static atomic64_t virt_timer_current;
@@ -152,49 +143,6 @@ void vtime_account_system(struct task_struct *tsk)
 __attribute__((alias("vtime_account_irq_enter")));
 EXPORT_SYMBOL_GPL(vtime_account_system);
 
-void __kprobes vtime_stop_cpu(void)
-{
-       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
-       unsigned long long idle_time;
-       unsigned long psw_mask;
-
-       trace_hardirqs_on();
-
-       /* Wait for external, I/O or machine check interrupt. */
-       psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
-               PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
-       clear_cpu_flag(CIF_NOHZ_DELAY);
-
-       /* Call the assembler magic in entry.S */
-       psw_idle(idle, psw_mask);
-
-       /* Account time spent with enabled wait psw loaded as idle time. */
-       idle->sequence++;
-       smp_wmb();
-       idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
-       idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
-       idle->idle_time += idle_time;
-       idle->idle_count++;
-       account_idle_time(idle_time);
-       smp_wmb();
-       idle->sequence++;
-}
-
-cputime64_t s390_get_idle_time(int cpu)
-{
-       struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
-       unsigned long long now, idle_enter, idle_exit;
-       unsigned int sequence;
-
-       do {
-               now = get_tod_clock();
-               sequence = ACCESS_ONCE(idle->sequence);
-               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
-               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
-       return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
-}
-
 /*
  * Sorted add to a list. List is linear searched until first bigger
  * element is found.
@@ -372,14 +320,8 @@ EXPORT_SYMBOL(del_virt_timer);
 /*
  * Start the virtual CPU timer on the current CPU.
  */
-void init_cpu_vtimer(void)
+void vtime_init(void)
 {
        /* set initial cpu timer */
        set_vtimer(VTIMER_MAX_SLICE);
 }
-
-void __init vtime_init(void)
-{
-       /* Enable cpu timer interrupts on the boot cpu. */
-       init_cpu_vtimer();
-}
index a9f3d0042d58ba849b8c624f23915d88d03d6f70..16dc42d83f9316c8524436457b2a92df59b2fbf0 100644 (file)
@@ -43,7 +43,7 @@ static void __udelay_disabled(unsigned long long usecs)
        lockdep_off();
        do {
                set_clock_comparator(end);
-               vtime_stop_cpu();
+               enabled_wait();
        } while (get_tod_clock_fast() < end);
        lockdep_on();
        __ctl_load(cr0, 0, 0);
@@ -62,7 +62,7 @@ static void __udelay_enabled(unsigned long long usecs)
                        clock_saved = local_tick_disable();
                        set_clock_comparator(end);
                }
-               vtime_stop_cpu();
+               enabled_wait();
                if (clock_saved)
                        local_tick_enable(clock_saved);
        } while (get_tod_clock_fast() < end);