diff options
26 files changed, 280 insertions, 159 deletions
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 27b70d8a359c..aeb3cff95f63 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
| @@ -176,7 +176,7 @@ static void __appldata_mod_vtimer_wrap(void *p) { | |||
| 176 | struct vtimer_list *timer; | 176 | struct vtimer_list *timer; |
| 177 | u64 expires; | 177 | u64 expires; |
| 178 | } *args = p; | 178 | } *args = p; |
| 179 | mod_virt_timer(args->timer, args->expires); | 179 | mod_virt_timer_periodic(args->timer, args->expires); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | #define APPLDATA_ADD_TIMER 0 | 182 | #define APPLDATA_ADD_TIMER 0 |
diff --git a/arch/s390/include/asm/cpuid.h b/arch/s390/include/asm/cpuid.h new file mode 100644 index 000000000000..07836a2e5222 --- /dev/null +++ b/arch/s390/include/asm/cpuid.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * Copyright IBM Corp. 2000,2009 | ||
| 3 | * Author(s): Hartmut Penner <hp@de.ibm.com>, | ||
| 4 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 5 | * Christian Ehrhardt <ehrhardt@de.ibm.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef _ASM_S390_CPUID_H_ | ||
| 9 | #define _ASM_S390_CPUID_H_ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * CPU type and hardware bug flags. Kept separately for each CPU. | ||
| 13 | * Members of this structure are referenced in head.S, so think twice | ||
| 14 | * before touching them. [mj] | ||
| 15 | */ | ||
| 16 | |||
| 17 | typedef struct | ||
| 18 | { | ||
| 19 | unsigned int version : 8; | ||
| 20 | unsigned int ident : 24; | ||
| 21 | unsigned int machine : 16; | ||
| 22 | unsigned int unused : 16; | ||
| 23 | } __attribute__ ((packed)) cpuid_t; | ||
| 24 | |||
| 25 | #endif /* _ASM_S390_CPUID_H_ */ | ||
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index c6e674f5fca9..54ea39f96ecd 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #define ASM_KVM_HOST_H | 15 | #define ASM_KVM_HOST_H |
| 16 | #include <linux/kvm_host.h> | 16 | #include <linux/kvm_host.h> |
| 17 | #include <asm/debug.h> | 17 | #include <asm/debug.h> |
| 18 | #include <asm/cpuid.h> | ||
| 18 | 19 | ||
| 19 | #define KVM_MAX_VCPUS 64 | 20 | #define KVM_MAX_VCPUS 64 |
| 20 | #define KVM_MEMORY_SLOTS 32 | 21 | #define KVM_MEMORY_SLOTS 32 |
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index b349f1c7fdfa..3aeca492b147 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #define __LC_USER_EXEC_ASCE 0x02ac | 66 | #define __LC_USER_EXEC_ASCE 0x02ac |
| 67 | #define __LC_CPUID 0x02b0 | 67 | #define __LC_CPUID 0x02b0 |
| 68 | #define __LC_INT_CLOCK 0x02c8 | 68 | #define __LC_INT_CLOCK 0x02c8 |
| 69 | #define __LC_MACHINE_FLAGS 0x02d8 | ||
| 69 | #define __LC_IRB 0x0300 | 70 | #define __LC_IRB 0x0300 |
| 70 | #define __LC_PFAULT_INTPARM 0x0080 | 71 | #define __LC_PFAULT_INTPARM 0x0080 |
| 71 | #define __LC_CPU_TIMER_SAVE_AREA 0x00d8 | 72 | #define __LC_CPU_TIMER_SAVE_AREA 0x00d8 |
| @@ -110,6 +111,7 @@ | |||
| 110 | #define __LC_CPUID 0x0320 | 111 | #define __LC_CPUID 0x0320 |
| 111 | #define __LC_INT_CLOCK 0x0340 | 112 | #define __LC_INT_CLOCK 0x0340 |
| 112 | #define __LC_VDSO_PER_CPU 0x0350 | 113 | #define __LC_VDSO_PER_CPU 0x0350 |
| 114 | #define __LC_MACHINE_FLAGS 0x0358 | ||
| 113 | #define __LC_IRB 0x0380 | 115 | #define __LC_IRB 0x0380 |
| 114 | #define __LC_PASTE 0x03c0 | 116 | #define __LC_PASTE 0x03c0 |
| 115 | #define __LC_PFAULT_INTPARM 0x11b8 | 117 | #define __LC_PFAULT_INTPARM 0x11b8 |
| @@ -127,9 +129,9 @@ | |||
| 127 | 129 | ||
| 128 | #ifndef __ASSEMBLY__ | 130 | #ifndef __ASSEMBLY__ |
| 129 | 131 | ||
| 130 | #include <asm/processor.h> | 132 | #include <asm/cpuid.h> |
| 133 | #include <asm/ptrace.h> | ||
| 131 | #include <linux/types.h> | 134 | #include <linux/types.h> |
| 132 | #include <asm/sigp.h> | ||
| 133 | 135 | ||
| 134 | void restart_int_handler(void); | 136 | void restart_int_handler(void); |
| 135 | void ext_int_handler(void); | 137 | void ext_int_handler(void); |
| @@ -277,7 +279,8 @@ struct _lowcore | |||
| 277 | __u32 ext_call_fast; /* 0x02c4 */ | 279 | __u32 ext_call_fast; /* 0x02c4 */ |
| 278 | __u64 int_clock; /* 0x02c8 */ | 280 | __u64 int_clock; /* 0x02c8 */ |
| 279 | __u64 clock_comparator; /* 0x02d0 */ | 281 | __u64 clock_comparator; /* 0x02d0 */ |
| 280 | __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */ | 282 | __u32 machine_flags; /* 0x02d8 */ |
| 283 | __u8 pad_0x02dc[0x0300-0x02dc]; /* 0x02dc */ | ||
| 281 | 284 | ||
| 282 | /* Interrupt response block */ | 285 | /* Interrupt response block */ |
| 283 | __u8 irb[64]; /* 0x0300 */ | 286 | __u8 irb[64]; /* 0x0300 */ |
| @@ -381,7 +384,8 @@ struct _lowcore | |||
| 381 | __u64 int_clock; /* 0x0340 */ | 384 | __u64 int_clock; /* 0x0340 */ |
| 382 | __u64 clock_comparator; /* 0x0348 */ | 385 | __u64 clock_comparator; /* 0x0348 */ |
| 383 | __u64 vdso_per_cpu_data; /* 0x0350 */ | 386 | __u64 vdso_per_cpu_data; /* 0x0350 */ |
| 384 | __u8 pad_0x0358[0x0380-0x0358]; /* 0x0358 */ | 387 | __u64 machine_flags; /* 0x0358 */ |
| 388 | __u8 pad_0x0360[0x0380-0x0360]; /* 0x0360 */ | ||
| 385 | 389 | ||
| 386 | /* Interrupt response block. */ | 390 | /* Interrupt response block. */ |
| 387 | __u8 irb[64]; /* 0x0380 */ | 391 | __u8 irb[64]; /* 0x0380 */ |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 61862b3ac794..c139fa7b8e89 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
| @@ -14,7 +14,10 @@ | |||
| 14 | #define __ASM_S390_PROCESSOR_H | 14 | #define __ASM_S390_PROCESSOR_H |
| 15 | 15 | ||
| 16 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
| 17 | #include <asm/cpuid.h> | ||
| 18 | #include <asm/page.h> | ||
| 17 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
| 20 | #include <asm/setup.h> | ||
| 18 | 21 | ||
| 19 | #ifdef __KERNEL__ | 22 | #ifdef __KERNEL__ |
| 20 | /* | 23 | /* |
| @@ -23,20 +26,6 @@ | |||
| 23 | */ | 26 | */ |
| 24 | #define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; }) | 27 | #define current_text_addr() ({ void *pc; asm("basr %0,0" : "=a" (pc)); pc; }) |
| 25 | 28 | ||
| 26 | /* | ||
| 27 | * CPU type and hardware bug flags. Kept separately for each CPU. | ||
| 28 | * Members of this structure are referenced in head.S, so think twice | ||
| 29 | * before touching them. [mj] | ||
| 30 | */ | ||
| 31 | |||
| 32 | typedef struct | ||
| 33 | { | ||
| 34 | unsigned int version : 8; | ||
| 35 | unsigned int ident : 24; | ||
| 36 | unsigned int machine : 16; | ||
| 37 | unsigned int unused : 16; | ||
| 38 | } __attribute__ ((packed)) cpuid_t; | ||
| 39 | |||
| 40 | static inline void get_cpu_id(cpuid_t *ptr) | 29 | static inline void get_cpu_id(cpuid_t *ptr) |
| 41 | { | 30 | { |
| 42 | asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); | 31 | asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); |
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index f1b051630c50..539263fc9ab9 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
| @@ -313,8 +313,6 @@ typedef struct | |||
| 313 | 313 | ||
| 314 | 314 | ||
| 315 | #ifdef __KERNEL__ | 315 | #ifdef __KERNEL__ |
| 316 | #include <asm/setup.h> | ||
| 317 | #include <asm/page.h> | ||
| 318 | 316 | ||
| 319 | /* | 317 | /* |
| 320 | * The pt_regs struct defines the way the registers are stored on | 318 | * The pt_regs struct defines the way the registers are stored on |
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index e8bd6ac22c99..38b0fc221ed7 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #ifdef __KERNEL__ | 15 | #ifdef __KERNEL__ |
| 16 | 16 | ||
| 17 | #include <asm/lowcore.h> | ||
| 17 | #include <asm/types.h> | 18 | #include <asm/types.h> |
| 18 | 19 | ||
| 19 | #define PARMAREA 0x10400 | 20 | #define PARMAREA 0x10400 |
| @@ -63,7 +64,6 @@ extern unsigned int s390_noexec; | |||
| 63 | /* | 64 | /* |
| 64 | * Machine features detected in head.S | 65 | * Machine features detected in head.S |
| 65 | */ | 66 | */ |
| 66 | extern unsigned long machine_flags; | ||
| 67 | 67 | ||
| 68 | #define MACHINE_FLAG_VM (1UL << 0) | 68 | #define MACHINE_FLAG_VM (1UL << 0) |
| 69 | #define MACHINE_FLAG_IEEE (1UL << 1) | 69 | #define MACHINE_FLAG_IEEE (1UL << 1) |
| @@ -77,28 +77,28 @@ extern unsigned long machine_flags; | |||
| 77 | #define MACHINE_FLAG_HPAGE (1UL << 10) | 77 | #define MACHINE_FLAG_HPAGE (1UL << 10) |
| 78 | #define MACHINE_FLAG_PFMF (1UL << 11) | 78 | #define MACHINE_FLAG_PFMF (1UL << 11) |
| 79 | 79 | ||
| 80 | #define MACHINE_IS_VM (machine_flags & MACHINE_FLAG_VM) | 80 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) |
| 81 | #define MACHINE_IS_KVM (machine_flags & MACHINE_FLAG_KVM) | 81 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) |
| 82 | #define MACHINE_HAS_DIAG9C (machine_flags & MACHINE_FLAG_DIAG9C) | 82 | #define MACHINE_HAS_DIAG9C (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C) |
| 83 | 83 | ||
| 84 | #ifndef __s390x__ | 84 | #ifndef __s390x__ |
| 85 | #define MACHINE_HAS_IEEE (machine_flags & MACHINE_FLAG_IEEE) | 85 | #define MACHINE_HAS_IEEE (S390_lowcore.machine_flags & MACHINE_FLAG_IEEE) |
| 86 | #define MACHINE_HAS_CSP (machine_flags & MACHINE_FLAG_CSP) | 86 | #define MACHINE_HAS_CSP (S390_lowcore.machine_flags & MACHINE_FLAG_CSP) |
| 87 | #define MACHINE_HAS_IDTE (0) | 87 | #define MACHINE_HAS_IDTE (0) |
| 88 | #define MACHINE_HAS_DIAG44 (1) | 88 | #define MACHINE_HAS_DIAG44 (1) |
| 89 | #define MACHINE_HAS_MVPG (machine_flags & MACHINE_FLAG_MVPG) | 89 | #define MACHINE_HAS_MVPG (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG) |
| 90 | #define MACHINE_HAS_MVCOS (0) | 90 | #define MACHINE_HAS_MVCOS (0) |
| 91 | #define MACHINE_HAS_HPAGE (0) | 91 | #define MACHINE_HAS_HPAGE (0) |
| 92 | #define MACHINE_HAS_PFMF (0) | 92 | #define MACHINE_HAS_PFMF (0) |
| 93 | #else /* __s390x__ */ | 93 | #else /* __s390x__ */ |
| 94 | #define MACHINE_HAS_IEEE (1) | 94 | #define MACHINE_HAS_IEEE (1) |
| 95 | #define MACHINE_HAS_CSP (1) | 95 | #define MACHINE_HAS_CSP (1) |
| 96 | #define MACHINE_HAS_IDTE (machine_flags & MACHINE_FLAG_IDTE) | 96 | #define MACHINE_HAS_IDTE (S390_lowcore.machine_flags & MACHINE_FLAG_IDTE) |
| 97 | #define MACHINE_HAS_DIAG44 (machine_flags & MACHINE_FLAG_DIAG44) | 97 | #define MACHINE_HAS_DIAG44 (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44) |
| 98 | #define MACHINE_HAS_MVPG (1) | 98 | #define MACHINE_HAS_MVPG (1) |
| 99 | #define MACHINE_HAS_MVCOS (machine_flags & MACHINE_FLAG_MVCOS) | 99 | #define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS) |
| 100 | #define MACHINE_HAS_HPAGE (machine_flags & MACHINE_FLAG_HPAGE) | 100 | #define MACHINE_HAS_HPAGE (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE) |
| 101 | #define MACHINE_HAS_PFMF (machine_flags & MACHINE_FLAG_PFMF) | 101 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) |
| 102 | #endif /* __s390x__ */ | 102 | #endif /* __s390x__ */ |
| 103 | 103 | ||
| 104 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) | 104 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) |
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index c544aa524535..461f2abd2e6f 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
| @@ -31,8 +31,9 @@ | |||
| 31 | #define ASYNC_SIZE (PAGE_SIZE << ASYNC_ORDER) | 31 | #define ASYNC_SIZE (PAGE_SIZE << ASYNC_ORDER) |
| 32 | 32 | ||
| 33 | #ifndef __ASSEMBLY__ | 33 | #ifndef __ASSEMBLY__ |
| 34 | #include <asm/processor.h> | ||
| 35 | #include <asm/lowcore.h> | 34 | #include <asm/lowcore.h> |
| 35 | #include <asm/page.h> | ||
| 36 | #include <asm/processor.h> | ||
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| 38 | * low level task data that entry.S needs immediate access to | 39 | * low level task data that entry.S needs immediate access to |
diff --git a/arch/s390/include/asm/timer.h b/arch/s390/include/asm/timer.h index e4bcab739c19..814243cafdfe 100644 --- a/arch/s390/include/asm/timer.h +++ b/arch/s390/include/asm/timer.h | |||
| @@ -41,6 +41,7 @@ extern void init_virt_timer(struct vtimer_list *timer); | |||
| 41 | extern void add_virt_timer(void *new); | 41 | extern void add_virt_timer(void *new); |
| 42 | extern void add_virt_timer_periodic(void *new); | 42 | extern void add_virt_timer_periodic(void *new); |
| 43 | extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); | 43 | extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); |
| 44 | extern int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires); | ||
| 44 | extern int del_virt_timer(struct vtimer_list *timer); | 45 | extern int del_virt_timer(struct vtimer_list *timer); |
| 45 | 46 | ||
| 46 | extern void init_cpu_vtimer(void); | 47 | extern void init_cpu_vtimer(void); |
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index d744c3d62de5..cc21e3e20fd7 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h | |||
| @@ -11,6 +11,9 @@ | |||
| 11 | #ifndef _ASM_S390_TIMEX_H | 11 | #ifndef _ASM_S390_TIMEX_H |
| 12 | #define _ASM_S390_TIMEX_H | 12 | #define _ASM_S390_TIMEX_H |
| 13 | 13 | ||
| 14 | /* The value of the TOD clock for 1.1.1970. */ | ||
| 15 | #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL | ||
| 16 | |||
| 14 | /* Inline functions for clock register access. */ | 17 | /* Inline functions for clock register access. */ |
| 15 | static inline int set_clock(__u64 time) | 18 | static inline int set_clock(__u64 time) |
| 16 | { | 19 | { |
| @@ -85,4 +88,6 @@ int get_sync_clock(unsigned long long *clock); | |||
| 85 | void init_cpu_timer(void); | 88 | void init_cpu_timer(void); |
| 86 | unsigned long long monotonic_clock(void); | 89 | unsigned long long monotonic_clock(void); |
| 87 | 90 | ||
| 91 | extern u64 sched_clock_base_cc; | ||
| 92 | |||
| 88 | #endif | 93 | #endif |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index c8ad350d1444..f0f19e6ace6c 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
| @@ -265,7 +265,9 @@ | |||
| 265 | #define __NR_pipe2 325 | 265 | #define __NR_pipe2 325 |
| 266 | #define __NR_dup3 326 | 266 | #define __NR_dup3 326 |
| 267 | #define __NR_epoll_create1 327 | 267 | #define __NR_epoll_create1 327 |
| 268 | #define NR_syscalls 328 | 268 | #define __NR_preadv 328 |
| 269 | #define __NR_pwritev 329 | ||
| 270 | #define NR_syscalls 330 | ||
| 269 | 271 | ||
| 270 | /* | 272 | /* |
| 271 | * There are some system calls that are not present on 64 bit, some | 273 | * There are some system calls that are not present on 64 bit, some |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 67a60016babb..fa9905ce7d0b 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
| @@ -27,6 +27,8 @@ int main(void) | |||
| 27 | DEFINE(__TI_flags, offsetof(struct thread_info, flags)); | 27 | DEFINE(__TI_flags, offsetof(struct thread_info, flags)); |
| 28 | DEFINE(__TI_cpu, offsetof(struct thread_info, cpu)); | 28 | DEFINE(__TI_cpu, offsetof(struct thread_info, cpu)); |
| 29 | DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); | 29 | DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); |
| 30 | DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer)); | ||
| 31 | DEFINE(__TI_system_timer, offsetof(struct thread_info, system_timer)); | ||
| 30 | BLANK(); | 32 | BLANK(); |
| 31 | DEFINE(__PT_ARGS, offsetof(struct pt_regs, args)); | 33 | DEFINE(__PT_ARGS, offsetof(struct pt_regs, args)); |
| 32 | DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); | 34 | DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 87cf5a79a351..fb38af6316bb 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
| @@ -1805,3 +1805,21 @@ compat_sys_keyctl_wrapper: | |||
| 1805 | llgfr %r5,%r5 # u32 | 1805 | llgfr %r5,%r5 # u32 |
| 1806 | llgfr %r6,%r6 # u32 | 1806 | llgfr %r6,%r6 # u32 |
| 1807 | jg compat_sys_keyctl # branch to system call | 1807 | jg compat_sys_keyctl # branch to system call |
| 1808 | |||
| 1809 | .globl compat_sys_preadv_wrapper | ||
| 1810 | compat_sys_preadv_wrapper: | ||
| 1811 | llgfr %r2,%r2 # unsigned long | ||
| 1812 | llgtr %r3,%r3 # compat_iovec * | ||
| 1813 | llgfr %r4,%r4 # unsigned long | ||
| 1814 | llgfr %r5,%r5 # u32 | ||
| 1815 | llgfr %r6,%r6 # u32 | ||
| 1816 | jg compat_sys_preadv # branch to system call | ||
| 1817 | |||
| 1818 | .globl compat_sys_pwritev_wrapper | ||
| 1819 | compat_sys_pwritev_wrapper: | ||
| 1820 | llgfr %r2,%r2 # unsigned long | ||
| 1821 | llgtr %r3,%r3 # compat_iovec * | ||
| 1822 | llgfr %r4,%r4 # unsigned long | ||
| 1823 | llgfr %r5,%r5 # u32 | ||
| 1824 | llgfr %r6,%r6 # u32 | ||
| 1825 | jg compat_sys_pwritev # branch to system call | ||
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 4d221c81c849..cf09948faad6 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
| @@ -34,8 +34,25 @@ | |||
| 34 | 34 | ||
| 35 | char kernel_nss_name[NSS_NAME_SIZE + 1]; | 35 | char kernel_nss_name[NSS_NAME_SIZE + 1]; |
| 36 | 36 | ||
| 37 | static unsigned long machine_flags; | ||
| 38 | |||
| 37 | static void __init setup_boot_command_line(void); | 39 | static void __init setup_boot_command_line(void); |
| 38 | 40 | ||
| 41 | /* | ||
| 42 | * Get the TOD clock running. | ||
| 43 | */ | ||
| 44 | static void __init reset_tod_clock(void) | ||
| 45 | { | ||
| 46 | u64 time; | ||
| 47 | |||
| 48 | if (store_clock(&time) == 0) | ||
| 49 | return; | ||
| 50 | /* TOD clock not running. Set the clock to Unix Epoch. */ | ||
| 51 | if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0) | ||
| 52 | disabled_wait(0); | ||
| 53 | |||
| 54 | sched_clock_base_cc = TOD_UNIX_EPOCH; | ||
| 55 | } | ||
| 39 | 56 | ||
| 40 | #ifdef CONFIG_SHARED_KERNEL | 57 | #ifdef CONFIG_SHARED_KERNEL |
| 41 | int __init savesys_ipl_nss(char *cmd, const int cmdlen); | 58 | int __init savesys_ipl_nss(char *cmd, const int cmdlen); |
| @@ -370,6 +387,7 @@ static void __init setup_boot_command_line(void) | |||
| 370 | */ | 387 | */ |
| 371 | void __init startup_init(void) | 388 | void __init startup_init(void) |
| 372 | { | 389 | { |
| 390 | reset_tod_clock(); | ||
| 373 | ipl_save_parameters(); | 391 | ipl_save_parameters(); |
| 374 | rescue_initrd(); | 392 | rescue_initrd(); |
| 375 | clear_bss_section(); | 393 | clear_bss_section(); |
| @@ -391,5 +409,6 @@ void __init startup_init(void) | |||
| 391 | setup_hpage(); | 409 | setup_hpage(); |
| 392 | sclp_facilities_detect(); | 410 | sclp_facilities_detect(); |
| 393 | detect_memory_layout(memory_chunk); | 411 | detect_memory_layout(memory_chunk); |
| 412 | S390_lowcore.machine_flags = machine_flags; | ||
| 394 | lockdep_on(); | 413 | lockdep_on(); |
| 395 | } | 414 | } |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1268aa2991bf..f3e275934213 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -837,16 +837,29 @@ mcck_return: | |||
| 837 | __CPUINIT | 837 | __CPUINIT |
| 838 | .globl restart_int_handler | 838 | .globl restart_int_handler |
| 839 | restart_int_handler: | 839 | restart_int_handler: |
| 840 | basr %r1,0 | ||
| 841 | restart_base: | ||
| 842 | spt restart_vtime-restart_base(%r1) | ||
| 843 | stck __LC_LAST_UPDATE_CLOCK | ||
| 844 | mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1) | ||
| 845 | mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1) | ||
| 840 | l %r15,__LC_SAVE_AREA+60 # load ksp | 846 | l %r15,__LC_SAVE_AREA+60 # load ksp |
| 841 | lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs | 847 | lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs |
| 842 | lam %a0,%a15,__LC_AREGS_SAVE_AREA | 848 | lam %a0,%a15,__LC_AREGS_SAVE_AREA |
| 843 | lm %r6,%r15,__SF_GPRS(%r15) # load registers from clone | 849 | lm %r6,%r15,__SF_GPRS(%r15) # load registers from clone |
| 850 | l %r1,__LC_THREAD_INFO | ||
| 851 | mvc __LC_USER_TIMER(8),__TI_user_timer(%r1) | ||
| 852 | mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1) | ||
| 853 | xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER | ||
| 844 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on | 854 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on |
| 845 | basr %r14,0 | 855 | basr %r14,0 |
| 846 | l %r14,restart_addr-.(%r14) | 856 | l %r14,restart_addr-.(%r14) |
| 847 | br %r14 # branch to start_secondary | 857 | br %r14 # branch to start_secondary |
| 848 | restart_addr: | 858 | restart_addr: |
| 849 | .long start_secondary | 859 | .long start_secondary |
| 860 | .align 8 | ||
| 861 | restart_vtime: | ||
| 862 | .long 0x7fffffff,0xffffffff | ||
| 850 | .previous | 863 | .previous |
| 851 | #else | 864 | #else |
| 852 | /* | 865 | /* |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index c6fbde13971a..84a105838e03 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
| @@ -831,14 +831,27 @@ mcck_return: | |||
| 831 | __CPUINIT | 831 | __CPUINIT |
| 832 | .globl restart_int_handler | 832 | .globl restart_int_handler |
| 833 | restart_int_handler: | 833 | restart_int_handler: |
| 834 | basr %r1,0 | ||
| 835 | restart_base: | ||
| 836 | spt restart_vtime-restart_base(%r1) | ||
| 837 | stck __LC_LAST_UPDATE_CLOCK | ||
| 838 | mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1) | ||
| 839 | mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1) | ||
| 834 | lg %r15,__LC_SAVE_AREA+120 # load ksp | 840 | lg %r15,__LC_SAVE_AREA+120 # load ksp |
| 835 | lghi %r10,__LC_CREGS_SAVE_AREA | 841 | lghi %r10,__LC_CREGS_SAVE_AREA |
| 836 | lctlg %c0,%c15,0(%r10) # get new ctl regs | 842 | lctlg %c0,%c15,0(%r10) # get new ctl regs |
| 837 | lghi %r10,__LC_AREGS_SAVE_AREA | 843 | lghi %r10,__LC_AREGS_SAVE_AREA |
| 838 | lam %a0,%a15,0(%r10) | 844 | lam %a0,%a15,0(%r10) |
| 839 | lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone | 845 | lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone |
| 846 | lg %r1,__LC_THREAD_INFO | ||
| 847 | mvc __LC_USER_TIMER(8),__TI_user_timer(%r1) | ||
| 848 | mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1) | ||
| 849 | xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER | ||
| 840 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on | 850 | stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on |
| 841 | jg start_secondary | 851 | jg start_secondary |
| 852 | .align 8 | ||
| 853 | restart_vtime: | ||
| 854 | .long 0x7fffffff,0xffffffff | ||
| 842 | .previous | 855 | .previous |
| 843 | #else | 856 | #else |
| 844 | /* | 857 | /* |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 1046c2c9f8d1..bba14494ee00 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
| @@ -471,7 +471,12 @@ startup:basr %r13,0 # get base | |||
| 471 | .LPG0: | 471 | .LPG0: |
| 472 | xc 0x200(256),0x200 # partially clear lowcore | 472 | xc 0x200(256),0x200 # partially clear lowcore |
| 473 | xc 0x300(256),0x300 | 473 | xc 0x300(256),0x300 |
| 474 | 474 | l %r1,5f-.LPG0(%r13) | |
| 475 | stck 0(%r1) | ||
| 476 | spt 6f-.LPG0(%r13) | ||
| 477 | mvc __LC_LAST_UPDATE_CLOCK(8),0(%r1) | ||
| 478 | mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13) | ||
| 479 | mvc __LC_EXIT_TIMER(8),5f-.LPG0(%r13) | ||
| 475 | #ifndef CONFIG_MARCH_G5 | 480 | #ifndef CONFIG_MARCH_G5 |
| 476 | # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} | 481 | # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} |
| 477 | stidp __LC_CPUID # store cpuid | 482 | stidp __LC_CPUID # store cpuid |
| @@ -496,9 +501,13 @@ startup:basr %r13,0 # get base | |||
| 496 | brct %r0,0b | 501 | brct %r0,0b |
| 497 | #endif | 502 | #endif |
| 498 | 503 | ||
| 499 | l %r13,0f-.LPG0(%r13) | 504 | l %r13,4f-.LPG0(%r13) |
| 500 | b 0(%r13) | 505 | b 0(%r13) |
| 501 | 0: .long startup_continue | 506 | .align 4 |
| 507 | 4: .long startup_continue | ||
| 508 | 5: .long sched_clock_base_cc | ||
| 509 | .align 8 | ||
| 510 | 6: .long 0x7fffffff,0xffffffff | ||
| 502 | 511 | ||
| 503 | # | 512 | # |
| 504 | # params at 10400 (setup.h) | 513 | # params at 10400 (setup.h) |
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 4bfdc421d7e9..28cf196ba775 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 13 | #include <linux/hardirq.h> | ||
| 13 | #include <linux/time.h> | 14 | #include <linux/time.h> |
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 15 | #include <asm/lowcore.h> | 16 | #include <asm/lowcore.h> |
| @@ -253,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs) | |||
| 253 | struct mci *mci; | 254 | struct mci *mci; |
| 254 | int umode; | 255 | int umode; |
| 255 | 256 | ||
| 256 | lockdep_off(); | 257 | nmi_enter(); |
| 257 | s390_idle_check(); | 258 | s390_idle_check(); |
| 258 | 259 | ||
| 259 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; | 260 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; |
| @@ -363,7 +364,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs) | |||
| 363 | mcck->warning = 1; | 364 | mcck->warning = 1; |
| 364 | set_thread_flag(TIF_MCCK_PENDING); | 365 | set_thread_flag(TIF_MCCK_PENDING); |
| 365 | } | 366 | } |
| 366 | lockdep_on(); | 367 | nmi_exit(); |
| 367 | } | 368 | } |
| 368 | 369 | ||
| 369 | static int __init machine_check_init(void) | 370 | static int __init machine_check_init(void) |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 06201b93cbbf..7402b6a39ead 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
| @@ -82,9 +82,6 @@ EXPORT_SYMBOL(console_devno); | |||
| 82 | unsigned int console_irq = -1; | 82 | unsigned int console_irq = -1; |
| 83 | EXPORT_SYMBOL(console_irq); | 83 | EXPORT_SYMBOL(console_irq); |
| 84 | 84 | ||
| 85 | unsigned long machine_flags; | ||
| 86 | EXPORT_SYMBOL(machine_flags); | ||
| 87 | |||
| 88 | unsigned long elf_hwcap = 0; | 85 | unsigned long elf_hwcap = 0; |
| 89 | char elf_platform[ELF_PLATFORM_SIZE]; | 86 | char elf_platform[ELF_PLATFORM_SIZE]; |
| 90 | 87 | ||
| @@ -426,6 +423,7 @@ setup_lowcore(void) | |||
| 426 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; | 423 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; |
| 427 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; | 424 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; |
| 428 | lc->thread_info = (unsigned long) &init_thread_union; | 425 | lc->thread_info = (unsigned long) &init_thread_union; |
| 426 | lc->machine_flags = S390_lowcore.machine_flags; | ||
| 429 | #ifndef CONFIG_64BIT | 427 | #ifndef CONFIG_64BIT |
| 430 | if (MACHINE_HAS_IEEE) { | 428 | if (MACHINE_HAS_IEEE) { |
| 431 | lc->extended_save_area_addr = (__u32) | 429 | lc->extended_save_area_addr = (__u32) |
| @@ -436,6 +434,14 @@ setup_lowcore(void) | |||
| 436 | #else | 434 | #else |
| 437 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; | 435 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; |
| 438 | #endif | 436 | #endif |
| 437 | lc->sync_enter_timer = S390_lowcore.sync_enter_timer; | ||
| 438 | lc->async_enter_timer = S390_lowcore.async_enter_timer; | ||
| 439 | lc->exit_timer = S390_lowcore.exit_timer; | ||
| 440 | lc->user_timer = S390_lowcore.user_timer; | ||
| 441 | lc->system_timer = S390_lowcore.system_timer; | ||
| 442 | lc->steal_timer = S390_lowcore.steal_timer; | ||
| 443 | lc->last_update_timer = S390_lowcore.last_update_timer; | ||
| 444 | lc->last_update_clock = S390_lowcore.last_update_clock; | ||
| 439 | set_prefix((u32)(unsigned long) lc); | 445 | set_prefix((u32)(unsigned long) lc); |
| 440 | lowcore_ptr[0] = lc; | 446 | lowcore_ptr[0] = lc; |
| 441 | } | 447 | } |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 006ed5016eb4..a985a3ba4401 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
| @@ -571,6 +571,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
| 571 | cpu_lowcore->current_task = (unsigned long) idle; | 571 | cpu_lowcore->current_task = (unsigned long) idle; |
| 572 | cpu_lowcore->cpu_nr = cpu; | 572 | cpu_lowcore->cpu_nr = cpu; |
| 573 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; | 573 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; |
| 574 | cpu_lowcore->machine_flags = S390_lowcore.machine_flags; | ||
| 574 | eieio(); | 575 | eieio(); |
| 575 | 576 | ||
| 576 | while (signal_processor(cpu, sigp_restart) == sigp_busy) | 577 | while (signal_processor(cpu, sigp_restart) == sigp_busy) |
| @@ -590,7 +591,8 @@ static int __init setup_possible_cpus(char *s) | |||
| 590 | int pcpus, cpu; | 591 | int pcpus, cpu; |
| 591 | 592 | ||
| 592 | pcpus = simple_strtoul(s, NULL, 0); | 593 | pcpus = simple_strtoul(s, NULL, 0); |
| 593 | for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++) | 594 | init_cpu_possible(cpumask_of(0)); |
| 595 | for (cpu = 1; cpu < pcpus && cpu < nr_cpu_ids; cpu++) | ||
| 594 | set_cpu_possible(cpu, true); | 596 | set_cpu_possible(cpu, true); |
| 595 | return 0; | 597 | return 0; |
| 596 | } | 598 | } |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index fe5b25a988ab..2c7739fe70b1 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
| @@ -336,3 +336,5 @@ SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper) | |||
| 336 | SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */ | 336 | SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */ |
| 337 | SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper) | 337 | SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper) |
| 338 | SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper) | 338 | SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper) |
| 339 | SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper) | ||
| 340 | SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper) | ||
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index f72d41068dc2..6ded50dfa75a 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
| @@ -52,9 +52,6 @@ | |||
| 52 | #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) | 52 | #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) |
| 53 | #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) | 53 | #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) |
| 54 | 54 | ||
| 55 | /* The value of the TOD clock for 1.1.1970. */ | ||
| 56 | #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL | ||
| 57 | |||
| 58 | /* | 55 | /* |
| 59 | * Create a small time difference between the timer interrupts | 56 | * Create a small time difference between the timer interrupts |
| 60 | * on the different cpus to avoid lock contention. | 57 | * on the different cpus to avoid lock contention. |
| @@ -63,9 +60,10 @@ | |||
| 63 | 60 | ||
| 64 | #define TICK_SIZE tick | 61 | #define TICK_SIZE tick |
| 65 | 62 | ||
| 63 | u64 sched_clock_base_cc = -1; /* Force to data section. */ | ||
| 64 | |||
| 66 | static ext_int_info_t ext_int_info_cc; | 65 | static ext_int_info_t ext_int_info_cc; |
| 67 | static ext_int_info_t ext_int_etr_cc; | 66 | static ext_int_info_t ext_int_etr_cc; |
| 68 | static u64 sched_clock_base_cc; | ||
| 69 | 67 | ||
| 70 | static DEFINE_PER_CPU(struct clock_event_device, comparators); | 68 | static DEFINE_PER_CPU(struct clock_event_device, comparators); |
| 71 | 69 | ||
| @@ -195,22 +193,12 @@ static void timing_alert_interrupt(__u16 code) | |||
| 195 | static void etr_reset(void); | 193 | static void etr_reset(void); |
| 196 | static void stp_reset(void); | 194 | static void stp_reset(void); |
| 197 | 195 | ||
| 198 | /* | 196 | unsigned long read_persistent_clock(void) |
| 199 | * Get the TOD clock running. | ||
| 200 | */ | ||
| 201 | static u64 __init reset_tod_clock(void) | ||
| 202 | { | 197 | { |
| 203 | u64 time; | 198 | struct timespec ts; |
| 204 | |||
| 205 | etr_reset(); | ||
| 206 | stp_reset(); | ||
| 207 | if (store_clock(&time) == 0) | ||
| 208 | return time; | ||
| 209 | /* TOD clock not running. Set the clock to Unix Epoch. */ | ||
| 210 | if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0) | ||
| 211 | panic("TOD clock not operational."); | ||
| 212 | 199 | ||
| 213 | return TOD_UNIX_EPOCH; | 200 | tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, &ts); |
| 201 | return ts.tv_sec; | ||
| 214 | } | 202 | } |
| 215 | 203 | ||
| 216 | static cycle_t read_tod_clock(void) | 204 | static cycle_t read_tod_clock(void) |
| @@ -265,12 +253,13 @@ void update_vsyscall_tz(void) | |||
| 265 | */ | 253 | */ |
| 266 | void __init time_init(void) | 254 | void __init time_init(void) |
| 267 | { | 255 | { |
| 268 | sched_clock_base_cc = reset_tod_clock(); | 256 | struct timespec ts; |
| 257 | unsigned long flags; | ||
| 258 | cycle_t now; | ||
| 269 | 259 | ||
| 270 | /* set xtime */ | 260 | /* Reset time synchronization interfaces. */ |
| 271 | tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime); | 261 | etr_reset(); |
| 272 | set_normalized_timespec(&wall_to_monotonic, | 262 | stp_reset(); |
| 273 | -xtime.tv_sec, -xtime.tv_nsec); | ||
| 274 | 263 | ||
| 275 | /* request the clock comparator external interrupt */ | 264 | /* request the clock comparator external interrupt */ |
| 276 | if (register_early_external_interrupt(0x1004, | 265 | if (register_early_external_interrupt(0x1004, |
| @@ -278,17 +267,38 @@ void __init time_init(void) | |||
| 278 | &ext_int_info_cc) != 0) | 267 | &ext_int_info_cc) != 0) |
| 279 | panic("Couldn't request external interrupt 0x1004"); | 268 | panic("Couldn't request external interrupt 0x1004"); |
| 280 | 269 | ||
| 281 | if (clocksource_register(&clocksource_tod) != 0) | ||
| 282 | panic("Could not register TOD clock source"); | ||
| 283 | |||
| 284 | /* request the timing alert external interrupt */ | 270 | /* request the timing alert external interrupt */ |
| 285 | if (register_early_external_interrupt(0x1406, | 271 | if (register_early_external_interrupt(0x1406, |
| 286 | timing_alert_interrupt, | 272 | timing_alert_interrupt, |
| 287 | &ext_int_etr_cc) != 0) | 273 | &ext_int_etr_cc) != 0) |
| 288 | panic("Couldn't request external interrupt 0x1406"); | 274 | panic("Couldn't request external interrupt 0x1406"); |
| 289 | 275 | ||
| 276 | if (clocksource_register(&clocksource_tod) != 0) | ||
| 277 | panic("Could not register TOD clock source"); | ||
| 278 | |||
| 279 | /* | ||
| 280 | * The TOD clock is an accurate clock. The xtime should be | ||
| 281 | * initialized in a way that the difference between TOD and | ||
| 282 | * xtime is reasonably small. Too bad that timekeeping_init | ||
| 283 | * sets xtime.tv_nsec to zero. In addition the clock source | ||
| 284 | * change from the jiffies clock source to the TOD clock | ||
| 285 | * source add another error of up to 1/HZ second. The same | ||
| 286 | * function sets wall_to_monotonic to a value that is too | ||
| 287 | * small for /proc/uptime to be accurate. | ||
| 288 | * Reset xtime and wall_to_monotonic to sane values. | ||
| 289 | */ | ||
| 290 | write_seqlock_irqsave(&xtime_lock, flags); | ||
| 291 | now = get_clock(); | ||
| 292 | tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime); | ||
| 293 | clocksource_tod.cycle_last = now; | ||
| 294 | clocksource_tod.raw_time = xtime; | ||
| 295 | tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts); | ||
| 296 | set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec); | ||
| 297 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
| 298 | |||
| 290 | /* Enable TOD clock interrupts on the boot cpu. */ | 299 | /* Enable TOD clock interrupts on the boot cpu. */ |
| 291 | init_cpu_timer(); | 300 | init_cpu_timer(); |
| 301 | |||
| 292 | /* Enable cpu timer interrupts on the boot cpu. */ | 302 | /* Enable cpu timer interrupts on the boot cpu. */ |
| 293 | vtime_init(); | 303 | vtime_init(); |
| 294 | } | 304 | } |
| @@ -1423,6 +1433,7 @@ static void *stp_page; | |||
| 1423 | static void stp_work_fn(struct work_struct *work); | 1433 | static void stp_work_fn(struct work_struct *work); |
| 1424 | static DEFINE_MUTEX(stp_work_mutex); | 1434 | static DEFINE_MUTEX(stp_work_mutex); |
| 1425 | static DECLARE_WORK(stp_work, stp_work_fn); | 1435 | static DECLARE_WORK(stp_work, stp_work_fn); |
| 1436 | static struct timer_list stp_timer; | ||
| 1426 | 1437 | ||
| 1427 | static int __init early_parse_stp(char *p) | 1438 | static int __init early_parse_stp(char *p) |
| 1428 | { | 1439 | { |
| @@ -1454,10 +1465,16 @@ static void __init stp_reset(void) | |||
| 1454 | } | 1465 | } |
| 1455 | } | 1466 | } |
| 1456 | 1467 | ||
| 1468 | static void stp_timeout(unsigned long dummy) | ||
| 1469 | { | ||
| 1470 | queue_work(time_sync_wq, &stp_work); | ||
| 1471 | } | ||
| 1472 | |||
| 1457 | static int __init stp_init(void) | 1473 | static int __init stp_init(void) |
| 1458 | { | 1474 | { |
| 1459 | if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) | 1475 | if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) |
| 1460 | return 0; | 1476 | return 0; |
| 1477 | setup_timer(&stp_timer, stp_timeout, 0UL); | ||
| 1461 | time_init_wq(); | 1478 | time_init_wq(); |
| 1462 | if (!stp_online) | 1479 | if (!stp_online) |
| 1463 | return 0; | 1480 | return 0; |
| @@ -1565,6 +1582,7 @@ static void stp_work_fn(struct work_struct *work) | |||
| 1565 | 1582 | ||
| 1566 | if (!stp_online) { | 1583 | if (!stp_online) { |
| 1567 | chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); | 1584 | chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); |
| 1585 | del_timer_sync(&stp_timer); | ||
| 1568 | goto out_unlock; | 1586 | goto out_unlock; |
| 1569 | } | 1587 | } |
| 1570 | 1588 | ||
| @@ -1586,6 +1604,13 @@ static void stp_work_fn(struct work_struct *work) | |||
| 1586 | stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map); | 1604 | stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map); |
| 1587 | put_online_cpus(); | 1605 | put_online_cpus(); |
| 1588 | 1606 | ||
| 1607 | if (!check_sync_clock()) | ||
| 1608 | /* | ||
| 1609 | * There is a usable clock but the synchonization failed. | ||
| 1610 | * Retry after a second. | ||
| 1611 | */ | ||
| 1612 | mod_timer(&stp_timer, jiffies + HZ); | ||
| 1613 | |||
| 1589 | out_unlock: | 1614 | out_unlock: |
| 1590 | mutex_unlock(&stp_work_mutex); | 1615 | mutex_unlock(&stp_work_mutex); |
| 1591 | } | 1616 | } |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index ecf0304e61c1..38ea92ff04f9 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
| @@ -134,6 +134,8 @@ void vtime_start_cpu(void) | |||
| 134 | /* Account time spent with enabled wait psw loaded as idle time. */ | 134 | /* Account time spent with enabled wait psw loaded as idle time. */ |
| 135 | idle_time = S390_lowcore.int_clock - idle->idle_enter; | 135 | idle_time = S390_lowcore.int_clock - idle->idle_enter; |
| 136 | account_idle_time(idle_time); | 136 | account_idle_time(idle_time); |
| 137 | S390_lowcore.steal_timer += | ||
| 138 | idle->idle_enter - S390_lowcore.last_update_clock; | ||
| 137 | S390_lowcore.last_update_clock = S390_lowcore.int_clock; | 139 | S390_lowcore.last_update_clock = S390_lowcore.int_clock; |
| 138 | 140 | ||
| 139 | /* Account system time spent going idle. */ | 141 | /* Account system time spent going idle. */ |
| @@ -425,17 +427,7 @@ void add_virt_timer_periodic(void *new) | |||
| 425 | } | 427 | } |
| 426 | EXPORT_SYMBOL(add_virt_timer_periodic); | 428 | EXPORT_SYMBOL(add_virt_timer_periodic); |
| 427 | 429 | ||
| 428 | /* | 430 | int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic) |
| 429 | * If we change a pending timer the function must be called on the CPU | ||
| 430 | * where the timer is running on, e.g. by smp_call_function_single() | ||
| 431 | * | ||
| 432 | * The original mod_timer adds the timer if it is not pending. For | ||
| 433 | * compatibility we do the same. The timer will be added on the current | ||
| 434 | * CPU as a oneshot timer. | ||
| 435 | * | ||
| 436 | * returns whether it has modified a pending timer (1) or not (0) | ||
| 437 | */ | ||
| 438 | int mod_virt_timer(struct vtimer_list *timer, __u64 expires) | ||
| 439 | { | 431 | { |
| 440 | struct vtimer_queue *vq; | 432 | struct vtimer_queue *vq; |
| 441 | unsigned long flags; | 433 | unsigned long flags; |
| @@ -444,39 +436,35 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires) | |||
| 444 | BUG_ON(!timer->function); | 436 | BUG_ON(!timer->function); |
| 445 | BUG_ON(!expires || expires > VTIMER_MAX_SLICE); | 437 | BUG_ON(!expires || expires > VTIMER_MAX_SLICE); |
| 446 | 438 | ||
| 447 | /* | ||
| 448 | * This is a common optimization triggered by the | ||
| 449 | * networking code - if the timer is re-modified | ||
| 450 | * to be the same thing then just return: | ||
| 451 | */ | ||
| 452 | if (timer->expires == expires && vtimer_pending(timer)) | 439 | if (timer->expires == expires && vtimer_pending(timer)) |
| 453 | return 1; | 440 | return 1; |
| 454 | 441 | ||
| 455 | cpu = get_cpu(); | 442 | cpu = get_cpu(); |
| 456 | vq = &per_cpu(virt_cpu_timer, cpu); | 443 | vq = &per_cpu(virt_cpu_timer, cpu); |
| 457 | 444 | ||
| 458 | /* check if we run on the right CPU */ | ||
| 459 | BUG_ON(timer->cpu != cpu); | ||
| 460 | |||
| 461 | /* disable interrupts before test if timer is pending */ | 445 | /* disable interrupts before test if timer is pending */ |
| 462 | spin_lock_irqsave(&vq->lock, flags); | 446 | spin_lock_irqsave(&vq->lock, flags); |
| 463 | 447 | ||
| 464 | /* if timer isn't pending add it on the current CPU */ | 448 | /* if timer isn't pending add it on the current CPU */ |
| 465 | if (!vtimer_pending(timer)) { | 449 | if (!vtimer_pending(timer)) { |
| 466 | spin_unlock_irqrestore(&vq->lock, flags); | 450 | spin_unlock_irqrestore(&vq->lock, flags); |
| 467 | /* we do not activate an interval timer with mod_virt_timer */ | 451 | |
| 468 | timer->interval = 0; | 452 | if (periodic) |
| 453 | timer->interval = expires; | ||
| 454 | else | ||
| 455 | timer->interval = 0; | ||
| 469 | timer->expires = expires; | 456 | timer->expires = expires; |
| 470 | timer->cpu = cpu; | 457 | timer->cpu = cpu; |
| 471 | internal_add_vtimer(timer); | 458 | internal_add_vtimer(timer); |
| 472 | return 0; | 459 | return 0; |
| 473 | } | 460 | } |
| 474 | 461 | ||
| 462 | /* check if we run on the right CPU */ | ||
| 463 | BUG_ON(timer->cpu != cpu); | ||
| 464 | |||
| 475 | list_del_init(&timer->entry); | 465 | list_del_init(&timer->entry); |
| 476 | timer->expires = expires; | 466 | timer->expires = expires; |
| 477 | 467 | if (periodic) | |
| 478 | /* also change the interval if we have an interval timer */ | ||
| 479 | if (timer->interval) | ||
| 480 | timer->interval = expires; | 468 | timer->interval = expires; |
| 481 | 469 | ||
| 482 | /* the timer can't expire anymore so we can release the lock */ | 470 | /* the timer can't expire anymore so we can release the lock */ |
| @@ -484,9 +472,32 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires) | |||
| 484 | internal_add_vtimer(timer); | 472 | internal_add_vtimer(timer); |
| 485 | return 1; | 473 | return 1; |
| 486 | } | 474 | } |
| 475 | |||
| 476 | /* | ||
| 477 | * If we change a pending timer the function must be called on the CPU | ||
| 478 | * where the timer is running on. | ||
| 479 | * | ||
| 480 | * returns whether it has modified a pending timer (1) or not (0) | ||
| 481 | */ | ||
| 482 | int mod_virt_timer(struct vtimer_list *timer, __u64 expires) | ||
| 483 | { | ||
| 484 | return __mod_vtimer(timer, expires, 0); | ||
| 485 | } | ||
| 487 | EXPORT_SYMBOL(mod_virt_timer); | 486 | EXPORT_SYMBOL(mod_virt_timer); |
| 488 | 487 | ||
| 489 | /* | 488 | /* |
| 489 | * If we change a pending timer the function must be called on the CPU | ||
| 490 | * where the timer is running on. | ||
| 491 | * | ||
| 492 | * returns whether it has modified a pending timer (1) or not (0) | ||
| 493 | */ | ||
| 494 | int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires) | ||
| 495 | { | ||
| 496 | return __mod_vtimer(timer, expires, 1); | ||
| 497 | } | ||
| 498 | EXPORT_SYMBOL(mod_virt_timer_periodic); | ||
| 499 | |||
| 500 | /* | ||
| 490 | * delete a virtual timer | 501 | * delete a virtual timer |
| 491 | * | 502 | * |
| 492 | * returns whether the deleted timer was pending (1) or not (0) | 503 | * returns whether the deleted timer was pending (1) or not (0) |
| @@ -516,16 +527,8 @@ EXPORT_SYMBOL(del_virt_timer); | |||
| 516 | */ | 527 | */ |
| 517 | void init_cpu_vtimer(void) | 528 | void init_cpu_vtimer(void) |
| 518 | { | 529 | { |
| 519 | struct thread_info *ti = current_thread_info(); | ||
| 520 | struct vtimer_queue *vq; | 530 | struct vtimer_queue *vq; |
| 521 | 531 | ||
| 522 | S390_lowcore.user_timer = ti->user_timer; | ||
| 523 | S390_lowcore.system_timer = ti->system_timer; | ||
| 524 | |||
| 525 | /* kick the virtual timer */ | ||
| 526 | asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock)); | ||
| 527 | asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer)); | ||
| 528 | |||
| 529 | /* initialize per cpu vtimer structure */ | 532 | /* initialize per cpu vtimer structure */ |
| 530 | vq = &__get_cpu_var(virt_cpu_timer); | 533 | vq = &__get_cpu_var(virt_cpu_timer); |
| 531 | INIT_LIST_HEAD(&vq->list); | 534 | INIT_LIST_HEAD(&vq->list); |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0570794ccf1c..d1815272c435 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
| 22 | #include <linux/hdreg.h> | 22 | #include <linux/hdreg.h> |
| 23 | #include <linux/async.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/ccwdev.h> | 25 | #include <asm/ccwdev.h> |
| 25 | #include <asm/ebcdic.h> | 26 | #include <asm/ebcdic.h> |
| @@ -480,8 +481,10 @@ static void dasd_change_state(struct dasd_device *device) | |||
| 480 | if (rc && rc != -EAGAIN) | 481 | if (rc && rc != -EAGAIN) |
| 481 | device->target = device->state; | 482 | device->target = device->state; |
| 482 | 483 | ||
| 483 | if (device->state == device->target) | 484 | if (device->state == device->target) { |
| 484 | wake_up(&dasd_init_waitq); | 485 | wake_up(&dasd_init_waitq); |
| 486 | dasd_put_device(device); | ||
| 487 | } | ||
| 485 | 488 | ||
| 486 | /* let user-space know that the device status changed */ | 489 | /* let user-space know that the device status changed */ |
| 487 | kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); | 490 | kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); |
| @@ -513,12 +516,15 @@ void dasd_kick_device(struct dasd_device *device) | |||
| 513 | */ | 516 | */ |
| 514 | void dasd_set_target_state(struct dasd_device *device, int target) | 517 | void dasd_set_target_state(struct dasd_device *device, int target) |
| 515 | { | 518 | { |
| 519 | dasd_get_device(device); | ||
| 516 | /* If we are in probeonly mode stop at DASD_STATE_READY. */ | 520 | /* If we are in probeonly mode stop at DASD_STATE_READY. */ |
| 517 | if (dasd_probeonly && target > DASD_STATE_READY) | 521 | if (dasd_probeonly && target > DASD_STATE_READY) |
| 518 | target = DASD_STATE_READY; | 522 | target = DASD_STATE_READY; |
| 519 | if (device->target != target) { | 523 | if (device->target != target) { |
| 520 | if (device->state == target) | 524 | if (device->state == target) { |
| 521 | wake_up(&dasd_init_waitq); | 525 | wake_up(&dasd_init_waitq); |
| 526 | dasd_put_device(device); | ||
| 527 | } | ||
| 522 | device->target = target; | 528 | device->target = target; |
| 523 | } | 529 | } |
| 524 | if (device->state != device->target) | 530 | if (device->state != device->target) |
| @@ -2148,6 +2154,22 @@ dasd_exit(void) | |||
| 2148 | * SECTION: common functions for ccw_driver use | 2154 | * SECTION: common functions for ccw_driver use |
| 2149 | */ | 2155 | */ |
| 2150 | 2156 | ||
| 2157 | static void dasd_generic_auto_online(void *data, async_cookie_t cookie) | ||
| 2158 | { | ||
| 2159 | struct ccw_device *cdev = data; | ||
| 2160 | int ret; | ||
| 2161 | |||
| 2162 | ret = ccw_device_set_online(cdev); | ||
| 2163 | if (ret) | ||
| 2164 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", | ||
| 2165 | dev_name(&cdev->dev), ret); | ||
| 2166 | else { | ||
| 2167 | struct dasd_device *device = dasd_device_from_cdev(cdev); | ||
| 2168 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
| 2169 | dasd_put_device(device); | ||
| 2170 | } | ||
| 2171 | } | ||
| 2172 | |||
| 2151 | /* | 2173 | /* |
| 2152 | * Initial attempt at a probe function. this can be simplified once | 2174 | * Initial attempt at a probe function. this can be simplified once |
| 2153 | * the other detection code is gone. | 2175 | * the other detection code is gone. |
| @@ -2180,10 +2202,7 @@ int dasd_generic_probe(struct ccw_device *cdev, | |||
| 2180 | */ | 2202 | */ |
| 2181 | if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || | 2203 | if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || |
| 2182 | (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) | 2204 | (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) |
| 2183 | ret = ccw_device_set_online(cdev); | 2205 | async_schedule(dasd_generic_auto_online, cdev); |
| 2184 | if (ret) | ||
| 2185 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", | ||
| 2186 | dev_name(&cdev->dev), ret); | ||
| 2187 | return 0; | 2206 | return 0; |
| 2188 | } | 2207 | } |
| 2189 | 2208 | ||
| @@ -2290,13 +2309,7 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
| 2290 | } else | 2309 | } else |
| 2291 | pr_debug("dasd_generic device %s found\n", | 2310 | pr_debug("dasd_generic device %s found\n", |
| 2292 | dev_name(&cdev->dev)); | 2311 | dev_name(&cdev->dev)); |
| 2293 | |||
| 2294 | /* FIXME: we have to wait for the root device but we don't want | ||
| 2295 | * to wait for each single device but for all at once. */ | ||
| 2296 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
| 2297 | |||
| 2298 | dasd_put_device(device); | 2312 | dasd_put_device(device); |
| 2299 | |||
| 2300 | return rc; | 2313 | return rc; |
| 2301 | } | 2314 | } |
| 2302 | 2315 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 21254793c604..cb52da033f06 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -2019,15 +2019,23 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
| 2019 | ccw++; | 2019 | ccw++; |
| 2020 | recid += count; | 2020 | recid += count; |
| 2021 | new_track = 0; | 2021 | new_track = 0; |
| 2022 | /* first idaw for a ccw may start anywhere */ | ||
| 2023 | if (!idaw_dst) | ||
| 2024 | idaw_dst = dst; | ||
| 2022 | } | 2025 | } |
| 2023 | /* If we start a new idaw, everything is fine and the | 2026 | /* If we start a new idaw, we must make sure that it |
| 2024 | * start of the new idaw is the start of this segment. | 2027 | * starts on an IDA_BLOCK_SIZE boundary. |
| 2025 | * If we continue an idaw, we must make sure that the | 2028 | * If we continue an idaw, we must make sure that the |
| 2026 | * current segment begins where the so far accumulated | 2029 | * current segment begins where the so far accumulated |
| 2027 | * idaw ends | 2030 | * idaw ends |
| 2028 | */ | 2031 | */ |
| 2029 | if (!idaw_dst) | 2032 | if (!idaw_dst) { |
| 2030 | idaw_dst = dst; | 2033 | if (__pa(dst) & (IDA_BLOCK_SIZE-1)) { |
| 2034 | dasd_sfree_request(cqr, startdev); | ||
| 2035 | return ERR_PTR(-ERANGE); | ||
| 2036 | } else | ||
| 2037 | idaw_dst = dst; | ||
| 2038 | } | ||
| 2031 | if ((idaw_dst + idaw_len) != dst) { | 2039 | if ((idaw_dst + idaw_len) != dst) { |
| 2032 | dasd_sfree_request(cqr, startdev); | 2040 | dasd_sfree_request(cqr, startdev); |
| 2033 | return ERR_PTR(-ERANGE); | 2041 | return ERR_PTR(-ERANGE); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 9e8a2914259b..accd957454e7 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -881,42 +881,6 @@ no_handler: | |||
| 881 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | 881 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); |
| 882 | } | 882 | } |
| 883 | 883 | ||
| 884 | static void qdio_call_shutdown(struct work_struct *work) | ||
| 885 | { | ||
| 886 | struct ccw_device_private *priv; | ||
| 887 | struct ccw_device *cdev; | ||
| 888 | |||
| 889 | priv = container_of(work, struct ccw_device_private, kick_work); | ||
| 890 | cdev = priv->cdev; | ||
| 891 | qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); | ||
| 892 | put_device(&cdev->dev); | ||
| 893 | } | ||
| 894 | |||
| 895 | static void qdio_int_error(struct ccw_device *cdev) | ||
| 896 | { | ||
| 897 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
| 898 | |||
| 899 | switch (irq_ptr->state) { | ||
| 900 | case QDIO_IRQ_STATE_INACTIVE: | ||
| 901 | case QDIO_IRQ_STATE_CLEANUP: | ||
| 902 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | ||
| 903 | break; | ||
| 904 | case QDIO_IRQ_STATE_ESTABLISHED: | ||
| 905 | case QDIO_IRQ_STATE_ACTIVE: | ||
| 906 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | ||
| 907 | if (get_device(&cdev->dev)) { | ||
| 908 | /* Can't call shutdown from interrupt context. */ | ||
| 909 | PREPARE_WORK(&cdev->private->kick_work, | ||
| 910 | qdio_call_shutdown); | ||
| 911 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
| 912 | } | ||
| 913 | break; | ||
| 914 | default: | ||
| 915 | WARN_ON(1); | ||
| 916 | } | ||
| 917 | wake_up(&cdev->private->wait_q); | ||
| 918 | } | ||
| 919 | |||
| 920 | static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat, | 884 | static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat, |
| 921 | int dstat) | 885 | int dstat) |
| 922 | { | 886 | { |
| @@ -973,10 +937,8 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
| 973 | switch (PTR_ERR(irb)) { | 937 | switch (PTR_ERR(irb)) { |
| 974 | case -EIO: | 938 | case -EIO: |
| 975 | DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no); | 939 | DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no); |
| 976 | return; | 940 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
| 977 | case -ETIMEDOUT: | 941 | wake_up(&cdev->private->wait_q); |
| 978 | DBF_ERROR("%4x IO timeout", irq_ptr->schid.sch_no); | ||
| 979 | qdio_int_error(cdev); | ||
| 980 | return; | 942 | return; |
| 981 | default: | 943 | default: |
| 982 | WARN_ON(1); | 944 | WARN_ON(1); |
| @@ -1001,7 +963,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
| 1001 | case QDIO_IRQ_STATE_ACTIVE: | 963 | case QDIO_IRQ_STATE_ACTIVE: |
| 1002 | if (cstat & SCHN_STAT_PCI) { | 964 | if (cstat & SCHN_STAT_PCI) { |
| 1003 | qdio_int_handler_pci(irq_ptr); | 965 | qdio_int_handler_pci(irq_ptr); |
| 1004 | /* no state change so no need to wake up wait_q */ | ||
| 1005 | return; | 966 | return; |
| 1006 | } | 967 | } |
| 1007 | if ((cstat & ~SCHN_STAT_PCI) || dstat) { | 968 | if ((cstat & ~SCHN_STAT_PCI) || dstat) { |
