Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/idle: consolidate idle functions and definitions

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>

+166 -144
+2 -16
arch/s390/include/asm/cputime.h
··· 8 8 #define _S390_CPUTIME_H 9 9 10 10 #include <linux/types.h> 11 - #include <linux/percpu.h> 12 - #include <linux/spinlock.h> 13 11 #include <asm/div64.h> 14 12 15 13 ··· 163 165 return clock; 164 166 } 165 167 166 - struct s390_idle_data { 167 - unsigned int sequence; 168 - unsigned long long idle_count; 169 - unsigned long long idle_time; 170 - unsigned long long clock_idle_enter; 171 - unsigned long long clock_idle_exit; 172 - unsigned long long timer_idle_enter; 173 - unsigned long long timer_idle_exit; 174 - }; 168 + cputime64_t arch_cpu_idle_time(int cpu); 175 169 176 - DECLARE_PER_CPU(struct s390_idle_data, s390_idle); 177 - 178 - cputime64_t s390_get_idle_time(int cpu); 179 - 180 - #define arch_idle_time(cpu) s390_get_idle_time(cpu) 170 + #define arch_idle_time(cpu) arch_cpu_idle_time(cpu) 181 171 182 172 #endif /* _S390_CPUTIME_H */
+26
arch/s390/include/asm/idle.h
··· 1 + /* 2 + * Copyright IBM Corp. 2014 3 + * 4 + * Author: Martin Schwidefsky <schwidefsky@de.ibm.com> 5 + */ 6 + 7 + #ifndef _S390_IDLE_H 8 + #define _S390_IDLE_H 9 + 10 + #include <linux/types.h> 11 + #include <linux/device.h> 12 + 13 + struct s390_idle_data { 14 + unsigned int sequence; 15 + unsigned long long idle_count; 16 + unsigned long long idle_time; 17 + unsigned long long clock_idle_enter; 18 + unsigned long long clock_idle_exit; 19 + unsigned long long timer_idle_enter; 20 + unsigned long long timer_idle_exit; 21 + }; 22 + 23 + extern struct device_attribute dev_attr_idle_count; 24 + extern struct device_attribute dev_attr_idle_time_us; 25 + 26 + #endif /* _S390_IDLE_H */
+6 -1
arch/s390/include/asm/processor.h
··· 289 289 return (psw.addr - ilc) & mask; 290 290 #endif 291 291 } 292 - 292 + 293 + /* 294 + * Function to stop a processor until the next interrupt occurs 295 + */ 296 + void enabled_wait(void); 297 + 293 298 /* 294 299 * Function to drop a processor into disabled wait state 295 300 */
-2
arch/s390/include/asm/vtimer.h
··· 28 28 extern void init_cpu_vtimer(void); 29 29 extern void vtime_init(void); 30 30 31 - extern void vtime_stop_cpu(void); 32 - 33 31 #endif /* _ASM_S390_TIMER_H */
+1 -1
arch/s390/kernel/Makefile
··· 28 28 29 29 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w 30 30 31 - obj-y := traps.o time.o process.o base.o early.o setup.o vtime.o 31 + obj-y := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o 32 32 obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o 33 33 obj-y += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o 34 34 obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+1 -1
arch/s390/kernel/asm-offsets.c
··· 9 9 #include <linux/kbuild.h> 10 10 #include <linux/kvm_host.h> 11 11 #include <linux/sched.h> 12 - #include <asm/cputime.h> 12 + #include <asm/idle.h> 13 13 #include <asm/vdso.h> 14 14 #include <asm/pgtable.h> 15 15
+1 -1
arch/s390/kernel/entry.h
··· 4 4 #include <linux/types.h> 5 5 #include <linux/signal.h> 6 6 #include <asm/ptrace.h> 7 - #include <asm/cputime.h> 7 + #include <asm/idle.h> 8 8 9 9 extern void *restart_stack; 10 10 extern unsigned long suspend_zero_pages;
+124
arch/s390/kernel/idle.c
··· 1 + /* 2 + * Idle functions for s390. 3 + * 4 + * Copyright IBM Corp. 2014 5 + * 6 + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 7 + */ 8 + 9 + #include <linux/kernel.h> 10 + #include <linux/kernel_stat.h> 11 + #include <linux/kprobes.h> 12 + #include <linux/notifier.h> 13 + #include <linux/init.h> 14 + #include <linux/cpu.h> 15 + #include <asm/cputime.h> 16 + #include <asm/nmi.h> 17 + #include <asm/smp.h> 18 + #include "entry.h" 19 + 20 + static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); 21 + 22 + void __kprobes enabled_wait(void) 23 + { 24 + struct s390_idle_data *idle = &__get_cpu_var(s390_idle); 25 + unsigned long long idle_time; 26 + unsigned long psw_mask; 27 + 28 + trace_hardirqs_on(); 29 + 30 + /* Wait for external, I/O or machine check interrupt. */ 31 + psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT | 32 + PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; 33 + clear_cpu_flag(CIF_NOHZ_DELAY); 34 + 35 + /* Call the assembler magic in entry.S */ 36 + psw_idle(idle, psw_mask); 37 + 38 + /* Account time spent with enabled wait psw loaded as idle time. */ 39 + idle->sequence++; 40 + smp_wmb(); 41 + idle_time = idle->clock_idle_exit - idle->clock_idle_enter; 42 + idle->clock_idle_enter = idle->clock_idle_exit = 0ULL; 43 + idle->idle_time += idle_time; 44 + idle->idle_count++; 45 + account_idle_time(idle_time); 46 + smp_wmb(); 47 + idle->sequence++; 48 + } 49 + 50 + static ssize_t show_idle_count(struct device *dev, 51 + struct device_attribute *attr, char *buf) 52 + { 53 + struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 54 + unsigned long long idle_count; 55 + unsigned int sequence; 56 + 57 + do { 58 + sequence = ACCESS_ONCE(idle->sequence); 59 + idle_count = ACCESS_ONCE(idle->idle_count); 60 + if (ACCESS_ONCE(idle->clock_idle_enter)) 61 + idle_count++; 62 + } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 63 + return sprintf(buf, "%llu\n", idle_count); 64 + } 65 + DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); 66 + 67 + static ssize_t show_idle_time(struct device *dev, 68 + struct device_attribute *attr, char *buf) 69 + { 70 + struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 71 + unsigned long long now, idle_time, idle_enter, idle_exit; 72 + unsigned int sequence; 73 + 74 + do { 75 + now = get_tod_clock(); 76 + sequence = ACCESS_ONCE(idle->sequence); 77 + idle_time = ACCESS_ONCE(idle->idle_time); 78 + idle_enter = ACCESS_ONCE(idle->clock_idle_enter); 79 + idle_exit = ACCESS_ONCE(idle->clock_idle_exit); 80 + } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 81 + idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; 82 + return sprintf(buf, "%llu\n", idle_time >> 12); 83 + } 84 + DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); 85 + 86 + cputime64_t arch_cpu_idle_time(int cpu) 87 + { 88 + struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); 89 + unsigned long long now, idle_enter, idle_exit; 90 + unsigned int sequence; 91 + 92 + do { 93 + now = get_tod_clock(); 94 + sequence = ACCESS_ONCE(idle->sequence); 95 + idle_enter = ACCESS_ONCE(idle->clock_idle_enter); 96 + idle_exit = ACCESS_ONCE(idle->clock_idle_exit); 97 + } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 98 + return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0; 99 + } 100 + 101 + void arch_cpu_idle_enter(void) 102 + { 103 + local_mcck_disable(); 104 + } 105 + 106 + void arch_cpu_idle(void) 107 + { 108 + if (!test_cpu_flag(CIF_MCCK_PENDING)) 109 + /* Halt the cpu and keep track of cpu time accounting. */ 110 + enabled_wait(); 111 + local_irq_enable(); 112 + } 113 + 114 + void arch_cpu_idle_exit(void) 115 + { 116 + local_mcck_enable(); 117 + if (test_cpu_flag(CIF_MCCK_PENDING)) 118 + s390_handle_mcck(); 119 + } 120 + 121 + void arch_cpu_idle_dead(void) 122 + { 123 + cpu_die(); 124 + }
-24
arch/s390/kernel/process.c
··· 61 61 return sf->gprs[8]; 62 62 } 63 63 64 - void arch_cpu_idle(void) 65 - { 66 - local_mcck_disable(); 67 - if (test_cpu_flag(CIF_MCCK_PENDING)) { 68 - local_mcck_enable(); 69 - local_irq_enable(); 70 - return; 71 - } 72 - /* Halt the cpu and keep track of cpu time accounting. */ 73 - vtime_stop_cpu(); 74 - local_irq_enable(); 75 - } 76 - 77 - void arch_cpu_idle_exit(void) 78 - { 79 - if (test_cpu_flag(CIF_MCCK_PENDING)) 80 - s390_handle_mcck(); 81 - } 82 - 83 - void arch_cpu_idle_dead(void) 84 - { 85 - cpu_die(); 86 - } 87 - 88 64 extern void __kprobes kernel_thread_starter(void); 89 65 90 66 /*
+2 -37
arch/s390/kernel/smp.c
··· 45 45 #include <asm/debug.h> 46 46 #include <asm/os_info.h> 47 47 #include <asm/sigp.h> 48 + #include <asm/idle.h> 48 49 #include "entry.h" 49 50 50 51 enum { ··· 662 661 cpu_init(); 663 662 preempt_disable(); 664 663 init_cpu_timer(); 665 - init_cpu_vtimer(); 664 + vtime_init(); 666 665 pfault_init(); 667 666 notify_cpu_starting(smp_processor_id()); 668 667 set_cpu_online(smp_processor_id(), true); ··· 893 892 static struct attribute_group cpu_common_attr_group = { 894 893 .attrs = cpu_common_attrs, 895 894 }; 896 - 897 - static ssize_t show_idle_count(struct device *dev, 898 - struct device_attribute *attr, char *buf) 899 - { 900 - struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 901 - unsigned long long idle_count; 902 - unsigned int sequence; 903 - 904 - do { 905 - sequence = ACCESS_ONCE(idle->sequence); 906 - idle_count = ACCESS_ONCE(idle->idle_count); 907 - if (ACCESS_ONCE(idle->clock_idle_enter)) 908 - idle_count++; 909 - } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 910 - return sprintf(buf, "%llu\n", idle_count); 911 - } 912 - static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); 913 - 914 - static ssize_t show_idle_time(struct device *dev, 915 - struct device_attribute *attr, char *buf) 916 - { 917 - struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); 918 - unsigned long long now, idle_time, idle_enter, idle_exit; 919 - unsigned int sequence; 920 - 921 - do { 922 - now = get_tod_clock(); 923 - sequence = ACCESS_ONCE(idle->sequence); 924 - idle_time = ACCESS_ONCE(idle->idle_time); 925 - idle_enter = ACCESS_ONCE(idle->clock_idle_enter); 926 - idle_exit = ACCESS_ONCE(idle->clock_idle_exit); 927 - } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 928 - idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; 929 - return sprintf(buf, "%llu\n", idle_time >> 12); 930 - } 931 - static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); 932 895 933 896 static struct attribute *cpu_online_attrs[] = { 934 897 &dev_attr_idle_count.attr,
+1 -59
arch/s390/kernel/vtime.c
··· 6 6 */ 7 7 8 8 #include <linux/kernel_stat.h> 9 - #include <linux/notifier.h> 10 - #include <linux/kprobes.h> 11 9 #include <linux/export.h> 12 10 #include <linux/kernel.h> 13 11 #include <linux/timex.h> 14 12 #include <linux/types.h> 15 13 #include <linux/time.h> 16 - #include <linux/cpu.h> 17 - #include <linux/smp.h> 18 14 19 - #include <asm/irq_regs.h> 20 15 #include <asm/cputime.h> 21 16 #include <asm/vtimer.h> 22 17 #include <asm/vtime.h> 23 - #include <asm/irq.h> 24 - #include "entry.h" 25 18 26 19 static void virt_timer_expire(void); 27 - 28 - DEFINE_PER_CPU(struct s390_idle_data, s390_idle); 29 20 30 21 static LIST_HEAD(virt_timer_list); 31 22 static DEFINE_SPINLOCK(virt_timer_lock); ··· 142 151 void vtime_account_system(struct task_struct *tsk) 143 152 __attribute__((alias("vtime_account_irq_enter"))); 144 153 EXPORT_SYMBOL_GPL(vtime_account_system); 145 - 146 - void __kprobes vtime_stop_cpu(void) 147 - { 148 - struct s390_idle_data *idle = &__get_cpu_var(s390_idle); 149 - unsigned long long idle_time; 150 - unsigned long psw_mask; 151 - 152 - trace_hardirqs_on(); 153 - 154 - /* Wait for external, I/O or machine check interrupt. */ 155 - psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT | 156 - PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; 157 - clear_cpu_flag(CIF_NOHZ_DELAY); 158 - 159 - /* Call the assembler magic in entry.S */ 160 - psw_idle(idle, psw_mask); 161 - 162 - /* Account time spent with enabled wait psw loaded as idle time. */ 163 - idle->sequence++; 164 - smp_wmb(); 165 - idle_time = idle->clock_idle_exit - idle->clock_idle_enter; 166 - idle->clock_idle_enter = idle->clock_idle_exit = 0ULL; 167 - idle->idle_time += idle_time; 168 - idle->idle_count++; 169 - account_idle_time(idle_time); 170 - smp_wmb(); 171 - idle->sequence++; 172 - } 173 - 174 - cputime64_t s390_get_idle_time(int cpu) 175 - { 176 - struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); 177 - unsigned long long now, idle_enter, idle_exit; 178 - unsigned int sequence; 179 - 180 - do { 181 - now = get_tod_clock(); 182 - sequence = ACCESS_ONCE(idle->sequence); 183 - idle_enter = ACCESS_ONCE(idle->clock_idle_enter); 184 - idle_exit = ACCESS_ONCE(idle->clock_idle_exit); 185 - } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); 186 - return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0; 187 - } 188 154 189 155 /* 190 156 * Sorted add to a list. List is linear searched until first bigger ··· 320 372 /* 321 373 * Start the virtual CPU timer on the current CPU. 322 374 */ 323 - void init_cpu_vtimer(void) 375 + void vtime_init(void) 324 376 { 325 377 /* set initial cpu timer */ 326 378 set_vtimer(VTIMER_MAX_SLICE); 327 - } 328 - 329 - void __init vtime_init(void) 330 - { 331 - /* Enable cpu timer interrupts on the boot cpu. */ 332 - init_cpu_vtimer(); 333 379 }
+2 -2
arch/s390/lib/delay.c
··· 43 43 lockdep_off(); 44 44 do { 45 45 set_clock_comparator(end); 46 - vtime_stop_cpu(); 46 + enabled_wait(); 47 47 } while (get_tod_clock_fast() < end); 48 48 lockdep_on(); 49 49 __ctl_load(cr0, 0, 0); ··· 62 62 clock_saved = local_tick_disable(); 63 63 set_clock_comparator(end); 64 64 } 65 - vtime_stop_cpu(); 65 + enabled_wait(); 66 66 if (clock_saved) 67 67 local_tick_enable(clock_saved); 68 68 } while (get_tod_clock_fast() < end);