diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 13:48:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 13:48:46 -0400 |
commit | cc106eb35ed4abea675bce0d8fe40a46ff0b4a72 (patch) | |
tree | 7d18624a769680049f2933ce48a02c8e08e5937c | |
parent | 4e455c6782bd6bf6a0135c1e1c9f018ec191979e (diff) | |
parent | 3bfe68580a9d2a25465fc004986acd7991d700d1 (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
[S390] fill out file list in s390 MAINTAINERS entry
[S390] Add support for LZO-compressed kernels.
[S390] cmm: get rid of CMM_PROC config option
[S390] cmm: remove superfluous EXPORT_SYMBOLs plus cleanups
[S390] dasd: unit check handling during internal cio I/O
[S390] cio: unit check handling during internal I/O
[S390] ccwgroup: add locking around drvdata access
[S390] cio: remove stsch
[S390] spp: remove KVM_AWARE_CMF config option
[S390] kprobes: forbid probing of stnsm/stosm/epsw
[S390] spp: fix compilation for CONFIG_32BIT
[S390] atomic: implement atomic64_dec_if_positive
[S390] cmm: fix crash on module unload
-rw-r--r-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | arch/s390/Kconfig | 8 | ||||
-rw-r--r-- | arch/s390/boot/compressed/Makefile | 5 | ||||
-rw-r--r-- | arch/s390/boot/compressed/misc.c | 4 | ||||
-rw-r--r-- | arch/s390/include/asm/atomic.h | 19 | ||||
-rw-r--r-- | arch/s390/include/asm/ccwdev.h | 10 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 2 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/Kconfig | 11 | ||||
-rw-r--r-- | arch/s390/kvm/sie64a.S | 4 | ||||
-rw-r--r-- | arch/s390/mm/cmm.c | 109 | ||||
-rw-r--r-- | drivers/s390/block/dasd.c | 23 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 1 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 7 | ||||
-rw-r--r-- | drivers/s390/cio/ccwreq.c | 15 | ||||
-rw-r--r-- | drivers/s390/cio/ioasm.h | 15 |
19 files changed, 134 insertions, 112 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8b7eba2de603..33047a605438 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4836,6 +4836,9 @@ W: http://www.ibm.com/developerworks/linux/linux390/ | |||
4836 | S: Supported | 4836 | S: Supported |
4837 | F: arch/s390/ | 4837 | F: arch/s390/ |
4838 | F: drivers/s390/ | 4838 | F: drivers/s390/ |
4839 | F: fs/partitions/ibm.c | ||
4840 | F: Documentation/s390/ | ||
4841 | F: Documentation/DocBook/s390* | ||
4839 | 4842 | ||
4840 | S390 NETWORK DRIVERS | 4843 | S390 NETWORK DRIVERS |
4841 | M: Ursula Braun <ursula.braun@de.ibm.com> | 4844 | M: Ursula Braun <ursula.braun@de.ibm.com> |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 79d0ca086820..bee1c0f794cf 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -102,6 +102,7 @@ config S390 | |||
102 | select HAVE_KERNEL_GZIP | 102 | select HAVE_KERNEL_GZIP |
103 | select HAVE_KERNEL_BZIP2 | 103 | select HAVE_KERNEL_BZIP2 |
104 | select HAVE_KERNEL_LZMA | 104 | select HAVE_KERNEL_LZMA |
105 | select HAVE_KERNEL_LZO | ||
105 | select ARCH_INLINE_SPIN_TRYLOCK | 106 | select ARCH_INLINE_SPIN_TRYLOCK |
106 | select ARCH_INLINE_SPIN_TRYLOCK_BH | 107 | select ARCH_INLINE_SPIN_TRYLOCK_BH |
107 | select ARCH_INLINE_SPIN_LOCK | 108 | select ARCH_INLINE_SPIN_LOCK |
@@ -479,13 +480,6 @@ config CMM | |||
479 | Everybody who wants to run Linux under VM should select this | 480 | Everybody who wants to run Linux under VM should select this |
480 | option. | 481 | option. |
481 | 482 | ||
482 | config CMM_PROC | ||
483 | bool "/proc interface to cooperative memory management" | ||
484 | depends on CMM | ||
485 | help | ||
486 | Select this option to enable the /proc interface to the | ||
487 | cooperative memory management. | ||
488 | |||
489 | config CMM_IUCV | 483 | config CMM_IUCV |
490 | bool "IUCV special message interface to cooperative memory management" | 484 | bool "IUCV special message interface to cooperative memory management" |
491 | depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV) | 485 | depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV) |
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile index 6e4a67ad07e1..1c999f726a58 100644 --- a/arch/s390/boot/compressed/Makefile +++ b/arch/s390/boot/compressed/Makefile | |||
@@ -7,7 +7,7 @@ | |||
7 | BITS := $(if $(CONFIG_64BIT),64,31) | 7 | BITS := $(if $(CONFIG_64BIT),64,31) |
8 | 8 | ||
9 | targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ | 9 | targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ |
10 | vmlinux.bin.lzma misc.o piggy.o sizes.h head$(BITS).o | 10 | vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o sizes.h head$(BITS).o |
11 | 11 | ||
12 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 | 12 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 |
13 | KBUILD_CFLAGS += $(cflags-y) | 13 | KBUILD_CFLAGS += $(cflags-y) |
@@ -47,6 +47,7 @@ vmlinux.bin.all-y := $(obj)/vmlinux.bin | |||
47 | suffix-$(CONFIG_KERNEL_GZIP) := gz | 47 | suffix-$(CONFIG_KERNEL_GZIP) := gz |
48 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 | 48 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 |
49 | suffix-$(CONFIG_KERNEL_LZMA) := lzma | 49 | suffix-$(CONFIG_KERNEL_LZMA) := lzma |
50 | suffix-$(CONFIG_KERNEL_LZO) := lzo | ||
50 | 51 | ||
51 | $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) | 52 | $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) |
52 | $(call if_changed,gzip) | 53 | $(call if_changed,gzip) |
@@ -54,6 +55,8 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) | |||
54 | $(call if_changed,bzip2) | 55 | $(call if_changed,bzip2) |
55 | $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) | 56 | $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) |
56 | $(call if_changed,lzma) | 57 | $(call if_changed,lzma) |
58 | $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) | ||
59 | $(call if_changed,lzo) | ||
57 | 60 | ||
58 | LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T | 61 | LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T |
59 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) | 62 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) |
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index 14e0479d3888..0851eb1e919e 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c | |||
@@ -50,6 +50,10 @@ static unsigned long free_mem_end_ptr; | |||
50 | #include "../../../../lib/decompress_unlzma.c" | 50 | #include "../../../../lib/decompress_unlzma.c" |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | #ifdef CONFIG_KERNEL_LZO | ||
54 | #include "../../../../lib/decompress_unlzo.c" | ||
55 | #endif | ||
56 | |||
53 | extern _sclp_print_early(const char *); | 57 | extern _sclp_print_early(const char *); |
54 | 58 | ||
55 | int puts(const char *s) | 59 | int puts(const char *s) |
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index 451bfbb9db3d..76daea117181 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/compiler.h> | 16 | #include <linux/compiler.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <asm/system.h> | ||
18 | 19 | ||
19 | #define ATOMIC_INIT(i) { (i) } | 20 | #define ATOMIC_INIT(i) { (i) } |
20 | 21 | ||
@@ -274,6 +275,7 @@ static inline void atomic64_clear_mask(unsigned long long mask, atomic64_t *v) | |||
274 | static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) | 275 | static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) |
275 | { | 276 | { |
276 | long long c, old; | 277 | long long c, old; |
278 | |||
277 | c = atomic64_read(v); | 279 | c = atomic64_read(v); |
278 | for (;;) { | 280 | for (;;) { |
279 | if (unlikely(c == u)) | 281 | if (unlikely(c == u)) |
@@ -286,6 +288,23 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) | |||
286 | return c != u; | 288 | return c != u; |
287 | } | 289 | } |
288 | 290 | ||
291 | static inline long long atomic64_dec_if_positive(atomic64_t *v) | ||
292 | { | ||
293 | long long c, old, dec; | ||
294 | |||
295 | c = atomic64_read(v); | ||
296 | for (;;) { | ||
297 | dec = c - 1; | ||
298 | if (unlikely(dec < 0)) | ||
299 | break; | ||
300 | old = atomic64_cmpxchg((v), c, dec); | ||
301 | if (likely(old == c)) | ||
302 | break; | ||
303 | c = old; | ||
304 | } | ||
305 | return dec; | ||
306 | } | ||
307 | |||
289 | #define atomic64_add(_i, _v) atomic64_add_return(_i, _v) | 308 | #define atomic64_add(_i, _v) atomic64_add_return(_i, _v) |
290 | #define atomic64_add_negative(_i, _v) (atomic64_add_return(_i, _v) < 0) | 309 | #define atomic64_add_negative(_i, _v) (atomic64_add_return(_i, _v) < 0) |
291 | #define atomic64_inc(_v) atomic64_add_return(1, _v) | 310 | #define atomic64_inc(_v) atomic64_add_return(1, _v) |
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index f4bd346a52d3..1c0030f9b890 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h | |||
@@ -91,6 +91,14 @@ struct ccw_device { | |||
91 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); | 91 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); |
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* | ||
95 | * Possible CIO actions triggered by the unit check handler. | ||
96 | */ | ||
97 | enum uc_todo { | ||
98 | UC_TODO_RETRY, | ||
99 | UC_TODO_RETRY_ON_NEW_PATH, | ||
100 | UC_TODO_STOP | ||
101 | }; | ||
94 | 102 | ||
95 | /** | 103 | /** |
96 | * struct ccw driver - device driver for channel attached devices | 104 | * struct ccw driver - device driver for channel attached devices |
@@ -107,6 +115,7 @@ struct ccw_device { | |||
107 | * @freeze: callback for freezing during hibernation snapshotting | 115 | * @freeze: callback for freezing during hibernation snapshotting |
108 | * @thaw: undo work done in @freeze | 116 | * @thaw: undo work done in @freeze |
109 | * @restore: callback for restoring after hibernation | 117 | * @restore: callback for restoring after hibernation |
118 | * @uc_handler: callback for unit check handler | ||
110 | * @driver: embedded device driver structure | 119 | * @driver: embedded device driver structure |
111 | * @name: device driver name | 120 | * @name: device driver name |
112 | */ | 121 | */ |
@@ -124,6 +133,7 @@ struct ccw_driver { | |||
124 | int (*freeze)(struct ccw_device *); | 133 | int (*freeze)(struct ccw_device *); |
125 | int (*thaw) (struct ccw_device *); | 134 | int (*thaw) (struct ccw_device *); |
126 | int (*restore)(struct ccw_device *); | 135 | int (*restore)(struct ccw_device *); |
136 | enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *); | ||
127 | struct device_driver driver; | 137 | struct device_driver driver; |
128 | char *name; | 138 | char *name; |
129 | }; | 139 | }; |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index d9b490a2716e..5232278d79ad 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -132,8 +132,6 @@ int main(void) | |||
132 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); | 132 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); |
133 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); | 133 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); |
134 | DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); | 134 | DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); |
135 | DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook)); | ||
136 | DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp)); | ||
137 | DEFINE(__LC_IRB, offsetof(struct _lowcore, irb)); | 135 | DEFINE(__LC_IRB, offsetof(struct _lowcore, irb)); |
138 | DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area)); | 136 | DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area)); |
139 | DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area)); | 137 | DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area)); |
@@ -154,6 +152,8 @@ int main(void) | |||
154 | DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area)); | 152 | DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area)); |
155 | DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); | 153 | DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); |
156 | DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); | 154 | DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); |
155 | DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook)); | ||
156 | DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp)); | ||
157 | #endif /* CONFIG_32BIT */ | 157 | #endif /* CONFIG_32BIT */ |
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 178d92536d90..e7192e1cb678 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -65,7 +65,7 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | |||
65 | ltgr %r3,%r3 | 65 | ltgr %r3,%r3 |
66 | jz 0f | 66 | jz 0f |
67 | basr %r14,%r3 | 67 | basr %r14,%r3 |
68 | 0: | 68 | 0: |
69 | #endif | 69 | #endif |
70 | .endm | 70 | .endm |
71 | 71 | ||
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 3d34eef5a2c3..2a3d2bf6f083 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -63,6 +63,8 @@ int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction) | |||
63 | case 0x0b: /* bsm */ | 63 | case 0x0b: /* bsm */ |
64 | case 0x83: /* diag */ | 64 | case 0x83: /* diag */ |
65 | case 0x44: /* ex */ | 65 | case 0x44: /* ex */ |
66 | case 0xac: /* stnsm */ | ||
67 | case 0xad: /* stosm */ | ||
66 | return -EINVAL; | 68 | return -EINVAL; |
67 | } | 69 | } |
68 | switch (*(__u16 *) instruction) { | 70 | switch (*(__u16 *) instruction) { |
@@ -72,6 +74,7 @@ int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction) | |||
72 | case 0xb258: /* bsg */ | 74 | case 0xb258: /* bsg */ |
73 | case 0xb218: /* pc */ | 75 | case 0xb218: /* pc */ |
74 | case 0xb228: /* pt */ | 76 | case 0xb228: /* pt */ |
77 | case 0xb98d: /* epsw */ | ||
75 | return -EINVAL; | 78 | return -EINVAL; |
76 | } | 79 | } |
77 | return 0; | 80 | return 0; |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 7d893248d265..c8e8e1354e1d 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -401,7 +401,6 @@ setup_lowcore(void) | |||
401 | lc->io_new_psw.mask = psw_kernel_bits; | 401 | lc->io_new_psw.mask = psw_kernel_bits; |
402 | lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; | 402 | lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; |
403 | lc->clock_comparator = -1ULL; | 403 | lc->clock_comparator = -1ULL; |
404 | lc->cmf_hpp = -1ULL; | ||
405 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; | 404 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; |
406 | lc->async_stack = (unsigned long) | 405 | lc->async_stack = (unsigned long) |
407 | __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; | 406 | __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; |
@@ -418,6 +417,7 @@ setup_lowcore(void) | |||
418 | __ctl_set_bit(14, 29); | 417 | __ctl_set_bit(14, 29); |
419 | } | 418 | } |
420 | #else | 419 | #else |
420 | lc->cmf_hpp = -1ULL; | ||
421 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; | 421 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; |
422 | #endif | 422 | #endif |
423 | lc->sync_enter_timer = S390_lowcore.sync_enter_timer; | 423 | lc->sync_enter_timer = S390_lowcore.sync_enter_timer; |
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 2f4b687cc7fa..a7251580891c 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig | |||
@@ -33,17 +33,6 @@ config KVM | |||
33 | 33 | ||
34 | If unsure, say N. | 34 | If unsure, say N. |
35 | 35 | ||
36 | config KVM_AWARE_CMF | ||
37 | depends on KVM | ||
38 | bool "KVM aware sampling" | ||
39 | ---help--- | ||
40 | This option enhances the sampling data from the CPU Measurement | ||
41 | Facility with additional information, that allows to distinguish | ||
42 | guest(s) and host when using the kernel based virtual machine | ||
43 | functionality. | ||
44 | |||
45 | If unsure, say N. | ||
46 | |||
47 | # OK, it's a little counter-intuitive to do this, but it puts it neatly under | 36 | # OK, it's a little counter-intuitive to do this, but it puts it neatly under |
48 | # the virtualization menu. | 37 | # the virtualization menu. |
49 | source drivers/vhost/Kconfig | 38 | source drivers/vhost/Kconfig |
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S index 31646bd0e469..7e9d30d567b0 100644 --- a/arch/s390/kvm/sie64a.S +++ b/arch/s390/kvm/sie64a.S | |||
@@ -32,12 +32,10 @@ SPI_PSW = STACK_FRAME_OVERHEAD + __PT_PSW | |||
32 | 32 | ||
33 | 33 | ||
34 | .macro SPP newpp | 34 | .macro SPP newpp |
35 | #ifdef CONFIG_KVM_AWARE_CMF | ||
36 | tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP | 35 | tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP |
37 | jz 0f | 36 | jz 0f |
38 | .insn s,0xb2800000,\newpp | 37 | .insn s,0xb2800000,\newpp |
39 | 0: | 38 | 0: |
40 | #endif | ||
41 | .endm | 39 | .endm |
42 | 40 | ||
43 | sie_irq_handler: | 41 | sie_irq_handler: |
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index f87b34731e1d..eb6a2ef5f82e 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
@@ -1,11 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/mm/cmm.c | 2 | * Collaborative memory management interface. |
3 | * | 3 | * |
4 | * S390 version | 4 | * Copyright IBM Corp 2003,2010 |
5 | * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | ||
7 | * | 6 | * |
8 | * Collaborative memory management interface. | ||
9 | */ | 7 | */ |
10 | 8 | ||
11 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
@@ -20,9 +18,9 @@ | |||
20 | #include <linux/kthread.h> | 18 | #include <linux/kthread.h> |
21 | #include <linux/oom.h> | 19 | #include <linux/oom.h> |
22 | #include <linux/suspend.h> | 20 | #include <linux/suspend.h> |
21 | #include <linux/uaccess.h> | ||
23 | 22 | ||
24 | #include <asm/pgalloc.h> | 23 | #include <asm/pgalloc.h> |
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/diag.h> | 24 | #include <asm/diag.h> |
27 | 25 | ||
28 | static char *sender = "VMRMSVM"; | 26 | static char *sender = "VMRMSVM"; |
@@ -53,14 +51,14 @@ static struct cmm_page_array *cmm_timed_page_list; | |||
53 | static DEFINE_SPINLOCK(cmm_lock); | 51 | static DEFINE_SPINLOCK(cmm_lock); |
54 | 52 | ||
55 | static struct task_struct *cmm_thread_ptr; | 53 | static struct task_struct *cmm_thread_ptr; |
56 | static wait_queue_head_t cmm_thread_wait; | 54 | static DECLARE_WAIT_QUEUE_HEAD(cmm_thread_wait); |
57 | static struct timer_list cmm_timer; | 55 | static DEFINE_TIMER(cmm_timer, NULL, 0, 0); |
58 | 56 | ||
59 | static void cmm_timer_fn(unsigned long); | 57 | static void cmm_timer_fn(unsigned long); |
60 | static void cmm_set_timer(void); | 58 | static void cmm_set_timer(void); |
61 | 59 | ||
62 | static long | 60 | static long cmm_alloc_pages(long nr, long *counter, |
63 | cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list) | 61 | struct cmm_page_array **list) |
64 | { | 62 | { |
65 | struct cmm_page_array *pa, *npa; | 63 | struct cmm_page_array *pa, *npa; |
66 | unsigned long addr; | 64 | unsigned long addr; |
@@ -99,8 +97,7 @@ cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list) | |||
99 | return nr; | 97 | return nr; |
100 | } | 98 | } |
101 | 99 | ||
102 | static long | 100 | static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) |
103 | cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) | ||
104 | { | 101 | { |
105 | struct cmm_page_array *pa; | 102 | struct cmm_page_array *pa; |
106 | unsigned long addr; | 103 | unsigned long addr; |
@@ -140,11 +137,10 @@ static int cmm_oom_notify(struct notifier_block *self, | |||
140 | } | 137 | } |
141 | 138 | ||
142 | static struct notifier_block cmm_oom_nb = { | 139 | static struct notifier_block cmm_oom_nb = { |
143 | .notifier_call = cmm_oom_notify | 140 | .notifier_call = cmm_oom_notify, |
144 | }; | 141 | }; |
145 | 142 | ||
146 | static int | 143 | static int cmm_thread(void *dummy) |
147 | cmm_thread(void *dummy) | ||
148 | { | 144 | { |
149 | int rc; | 145 | int rc; |
150 | 146 | ||
@@ -170,7 +166,7 @@ cmm_thread(void *dummy) | |||
170 | cmm_timed_pages_target = cmm_timed_pages; | 166 | cmm_timed_pages_target = cmm_timed_pages; |
171 | } else if (cmm_timed_pages_target < cmm_timed_pages) { | 167 | } else if (cmm_timed_pages_target < cmm_timed_pages) { |
172 | cmm_free_pages(1, &cmm_timed_pages, | 168 | cmm_free_pages(1, &cmm_timed_pages, |
173 | &cmm_timed_page_list); | 169 | &cmm_timed_page_list); |
174 | } | 170 | } |
175 | if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) | 171 | if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) |
176 | cmm_set_timer(); | 172 | cmm_set_timer(); |
@@ -178,14 +174,12 @@ cmm_thread(void *dummy) | |||
178 | return 0; | 174 | return 0; |
179 | } | 175 | } |
180 | 176 | ||
181 | static void | 177 | static void cmm_kick_thread(void) |
182 | cmm_kick_thread(void) | ||
183 | { | 178 | { |
184 | wake_up(&cmm_thread_wait); | 179 | wake_up(&cmm_thread_wait); |
185 | } | 180 | } |
186 | 181 | ||
187 | static void | 182 | static void cmm_set_timer(void) |
188 | cmm_set_timer(void) | ||
189 | { | 183 | { |
190 | if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { | 184 | if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { |
191 | if (timer_pending(&cmm_timer)) | 185 | if (timer_pending(&cmm_timer)) |
@@ -202,8 +196,7 @@ cmm_set_timer(void) | |||
202 | add_timer(&cmm_timer); | 196 | add_timer(&cmm_timer); |
203 | } | 197 | } |
204 | 198 | ||
205 | static void | 199 | static void cmm_timer_fn(unsigned long ignored) |
206 | cmm_timer_fn(unsigned long ignored) | ||
207 | { | 200 | { |
208 | long nr; | 201 | long nr; |
209 | 202 | ||
@@ -216,57 +209,49 @@ cmm_timer_fn(unsigned long ignored) | |||
216 | cmm_set_timer(); | 209 | cmm_set_timer(); |
217 | } | 210 | } |
218 | 211 | ||
219 | void | 212 | static void cmm_set_pages(long nr) |
220 | cmm_set_pages(long nr) | ||
221 | { | 213 | { |
222 | cmm_pages_target = nr; | 214 | cmm_pages_target = nr; |
223 | cmm_kick_thread(); | 215 | cmm_kick_thread(); |
224 | } | 216 | } |
225 | 217 | ||
226 | long | 218 | static long cmm_get_pages(void) |
227 | cmm_get_pages(void) | ||
228 | { | 219 | { |
229 | return cmm_pages; | 220 | return cmm_pages; |
230 | } | 221 | } |
231 | 222 | ||
232 | void | 223 | static void cmm_add_timed_pages(long nr) |
233 | cmm_add_timed_pages(long nr) | ||
234 | { | 224 | { |
235 | cmm_timed_pages_target += nr; | 225 | cmm_timed_pages_target += nr; |
236 | cmm_kick_thread(); | 226 | cmm_kick_thread(); |
237 | } | 227 | } |
238 | 228 | ||
239 | long | 229 | static long cmm_get_timed_pages(void) |
240 | cmm_get_timed_pages(void) | ||
241 | { | 230 | { |
242 | return cmm_timed_pages; | 231 | return cmm_timed_pages; |
243 | } | 232 | } |
244 | 233 | ||
245 | void | 234 | static void cmm_set_timeout(long nr, long seconds) |
246 | cmm_set_timeout(long nr, long seconds) | ||
247 | { | 235 | { |
248 | cmm_timeout_pages = nr; | 236 | cmm_timeout_pages = nr; |
249 | cmm_timeout_seconds = seconds; | 237 | cmm_timeout_seconds = seconds; |
250 | cmm_set_timer(); | 238 | cmm_set_timer(); |
251 | } | 239 | } |
252 | 240 | ||
253 | static int | 241 | static int cmm_skip_blanks(char *cp, char **endp) |
254 | cmm_skip_blanks(char *cp, char **endp) | ||
255 | { | 242 | { |
256 | char *str; | 243 | char *str; |
257 | 244 | ||
258 | for (str = cp; *str == ' ' || *str == '\t'; str++); | 245 | for (str = cp; *str == ' ' || *str == '\t'; str++) |
246 | ; | ||
259 | *endp = str; | 247 | *endp = str; |
260 | return str != cp; | 248 | return str != cp; |
261 | } | 249 | } |
262 | 250 | ||
263 | #ifdef CONFIG_CMM_PROC | ||
264 | |||
265 | static struct ctl_table cmm_table[]; | 251 | static struct ctl_table cmm_table[]; |
266 | 252 | ||
267 | static int | 253 | static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer, |
268 | cmm_pages_handler(ctl_table *ctl, int write, | 254 | size_t *lenp, loff_t *ppos) |
269 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
270 | { | 255 | { |
271 | char buf[16], *p; | 256 | char buf[16], *p; |
272 | long nr; | 257 | long nr; |
@@ -305,9 +290,8 @@ cmm_pages_handler(ctl_table *ctl, int write, | |||
305 | return 0; | 290 | return 0; |
306 | } | 291 | } |
307 | 292 | ||
308 | static int | 293 | static int cmm_timeout_handler(ctl_table *ctl, int write, void __user *buffer, |
309 | cmm_timeout_handler(ctl_table *ctl, int write, | 294 | size_t *lenp, loff_t *ppos) |
310 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
311 | { | 295 | { |
312 | char buf[64], *p; | 296 | char buf[64], *p; |
313 | long nr, seconds; | 297 | long nr, seconds; |
@@ -370,12 +354,10 @@ static struct ctl_table cmm_dir_table[] = { | |||
370 | }, | 354 | }, |
371 | { } | 355 | { } |
372 | }; | 356 | }; |
373 | #endif | ||
374 | 357 | ||
375 | #ifdef CONFIG_CMM_IUCV | 358 | #ifdef CONFIG_CMM_IUCV |
376 | #define SMSG_PREFIX "CMM" | 359 | #define SMSG_PREFIX "CMM" |
377 | static void | 360 | static void cmm_smsg_target(const char *from, char *msg) |
378 | cmm_smsg_target(const char *from, char *msg) | ||
379 | { | 361 | { |
380 | long nr, seconds; | 362 | long nr, seconds; |
381 | 363 | ||
@@ -445,16 +427,13 @@ static struct notifier_block cmm_power_notifier = { | |||
445 | .notifier_call = cmm_power_event, | 427 | .notifier_call = cmm_power_event, |
446 | }; | 428 | }; |
447 | 429 | ||
448 | static int | 430 | static int cmm_init(void) |
449 | cmm_init (void) | ||
450 | { | 431 | { |
451 | int rc = -ENOMEM; | 432 | int rc = -ENOMEM; |
452 | 433 | ||
453 | #ifdef CONFIG_CMM_PROC | ||
454 | cmm_sysctl_header = register_sysctl_table(cmm_dir_table); | 434 | cmm_sysctl_header = register_sysctl_table(cmm_dir_table); |
455 | if (!cmm_sysctl_header) | 435 | if (!cmm_sysctl_header) |
456 | goto out_sysctl; | 436 | goto out_sysctl; |
457 | #endif | ||
458 | #ifdef CONFIG_CMM_IUCV | 437 | #ifdef CONFIG_CMM_IUCV |
459 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); | 438 | rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); |
460 | if (rc < 0) | 439 | if (rc < 0) |
@@ -466,8 +445,6 @@ cmm_init (void) | |||
466 | rc = register_pm_notifier(&cmm_power_notifier); | 445 | rc = register_pm_notifier(&cmm_power_notifier); |
467 | if (rc) | 446 | if (rc) |
468 | goto out_pm; | 447 | goto out_pm; |
469 | init_waitqueue_head(&cmm_thread_wait); | ||
470 | init_timer(&cmm_timer); | ||
471 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); | 448 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); |
472 | rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0; | 449 | rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0; |
473 | if (rc) | 450 | if (rc) |
@@ -483,36 +460,26 @@ out_oom_notify: | |||
483 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); | 460 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); |
484 | out_smsg: | 461 | out_smsg: |
485 | #endif | 462 | #endif |
486 | #ifdef CONFIG_CMM_PROC | ||
487 | unregister_sysctl_table(cmm_sysctl_header); | 463 | unregister_sysctl_table(cmm_sysctl_header); |
488 | out_sysctl: | 464 | out_sysctl: |
489 | #endif | 465 | del_timer_sync(&cmm_timer); |
490 | return rc; | 466 | return rc; |
491 | } | 467 | } |
468 | module_init(cmm_init); | ||
492 | 469 | ||
493 | static void | 470 | static void cmm_exit(void) |
494 | cmm_exit(void) | ||
495 | { | 471 | { |
496 | kthread_stop(cmm_thread_ptr); | ||
497 | unregister_pm_notifier(&cmm_power_notifier); | ||
498 | unregister_oom_notifier(&cmm_oom_nb); | ||
499 | cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); | ||
500 | cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); | ||
501 | #ifdef CONFIG_CMM_PROC | ||
502 | unregister_sysctl_table(cmm_sysctl_header); | 472 | unregister_sysctl_table(cmm_sysctl_header); |
503 | #endif | ||
504 | #ifdef CONFIG_CMM_IUCV | 473 | #ifdef CONFIG_CMM_IUCV |
505 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); | 474 | smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); |
506 | #endif | 475 | #endif |
476 | unregister_pm_notifier(&cmm_power_notifier); | ||
477 | unregister_oom_notifier(&cmm_oom_nb); | ||
478 | kthread_stop(cmm_thread_ptr); | ||
479 | del_timer_sync(&cmm_timer); | ||
480 | cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); | ||
481 | cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); | ||
507 | } | 482 | } |
508 | |||
509 | module_init(cmm_init); | ||
510 | module_exit(cmm_exit); | 483 | module_exit(cmm_exit); |
511 | 484 | ||
512 | EXPORT_SYMBOL(cmm_set_pages); | ||
513 | EXPORT_SYMBOL(cmm_get_pages); | ||
514 | EXPORT_SYMBOL(cmm_add_timed_pages); | ||
515 | EXPORT_SYMBOL(cmm_get_timed_pages); | ||
516 | EXPORT_SYMBOL(cmm_set_timeout); | ||
517 | |||
518 | MODULE_LICENSE("GPL"); | 485 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0e86247d791e..33975e922d65 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1186,6 +1186,29 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1186 | dasd_schedule_device_bh(device); | 1186 | dasd_schedule_device_bh(device); |
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb) | ||
1190 | { | ||
1191 | struct dasd_device *device; | ||
1192 | |||
1193 | device = dasd_device_from_cdev_locked(cdev); | ||
1194 | |||
1195 | if (IS_ERR(device)) | ||
1196 | goto out; | ||
1197 | if (test_bit(DASD_FLAG_OFFLINE, &device->flags) || | ||
1198 | device->state != device->target || | ||
1199 | !device->discipline->handle_unsolicited_interrupt){ | ||
1200 | dasd_put_device(device); | ||
1201 | goto out; | ||
1202 | } | ||
1203 | |||
1204 | dasd_device_clear_timer(device); | ||
1205 | device->discipline->handle_unsolicited_interrupt(device, irb); | ||
1206 | dasd_put_device(device); | ||
1207 | out: | ||
1208 | return UC_TODO_RETRY; | ||
1209 | } | ||
1210 | EXPORT_SYMBOL_GPL(dasd_generic_uc_handler); | ||
1211 | |||
1189 | /* | 1212 | /* |
1190 | * If we have an error on a dasd_block layer request then we cancel | 1213 | * If we have an error on a dasd_block layer request then we cancel |
1191 | * and return all further requests from the same dasd_block as well. | 1214 | * and return all further requests from the same dasd_block as well. |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 5b1cd8d6e971..ab84da5592e8 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -3436,6 +3436,7 @@ static struct ccw_driver dasd_eckd_driver = { | |||
3436 | .freeze = dasd_generic_pm_freeze, | 3436 | .freeze = dasd_generic_pm_freeze, |
3437 | .thaw = dasd_generic_restore_device, | 3437 | .thaw = dasd_generic_restore_device, |
3438 | .restore = dasd_generic_restore_device, | 3438 | .restore = dasd_generic_restore_device, |
3439 | .uc_handler = dasd_generic_uc_handler, | ||
3439 | }; | 3440 | }; |
3440 | 3441 | ||
3441 | /* | 3442 | /* |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 32fac186ba3f..49b431d135e0 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -617,6 +617,7 @@ int dasd_generic_notify(struct ccw_device *, int); | |||
617 | void dasd_generic_handle_state_change(struct dasd_device *); | 617 | void dasd_generic_handle_state_change(struct dasd_device *); |
618 | int dasd_generic_pm_freeze(struct ccw_device *); | 618 | int dasd_generic_pm_freeze(struct ccw_device *); |
619 | int dasd_generic_restore_device(struct ccw_device *); | 619 | int dasd_generic_restore_device(struct ccw_device *); |
620 | enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *); | ||
620 | 621 | ||
621 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); | 622 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); |
622 | char *dasd_get_sense(struct irb *); | 623 | char *dasd_get_sense(struct irb *); |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5f97ea2ee6b1..97b25d68e3e7 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -123,8 +123,10 @@ ccwgroup_release (struct device *dev) | |||
123 | 123 | ||
124 | for (i = 0; i < gdev->count; i++) { | 124 | for (i = 0; i < gdev->count; i++) { |
125 | if (gdev->cdev[i]) { | 125 | if (gdev->cdev[i]) { |
126 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
126 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) | 127 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) |
127 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); | 128 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); |
129 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
128 | put_device(&gdev->cdev[i]->dev); | 130 | put_device(&gdev->cdev[i]->dev); |
129 | } | 131 | } |
130 | } | 132 | } |
@@ -262,11 +264,14 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
262 | goto error; | 264 | goto error; |
263 | } | 265 | } |
264 | /* Don't allow a device to belong to more than one group. */ | 266 | /* Don't allow a device to belong to more than one group. */ |
267 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
265 | if (dev_get_drvdata(&gdev->cdev[i]->dev)) { | 268 | if (dev_get_drvdata(&gdev->cdev[i]->dev)) { |
269 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
266 | rc = -EINVAL; | 270 | rc = -EINVAL; |
267 | goto error; | 271 | goto error; |
268 | } | 272 | } |
269 | dev_set_drvdata(&gdev->cdev[i]->dev, gdev); | 273 | dev_set_drvdata(&gdev->cdev[i]->dev, gdev); |
274 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
270 | } | 275 | } |
271 | /* Check for sufficient number of bus ids. */ | 276 | /* Check for sufficient number of bus ids. */ |
272 | if (i < num_devices && !curr_buf) { | 277 | if (i < num_devices && !curr_buf) { |
@@ -303,8 +308,10 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
303 | error: | 308 | error: |
304 | for (i = 0; i < num_devices; i++) | 309 | for (i = 0; i < num_devices; i++) |
305 | if (gdev->cdev[i]) { | 310 | if (gdev->cdev[i]) { |
311 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
306 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) | 312 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) |
307 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); | 313 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); |
314 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
308 | put_device(&gdev->cdev[i]->dev); | 315 | put_device(&gdev->cdev[i]->dev); |
309 | gdev->cdev[i] = NULL; | 316 | gdev->cdev[i] = NULL; |
310 | } | 317 | } |
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c index 37df42af05ec..7f206ed44fdf 100644 --- a/drivers/s390/cio/ccwreq.c +++ b/drivers/s390/cio/ccwreq.c | |||
@@ -159,6 +159,7 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
159 | { | 159 | { |
160 | struct irb *irb = &cdev->private->irb; | 160 | struct irb *irb = &cdev->private->irb; |
161 | struct cmd_scsw *scsw = &irb->scsw.cmd; | 161 | struct cmd_scsw *scsw = &irb->scsw.cmd; |
162 | enum uc_todo todo; | ||
162 | 163 | ||
163 | /* Perform BASIC SENSE if needed. */ | 164 | /* Perform BASIC SENSE if needed. */ |
164 | if (ccw_device_accumulate_and_sense(cdev, lcirb)) | 165 | if (ccw_device_accumulate_and_sense(cdev, lcirb)) |
@@ -178,6 +179,20 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
178 | /* Check for command reject. */ | 179 | /* Check for command reject. */ |
179 | if (irb->ecw[0] & SNS0_CMD_REJECT) | 180 | if (irb->ecw[0] & SNS0_CMD_REJECT) |
180 | return IO_REJECTED; | 181 | return IO_REJECTED; |
182 | /* Ask the driver what to do */ | ||
183 | if (cdev->drv && cdev->drv->uc_handler) { | ||
184 | todo = cdev->drv->uc_handler(cdev, lcirb); | ||
185 | switch (todo) { | ||
186 | case UC_TODO_RETRY: | ||
187 | return IO_STATUS_ERROR; | ||
188 | case UC_TODO_RETRY_ON_NEW_PATH: | ||
189 | return IO_PATH_ERROR; | ||
190 | case UC_TODO_STOP: | ||
191 | return IO_REJECTED; | ||
192 | default: | ||
193 | return IO_STATUS_ERROR; | ||
194 | } | ||
195 | } | ||
181 | /* Assume that unexpected SENSE data implies an error. */ | 196 | /* Assume that unexpected SENSE data implies an error. */ |
182 | return IO_STATUS_ERROR; | 197 | return IO_STATUS_ERROR; |
183 | } | 198 | } |
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 759262792633..fac06155773f 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h | |||
@@ -23,21 +23,6 @@ struct tpi_info { | |||
23 | * Some S390 specific IO instructions as inline | 23 | * Some S390 specific IO instructions as inline |
24 | */ | 24 | */ |
25 | 25 | ||
26 | static inline int stsch(struct subchannel_id schid, struct schib *addr) | ||
27 | { | ||
28 | register struct subchannel_id reg1 asm ("1") = schid; | ||
29 | int ccode; | ||
30 | |||
31 | asm volatile( | ||
32 | " stsch 0(%3)\n" | ||
33 | " ipm %0\n" | ||
34 | " srl %0,28" | ||
35 | : "=d" (ccode), "=m" (*addr) | ||
36 | : "d" (reg1), "a" (addr) | ||
37 | : "cc"); | ||
38 | return ccode; | ||
39 | } | ||
40 | |||
41 | static inline int stsch_err(struct subchannel_id schid, struct schib *addr) | 26 | static inline int stsch_err(struct subchannel_id schid, struct schib *addr) |
42 | { | 27 | { |
43 | register struct subchannel_id reg1 asm ("1") = schid; | 28 | register struct subchannel_id reg1 asm ("1") = schid; |