diff options
54 files changed, 592 insertions, 1127 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 9015060919a0..b42f2866594b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -217,7 +217,7 @@ config COMPAT | |||
217 | def_bool y | 217 | def_bool y |
218 | prompt "Kernel support for 31 bit emulation" | 218 | prompt "Kernel support for 31 bit emulation" |
219 | depends on 64BIT | 219 | depends on 64BIT |
220 | select COMPAT_BINFMT_ELF | 220 | select COMPAT_BINFMT_ELF if BINFMT_ELF |
221 | select ARCH_WANT_OLD_COMPAT_IPC | 221 | select ARCH_WANT_OLD_COMPAT_IPC |
222 | help | 222 | help |
223 | Select this option if you want to enable your system kernel to | 223 | Select this option if you want to enable your system kernel to |
@@ -234,6 +234,25 @@ config KEYS_COMPAT | |||
234 | config AUDIT_ARCH | 234 | config AUDIT_ARCH |
235 | def_bool y | 235 | def_bool y |
236 | 236 | ||
237 | config HAVE_MARCH_Z900_FEATURES | ||
238 | def_bool n | ||
239 | |||
240 | config HAVE_MARCH_Z990_FEATURES | ||
241 | def_bool n | ||
242 | select HAVE_MARCH_Z900_FEATURES | ||
243 | |||
244 | config HAVE_MARCH_Z9_109_FEATURES | ||
245 | def_bool n | ||
246 | select HAVE_MARCH_Z990_FEATURES | ||
247 | |||
248 | config HAVE_MARCH_Z10_FEATURES | ||
249 | def_bool n | ||
250 | select HAVE_MARCH_Z9_109_FEATURES | ||
251 | |||
252 | config HAVE_MARCH_Z196_FEATURES | ||
253 | def_bool n | ||
254 | select HAVE_MARCH_Z10_FEATURES | ||
255 | |||
237 | comment "Code generation options" | 256 | comment "Code generation options" |
238 | 257 | ||
239 | choice | 258 | choice |
@@ -249,6 +268,7 @@ config MARCH_G5 | |||
249 | 268 | ||
250 | config MARCH_Z900 | 269 | config MARCH_Z900 |
251 | bool "IBM zSeries model z800 and z900" | 270 | bool "IBM zSeries model z800 and z900" |
271 | select HAVE_MARCH_Z900_FEATURES if 64BIT | ||
252 | help | 272 | help |
253 | Select this to enable optimizations for model z800/z900 (2064 and | 273 | Select this to enable optimizations for model z800/z900 (2064 and |
254 | 2066 series). This will enable some optimizations that are not | 274 | 2066 series). This will enable some optimizations that are not |
@@ -256,6 +276,7 @@ config MARCH_Z900 | |||
256 | 276 | ||
257 | config MARCH_Z990 | 277 | config MARCH_Z990 |
258 | bool "IBM zSeries model z890 and z990" | 278 | bool "IBM zSeries model z890 and z990" |
279 | select HAVE_MARCH_Z990_FEATURES if 64BIT | ||
259 | help | 280 | help |
260 | Select this to enable optimizations for model z890/z990 (2084 and | 281 | Select this to enable optimizations for model z890/z990 (2084 and |
261 | 2086 series). The kernel will be slightly faster but will not work | 282 | 2086 series). The kernel will be slightly faster but will not work |
@@ -263,6 +284,7 @@ config MARCH_Z990 | |||
263 | 284 | ||
264 | config MARCH_Z9_109 | 285 | config MARCH_Z9_109 |
265 | bool "IBM System z9" | 286 | bool "IBM System z9" |
287 | select HAVE_MARCH_Z9_109_FEATURES if 64BIT | ||
266 | help | 288 | help |
267 | Select this to enable optimizations for IBM System z9 (2094 and | 289 | Select this to enable optimizations for IBM System z9 (2094 and |
268 | 2096 series). The kernel will be slightly faster but will not work | 290 | 2096 series). The kernel will be slightly faster but will not work |
@@ -270,6 +292,7 @@ config MARCH_Z9_109 | |||
270 | 292 | ||
271 | config MARCH_Z10 | 293 | config MARCH_Z10 |
272 | bool "IBM System z10" | 294 | bool "IBM System z10" |
295 | select HAVE_MARCH_Z10_FEATURES if 64BIT | ||
273 | help | 296 | help |
274 | Select this to enable optimizations for IBM System z10 (2097 and | 297 | Select this to enable optimizations for IBM System z10 (2097 and |
275 | 2098 series). The kernel will be slightly faster but will not work | 298 | 2098 series). The kernel will be slightly faster but will not work |
@@ -277,6 +300,7 @@ config MARCH_Z10 | |||
277 | 300 | ||
278 | config MARCH_Z196 | 301 | config MARCH_Z196 |
279 | bool "IBM zEnterprise 114 and 196" | 302 | bool "IBM zEnterprise 114 and 196" |
303 | select HAVE_MARCH_Z196_FEATURES if 64BIT | ||
280 | help | 304 | help |
281 | Select this to enable optimizations for IBM zEnterprise 114 and 196 | 305 | Select this to enable optimizations for IBM zEnterprise 114 and 196 |
282 | (2818 and 2817 series). The kernel will be slightly faster but will | 306 | (2818 and 2817 series). The kernel will be slightly faster but will |
@@ -406,33 +430,6 @@ config CHSC_SCH | |||
406 | 430 | ||
407 | comment "Misc" | 431 | comment "Misc" |
408 | 432 | ||
409 | config IPL | ||
410 | def_bool y | ||
411 | prompt "Builtin IPL record support" | ||
412 | help | ||
413 | If you want to use the produced kernel to IPL directly from a | ||
414 | device, you have to merge a bootsector specific to the device | ||
415 | into the first bytes of the kernel. You will have to select the | ||
416 | IPL device. | ||
417 | |||
418 | choice | ||
419 | prompt "IPL method generated into head.S" | ||
420 | depends on IPL | ||
421 | default IPL_VM | ||
422 | help | ||
423 | Select "tape" if you want to IPL the image from a Tape. | ||
424 | |||
425 | Select "vm_reader" if you are running under VM/ESA and want | ||
426 | to IPL the image from the emulated card reader. | ||
427 | |||
428 | config IPL_TAPE | ||
429 | bool "tape" | ||
430 | |||
431 | config IPL_VM | ||
432 | bool "vm_reader" | ||
433 | |||
434 | endchoice | ||
435 | |||
436 | source "fs/Kconfig.binfmt" | 433 | source "fs/Kconfig.binfmt" |
437 | 434 | ||
438 | config FORCE_MAX_ZONEORDER | 435 | config FORCE_MAX_ZONEORDER |
@@ -569,7 +566,7 @@ config KEXEC | |||
569 | 566 | ||
570 | config CRASH_DUMP | 567 | config CRASH_DUMP |
571 | bool "kernel crash dumps" | 568 | bool "kernel crash dumps" |
572 | depends on 64BIT | 569 | depends on 64BIT && SMP |
573 | select KEXEC | 570 | select KEXEC |
574 | help | 571 | help |
575 | Generate crash dump after being started by kexec. | 572 | Generate crash dump after being started by kexec. |
diff --git a/arch/s390/boot/.gitignore b/arch/s390/boot/.gitignore new file mode 100644 index 000000000000..017d5912ad2d --- /dev/null +++ b/arch/s390/boot/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | image | ||
2 | bzImage | ||
diff --git a/arch/s390/boot/compressed/.gitignore b/arch/s390/boot/compressed/.gitignore new file mode 100644 index 000000000000..ae06b9b4c02f --- /dev/null +++ b/arch/s390/boot/compressed/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | sizes.h | ||
2 | vmlinux | ||
3 | vmlinux.lds | ||
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 1957a9dd256d..37d2bf267964 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
@@ -155,7 +155,6 @@ CONFIG_CRYPTO_BLOWFISH=m | |||
155 | CONFIG_CRYPTO_CAMELLIA=m | 155 | CONFIG_CRYPTO_CAMELLIA=m |
156 | CONFIG_CRYPTO_CAST5=m | 156 | CONFIG_CRYPTO_CAST5=m |
157 | CONFIG_CRYPTO_CAST6=m | 157 | CONFIG_CRYPTO_CAST6=m |
158 | CONFIG_CRYPTO_DES=m | ||
159 | CONFIG_CRYPTO_FCRYPT=m | 158 | CONFIG_CRYPTO_FCRYPT=m |
160 | CONFIG_CRYPTO_KHAZAD=m | 159 | CONFIG_CRYPTO_KHAZAD=m |
161 | CONFIG_CRYPTO_SALSA20=m | 160 | CONFIG_CRYPTO_SALSA20=m |
diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h index 451273ad4d34..10a508802940 100644 --- a/arch/s390/include/asm/barrier.h +++ b/arch/s390/include/asm/barrier.h | |||
@@ -11,25 +11,28 @@ | |||
11 | * Force strict CPU ordering. | 11 | * Force strict CPU ordering. |
12 | * And yes, this is required on UP too when we're talking | 12 | * And yes, this is required on UP too when we're talking |
13 | * to devices. | 13 | * to devices. |
14 | * | ||
15 | * This is very similar to the ppc eieio/sync instruction in that is | ||
16 | * does a checkpoint syncronisation & makes sure that | ||
17 | * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ). | ||
18 | */ | 14 | */ |
19 | 15 | ||
20 | #define eieio() asm volatile("bcr 15,0" : : : "memory") | 16 | static inline void mb(void) |
21 | #define SYNC_OTHER_CORES(x) eieio() | 17 | { |
22 | #define mb() eieio() | 18 | #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES |
23 | #define rmb() eieio() | 19 | /* Fast-BCR without checkpoint synchronization */ |
24 | #define wmb() eieio() | 20 | asm volatile("bcr 14,0" : : : "memory"); |
25 | #define read_barrier_depends() do { } while(0) | 21 | #else |
26 | #define smp_mb() mb() | 22 | asm volatile("bcr 15,0" : : : "memory"); |
27 | #define smp_rmb() rmb() | 23 | #endif |
28 | #define smp_wmb() wmb() | 24 | } |
29 | #define smp_read_barrier_depends() read_barrier_depends() | 25 | |
30 | #define smp_mb__before_clear_bit() smp_mb() | 26 | #define rmb() mb() |
31 | #define smp_mb__after_clear_bit() smp_mb() | 27 | #define wmb() mb() |
28 | #define read_barrier_depends() do { } while(0) | ||
29 | #define smp_mb() mb() | ||
30 | #define smp_rmb() rmb() | ||
31 | #define smp_wmb() wmb() | ||
32 | #define smp_read_barrier_depends() read_barrier_depends() | ||
33 | #define smp_mb__before_clear_bit() smp_mb() | ||
34 | #define smp_mb__after_clear_bit() smp_mb() | ||
32 | 35 | ||
33 | #define set_mb(var, value) do { var = value; mb(); } while (0) | 36 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
34 | 37 | ||
35 | #endif /* __ASM_BARRIER_H */ | 38 | #endif /* __ASM_BARRIER_H */ |
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index f2ea2c56a7e1..f2ef34f6d6e5 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h | |||
@@ -29,9 +29,7 @@ struct ccwgroup_device { | |||
29 | 29 | ||
30 | /** | 30 | /** |
31 | * struct ccwgroup_driver - driver for ccw group devices | 31 | * struct ccwgroup_driver - driver for ccw group devices |
32 | * @max_slaves: maximum number of slave devices | 32 | * @setup: function called during device creation to setup the device |
33 | * @driver_id: unique id | ||
34 | * @probe: function called on probe | ||
35 | * @remove: function called on remove | 33 | * @remove: function called on remove |
36 | * @set_online: function called when device is set online | 34 | * @set_online: function called when device is set online |
37 | * @set_offline: function called when device is set offline | 35 | * @set_offline: function called when device is set offline |
@@ -44,10 +42,7 @@ struct ccwgroup_device { | |||
44 | * @driver: embedded driver structure | 42 | * @driver: embedded driver structure |
45 | */ | 43 | */ |
46 | struct ccwgroup_driver { | 44 | struct ccwgroup_driver { |
47 | int max_slaves; | 45 | int (*setup) (struct ccwgroup_device *); |
48 | unsigned long driver_id; | ||
49 | |||
50 | int (*probe) (struct ccwgroup_device *); | ||
51 | void (*remove) (struct ccwgroup_device *); | 46 | void (*remove) (struct ccwgroup_device *); |
52 | int (*set_online) (struct ccwgroup_device *); | 47 | int (*set_online) (struct ccwgroup_device *); |
53 | int (*set_offline) (struct ccwgroup_device *); | 48 | int (*set_offline) (struct ccwgroup_device *); |
@@ -63,9 +58,8 @@ struct ccwgroup_driver { | |||
63 | 58 | ||
64 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); | 59 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); |
65 | extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); | 60 | extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); |
66 | int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | 61 | int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv, |
67 | struct ccw_driver *cdrv, int num_devices, | 62 | int num_devices, const char *buf); |
68 | const char *buf); | ||
69 | 63 | ||
70 | extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); | 64 | extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); |
71 | extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); | 65 | extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); |
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index b7ff6afc3caa..27216d317991 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h | |||
@@ -38,11 +38,8 @@ static inline void * phys_to_virt(unsigned long address) | |||
38 | return (void *) address; | 38 | return (void *) address; |
39 | } | 39 | } |
40 | 40 | ||
41 | /* | 41 | void *xlate_dev_mem_ptr(unsigned long phys); |
42 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | 42 | void unxlate_dev_mem_ptr(unsigned long phys, void *addr); |
43 | * access | ||
44 | */ | ||
45 | #define xlate_dev_mem_ptr(p) __va(p) | ||
46 | 43 | ||
47 | /* | 44 | /* |
48 | * Convert a virtual cached pointer to an uncached pointer | 45 | * Convert a virtual cached pointer to an uncached pointer |
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index d75c8e78f7e3..f039d86adf67 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h | |||
@@ -258,11 +258,6 @@ struct slsb { | |||
258 | u8 val[QDIO_MAX_BUFFERS_PER_Q]; | 258 | u8 val[QDIO_MAX_BUFFERS_PER_Q]; |
259 | } __attribute__ ((packed, aligned(256))); | 259 | } __attribute__ ((packed, aligned(256))); |
260 | 260 | ||
261 | #define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080 | ||
262 | #define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040 | ||
263 | #define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 | ||
264 | #define CHSC_AC2_DATA_DIV_ENABLED 0x0002 | ||
265 | |||
266 | /** | 261 | /** |
267 | * struct qdio_outbuf_state - SBAL related asynchronous operation information | 262 | * struct qdio_outbuf_state - SBAL related asynchronous operation information |
268 | * (for communication with upper layer programs) | 263 | * (for communication with upper layer programs) |
@@ -293,6 +288,8 @@ struct qdio_outbuf_state { | |||
293 | #define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */ | 288 | #define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */ |
294 | #define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */ | 289 | #define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */ |
295 | 290 | ||
291 | #define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080 | ||
292 | #define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040 | ||
296 | #define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 | 293 | #define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 |
297 | #define CHSC_AC2_DATA_DIV_ENABLED 0x0002 | 294 | #define CHSC_AC2_DATA_DIV_ENABLED 0x0002 |
298 | 295 | ||
@@ -328,11 +325,13 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, | |||
328 | int, int, unsigned long); | 325 | int, int, unsigned long); |
329 | 326 | ||
330 | /* qdio errors reported to the upper-layer program */ | 327 | /* qdio errors reported to the upper-layer program */ |
331 | #define QDIO_ERROR_SIGA_TARGET 0x02 | 328 | #define QDIO_ERROR_ACTIVATE 0x0001 |
332 | #define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10 | 329 | #define QDIO_ERROR_GET_BUF_STATE 0x0002 |
333 | #define QDIO_ERROR_SIGA_BUSY 0x20 | 330 | #define QDIO_ERROR_SET_BUF_STATE 0x0004 |
334 | #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 | 331 | #define QDIO_ERROR_SLSB_STATE 0x0100 |
335 | #define QDIO_ERROR_SLSB_STATE 0x80 | 332 | |
333 | #define QDIO_ERROR_FATAL 0x00ff | ||
334 | #define QDIO_ERROR_TEMPORARY 0xff00 | ||
336 | 335 | ||
337 | /* for qdio_cleanup */ | 336 | /* for qdio_cleanup */ |
338 | #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 | 337 | #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 |
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index b21e46e5d4b8..7244e1f64126 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -82,7 +82,6 @@ extern unsigned int user_mode; | |||
82 | #define MACHINE_FLAG_LPAR (1UL << 12) | 82 | #define MACHINE_FLAG_LPAR (1UL << 12) |
83 | #define MACHINE_FLAG_SPP (1UL << 13) | 83 | #define MACHINE_FLAG_SPP (1UL << 13) |
84 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) | 84 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) |
85 | #define MACHINE_FLAG_STCKF (1UL << 15) | ||
86 | 85 | ||
87 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) | 86 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) |
88 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) | 87 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) |
@@ -101,7 +100,6 @@ extern unsigned int user_mode; | |||
101 | #define MACHINE_HAS_PFMF (0) | 100 | #define MACHINE_HAS_PFMF (0) |
102 | #define MACHINE_HAS_SPP (0) | 101 | #define MACHINE_HAS_SPP (0) |
103 | #define MACHINE_HAS_TOPOLOGY (0) | 102 | #define MACHINE_HAS_TOPOLOGY (0) |
104 | #define MACHINE_HAS_STCKF (0) | ||
105 | #else /* __s390x__ */ | 103 | #else /* __s390x__ */ |
106 | #define MACHINE_HAS_IEEE (1) | 104 | #define MACHINE_HAS_IEEE (1) |
107 | #define MACHINE_HAS_CSP (1) | 105 | #define MACHINE_HAS_CSP (1) |
@@ -113,7 +111,6 @@ extern unsigned int user_mode; | |||
113 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) | 111 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) |
114 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) | 112 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) |
115 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) | 113 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) |
116 | #define MACHINE_HAS_STCKF (S390_lowcore.machine_flags & MACHINE_FLAG_STCKF) | ||
117 | #endif /* __s390x__ */ | 114 | #endif /* __s390x__ */ |
118 | 115 | ||
119 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) | 116 | #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 a73038155e0d..003b04edcff6 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -95,7 +95,6 @@ static inline struct thread_info *current_thread_info(void) | |||
95 | #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ | 95 | #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ |
96 | #define TIF_SECCOMP 10 /* secure computing */ | 96 | #define TIF_SECCOMP 10 /* secure computing */ |
97 | #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ | 97 | #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ |
98 | #define TIF_SIE 12 /* guest execution active */ | ||
99 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling | 98 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling |
100 | TIF_NEED_RESCHED */ | 99 | TIF_NEED_RESCHED */ |
101 | #define TIF_31BIT 17 /* 32bit process */ | 100 | #define TIF_31BIT 17 /* 32bit process */ |
@@ -114,7 +113,6 @@ static inline struct thread_info *current_thread_info(void) | |||
114 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 113 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
115 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) | 114 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) |
116 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | 115 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) |
117 | #define _TIF_SIE (1<<TIF_SIE) | ||
118 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 116 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
119 | #define _TIF_31BIT (1<<TIF_31BIT) | 117 | #define _TIF_31BIT (1<<TIF_31BIT) |
120 | #define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP) | 118 | #define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP) |
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index c447a27a7fdb..239ece9e53c1 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h | |||
@@ -73,11 +73,15 @@ static inline void local_tick_enable(unsigned long long comp) | |||
73 | 73 | ||
74 | typedef unsigned long long cycles_t; | 74 | typedef unsigned long long cycles_t; |
75 | 75 | ||
76 | static inline unsigned long long get_clock (void) | 76 | static inline unsigned long long get_clock(void) |
77 | { | 77 | { |
78 | unsigned long long clk; | 78 | unsigned long long clk; |
79 | 79 | ||
80 | #ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES | ||
81 | asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc"); | ||
82 | #else | ||
80 | asm volatile("stck %0" : "=Q" (clk) : : "cc"); | 83 | asm volatile("stck %0" : "=Q" (clk) : : "cc"); |
84 | #endif | ||
81 | return clk; | 85 | return clk; |
82 | } | 86 | } |
83 | 87 | ||
@@ -86,17 +90,6 @@ static inline void get_clock_ext(char *clk) | |||
86 | asm volatile("stcke %0" : "=Q" (*clk) : : "cc"); | 90 | asm volatile("stcke %0" : "=Q" (*clk) : : "cc"); |
87 | } | 91 | } |
88 | 92 | ||
89 | static inline unsigned long long get_clock_fast(void) | ||
90 | { | ||
91 | unsigned long long clk; | ||
92 | |||
93 | if (MACHINE_HAS_STCKF) | ||
94 | asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc"); | ||
95 | else | ||
96 | clk = get_clock(); | ||
97 | return clk; | ||
98 | } | ||
99 | |||
100 | static inline unsigned long long get_clock_xt(void) | 93 | static inline unsigned long long get_clock_xt(void) |
101 | { | 94 | { |
102 | unsigned char clk[16]; | 95 | unsigned char clk[16]; |
diff --git a/arch/s390/kernel/.gitignore b/arch/s390/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/s390/kernel/.gitignore | |||
@@ -0,0 +1 @@ | |||
vmlinux.lds | |||
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 28040fd5e8a2..377c096ca4a7 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c | |||
@@ -437,13 +437,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | |||
437 | sp = current->sas_ss_sp + current->sas_ss_size; | 437 | sp = current->sas_ss_sp + current->sas_ss_size; |
438 | } | 438 | } |
439 | 439 | ||
440 | /* This is the legacy signal stack switching. */ | ||
441 | else if (!user_mode(regs) && | ||
442 | !(ka->sa.sa_flags & SA_RESTORER) && | ||
443 | ka->sa.sa_restorer) { | ||
444 | sp = (unsigned long) ka->sa.sa_restorer; | ||
445 | } | ||
446 | |||
447 | return (void __user *)((sp - frame_size) & -8ul); | 440 | return (void __user *)((sp - frame_size) & -8ul); |
448 | } | 441 | } |
449 | 442 | ||
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 9475e682727f..d84181f1f5e8 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -374,8 +374,6 @@ static __init void detect_machine_facilities(void) | |||
374 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; | 374 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; |
375 | if (test_facility(40)) | 375 | if (test_facility(40)) |
376 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; | 376 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; |
377 | if (test_facility(25)) | ||
378 | S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF; | ||
379 | #endif | 377 | #endif |
380 | } | 378 | } |
381 | 379 | ||
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 74ee563fe62b..1ae93b573d7d 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -145,22 +145,23 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
145 | * gpr2 = prev | 145 | * gpr2 = prev |
146 | */ | 146 | */ |
147 | ENTRY(__switch_to) | 147 | ENTRY(__switch_to) |
148 | stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task | ||
149 | st %r15,__THREAD_ksp(%r2) # store kernel stack of prev | ||
148 | l %r4,__THREAD_info(%r2) # get thread_info of prev | 150 | l %r4,__THREAD_info(%r2) # get thread_info of prev |
149 | l %r5,__THREAD_info(%r3) # get thread_info of next | 151 | l %r5,__THREAD_info(%r3) # get thread_info of next |
152 | lr %r15,%r5 | ||
153 | ahi %r15,STACK_SIZE # end of kernel stack of next | ||
154 | st %r3,__LC_CURRENT # store task struct of next | ||
155 | st %r5,__LC_THREAD_INFO # store thread info of next | ||
156 | st %r15,__LC_KERNEL_STACK # store end of kernel stack | ||
157 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 | ||
158 | mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next | ||
159 | l %r15,__THREAD_ksp(%r3) # load kernel stack of next | ||
150 | tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? | 160 | tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? |
151 | jz 0f | 161 | jz 0f |
152 | ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev | 162 | ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev |
153 | oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next | 163 | oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next |
154 | 0: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task | 164 | 0: lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
155 | st %r15,__THREAD_ksp(%r2) # store kernel stack of prev | ||
156 | l %r15,__THREAD_ksp(%r3) # load kernel stack of next | ||
157 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 | ||
158 | lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task | ||
159 | st %r3,__LC_CURRENT # store task struct of next | ||
160 | mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next | ||
161 | st %r5,__LC_THREAD_INFO # store thread info of next | ||
162 | ahi %r5,STACK_SIZE # end of kernel stack of next | ||
163 | st %r5,__LC_KERNEL_STACK # store end of kernel stack | ||
164 | br %r14 | 165 | br %r14 |
165 | 166 | ||
166 | __critical_start: | 167 | __critical_start: |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 4e1c292fa7e3..229fe1d07749 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -81,16 +81,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
81 | 81 | ||
82 | .macro HANDLE_SIE_INTERCEPT scratch | 82 | .macro HANDLE_SIE_INTERCEPT scratch |
83 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 83 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |
84 | tm __TI_flags+6(%r12),_TIF_SIE>>8 | 84 | tmhh %r8,0x0001 # interrupting from user ? |
85 | jz .+42 | 85 | jnz .+42 |
86 | tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP | ||
87 | jz .+8 | ||
88 | .insn s,0xb2800000,BASED(.Lhost_id) # set host id | ||
89 | lgr \scratch,%r9 | 86 | lgr \scratch,%r9 |
90 | slg \scratch,BASED(.Lsie_loop) | 87 | slg \scratch,BASED(.Lsie_loop) |
91 | clg \scratch,BASED(.Lsie_length) | 88 | clg \scratch,BASED(.Lsie_length) |
92 | jhe .+10 | 89 | jhe .+22 |
93 | lg %r9,BASED(.Lsie_loop) | 90 | lg %r9,BASED(.Lsie_loop) |
91 | SPP BASED(.Lhost_id) # set host id | ||
94 | #endif | 92 | #endif |
95 | .endm | 93 | .endm |
96 | 94 | ||
@@ -148,6 +146,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
148 | ssm __LC_RETURN_PSW | 146 | ssm __LC_RETURN_PSW |
149 | .endm | 147 | .endm |
150 | 148 | ||
149 | .macro STCK savearea | ||
150 | #ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES | ||
151 | .insn s,0xb27c0000,\savearea # store clock fast | ||
152 | #else | ||
153 | .insn s,0xb2050000,\savearea # store clock | ||
154 | #endif | ||
155 | .endm | ||
156 | |||
151 | .section .kprobes.text, "ax" | 157 | .section .kprobes.text, "ax" |
152 | 158 | ||
153 | /* | 159 | /* |
@@ -158,22 +164,23 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
158 | * gpr2 = prev | 164 | * gpr2 = prev |
159 | */ | 165 | */ |
160 | ENTRY(__switch_to) | 166 | ENTRY(__switch_to) |
167 | stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task | ||
168 | stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev | ||
161 | lg %r4,__THREAD_info(%r2) # get thread_info of prev | 169 | lg %r4,__THREAD_info(%r2) # get thread_info of prev |
162 | lg %r5,__THREAD_info(%r3) # get thread_info of next | 170 | lg %r5,__THREAD_info(%r3) # get thread_info of next |
171 | lgr %r15,%r5 | ||
172 | aghi %r15,STACK_SIZE # end of kernel stack of next | ||
173 | stg %r3,__LC_CURRENT # store task struct of next | ||
174 | stg %r5,__LC_THREAD_INFO # store thread info of next | ||
175 | stg %r15,__LC_KERNEL_STACK # store end of kernel stack | ||
176 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 | ||
177 | mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next | ||
178 | lg %r15,__THREAD_ksp(%r3) # load kernel stack of next | ||
163 | tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? | 179 | tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? |
164 | jz 0f | 180 | jz 0f |
165 | ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev | 181 | ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev |
166 | oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next | 182 | oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next |
167 | 0: stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task | 183 | 0: lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
168 | stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev | ||
169 | lg %r15,__THREAD_ksp(%r3) # load kernel stack of next | ||
170 | lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 | ||
171 | lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task | ||
172 | stg %r3,__LC_CURRENT # store task struct of next | ||
173 | mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next | ||
174 | stg %r5,__LC_THREAD_INFO # store thread info of next | ||
175 | aghi %r5,STACK_SIZE # end of kernel stack of next | ||
176 | stg %r5,__LC_KERNEL_STACK # store end of kernel stack | ||
177 | br %r14 | 184 | br %r14 |
178 | 185 | ||
179 | __critical_start: | 186 | __critical_start: |
@@ -458,7 +465,7 @@ pgm_svcper: | |||
458 | * IO interrupt handler routine | 465 | * IO interrupt handler routine |
459 | */ | 466 | */ |
460 | ENTRY(io_int_handler) | 467 | ENTRY(io_int_handler) |
461 | stck __LC_INT_CLOCK | 468 | STCK __LC_INT_CLOCK |
462 | stpt __LC_ASYNC_ENTER_TIMER | 469 | stpt __LC_ASYNC_ENTER_TIMER |
463 | stmg %r8,%r15,__LC_SAVE_AREA_ASYNC | 470 | stmg %r8,%r15,__LC_SAVE_AREA_ASYNC |
464 | lg %r10,__LC_LAST_BREAK | 471 | lg %r10,__LC_LAST_BREAK |
@@ -604,7 +611,7 @@ io_notify_resume: | |||
604 | * External interrupt handler routine | 611 | * External interrupt handler routine |
605 | */ | 612 | */ |
606 | ENTRY(ext_int_handler) | 613 | ENTRY(ext_int_handler) |
607 | stck __LC_INT_CLOCK | 614 | STCK __LC_INT_CLOCK |
608 | stpt __LC_ASYNC_ENTER_TIMER | 615 | stpt __LC_ASYNC_ENTER_TIMER |
609 | stmg %r8,%r15,__LC_SAVE_AREA_ASYNC | 616 | stmg %r8,%r15,__LC_SAVE_AREA_ASYNC |
610 | lg %r10,__LC_LAST_BREAK | 617 | lg %r10,__LC_LAST_BREAK |
@@ -622,6 +629,7 @@ ext_skip: | |||
622 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC | 629 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC |
623 | stmg %r8,%r9,__PT_PSW(%r11) | 630 | stmg %r8,%r9,__PT_PSW(%r11) |
624 | TRACE_IRQS_OFF | 631 | TRACE_IRQS_OFF |
632 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | ||
625 | lghi %r1,4096 | 633 | lghi %r1,4096 |
626 | lgr %r2,%r11 # pass pointer to pt_regs | 634 | lgr %r2,%r11 # pass pointer to pt_regs |
627 | llgf %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code | 635 | llgf %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code |
@@ -638,7 +646,7 @@ ENTRY(psw_idle) | |||
638 | larl %r1,psw_idle_lpsw+4 | 646 | larl %r1,psw_idle_lpsw+4 |
639 | stg %r1,__SF_EMPTY+8(%r15) | 647 | stg %r1,__SF_EMPTY+8(%r15) |
640 | larl %r1,.Lvtimer_max | 648 | larl %r1,.Lvtimer_max |
641 | stck __IDLE_ENTER(%r2) | 649 | STCK __IDLE_ENTER(%r2) |
642 | ltr %r5,%r5 | 650 | ltr %r5,%r5 |
643 | stpt __VQ_IDLE_ENTER(%r3) | 651 | stpt __VQ_IDLE_ENTER(%r3) |
644 | jz psw_idle_lpsw | 652 | jz psw_idle_lpsw |
@@ -654,7 +662,7 @@ __critical_end: | |||
654 | * Machine check handler routines | 662 | * Machine check handler routines |
655 | */ | 663 | */ |
656 | ENTRY(mcck_int_handler) | 664 | ENTRY(mcck_int_handler) |
657 | stck __LC_MCCK_CLOCK | 665 | STCK __LC_MCCK_CLOCK |
658 | la %r1,4095 # revalidate r1 | 666 | la %r1,4095 # revalidate r1 |
659 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | 667 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer |
660 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | 668 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs |
@@ -967,7 +975,6 @@ ENTRY(sie64a) | |||
967 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 | 975 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 |
968 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 | 976 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 |
969 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 977 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct |
970 | oi __TI_flags+6(%r14),_TIF_SIE>>8 | ||
971 | sie_loop: | 978 | sie_loop: |
972 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 979 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct |
973 | tm __TI_flags+7(%r14),_TIF_EXIT_SIE | 980 | tm __TI_flags+7(%r14),_TIF_EXIT_SIE |
@@ -985,7 +992,6 @@ sie_done: | |||
985 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 992 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct |
986 | sie_exit: | 993 | sie_exit: |
987 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 994 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
988 | ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) | ||
989 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area | 995 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area |
990 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 | 996 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 |
991 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers | 997 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers |
@@ -994,7 +1000,6 @@ sie_exit: | |||
994 | sie_fault: | 1000 | sie_fault: |
995 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 1001 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
996 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 1002 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct |
997 | ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) | ||
998 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area | 1003 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area |
999 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 | 1004 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 |
1000 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers | 1005 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index adccd908ebc7..4939d15375aa 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -34,125 +34,7 @@ | |||
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | __HEAD | 36 | __HEAD |
37 | #ifndef CONFIG_IPL | ||
38 | .org 0 | ||
39 | .long 0x00080000,0x80000000+startup # Just a restart PSW | ||
40 | #else | ||
41 | #ifdef CONFIG_IPL_TAPE | ||
42 | #define IPL_BS 1024 | ||
43 | .org 0 | ||
44 | .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded | ||
45 | .long 0x27000000,0x60000001 # by ipl to addresses 0-23. | ||
46 | .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). | ||
47 | .long 0x00000000,0x00000000 # external old psw | ||
48 | .long 0x00000000,0x00000000 # svc old psw | ||
49 | .long 0x00000000,0x00000000 # program check old psw | ||
50 | .long 0x00000000,0x00000000 # machine check old psw | ||
51 | .long 0x00000000,0x00000000 # io old psw | ||
52 | .long 0x00000000,0x00000000 | ||
53 | .long 0x00000000,0x00000000 | ||
54 | .long 0x00000000,0x00000000 | ||
55 | .long 0x000a0000,0x00000058 # external new psw | ||
56 | .long 0x000a0000,0x00000060 # svc new psw | ||
57 | .long 0x000a0000,0x00000068 # program check new psw | ||
58 | .long 0x000a0000,0x00000070 # machine check new psw | ||
59 | .long 0x00080000,0x80000000+.Lioint # io new psw | ||
60 | 37 | ||
61 | .org 0x100 | ||
62 | # | ||
63 | # subroutine for loading from tape | ||
64 | # Parameters: | ||
65 | # R1 = device number | ||
66 | # R2 = load address | ||
67 | .Lloader: | ||
68 | st %r14,.Lldret | ||
69 | la %r3,.Lorbread # r3 = address of orb | ||
70 | la %r5,.Lirb # r5 = address of irb | ||
71 | st %r2,.Lccwread+4 # initialize CCW data addresses | ||
72 | lctl %c6,%c6,.Lcr6 | ||
73 | slr %r2,%r2 | ||
74 | .Lldlp: | ||
75 | la %r6,3 # 3 retries | ||
76 | .Lssch: | ||
77 | ssch 0(%r3) # load chunk of IPL_BS bytes | ||
78 | bnz .Llderr | ||
79 | .Lw4end: | ||
80 | bas %r14,.Lwait4io | ||
81 | tm 8(%r5),0x82 # do we have a problem ? | ||
82 | bnz .Lrecov | ||
83 | slr %r7,%r7 | ||
84 | icm %r7,3,10(%r5) # get residual count | ||
85 | lcr %r7,%r7 | ||
86 | la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read | ||
87 | ar %r2,%r7 # add to total size | ||
88 | tm 8(%r5),0x01 # found a tape mark ? | ||
89 | bnz .Ldone | ||
90 | l %r0,.Lccwread+4 # update CCW data addresses | ||
91 | ar %r0,%r7 | ||
92 | st %r0,.Lccwread+4 | ||
93 | b .Lldlp | ||
94 | .Ldone: | ||
95 | l %r14,.Lldret | ||
96 | br %r14 # r2 contains the total size | ||
97 | .Lrecov: | ||
98 | bas %r14,.Lsense # do the sensing | ||
99 | bct %r6,.Lssch # dec. retry count & branch | ||
100 | b .Llderr | ||
101 | # | ||
102 | # Sense subroutine | ||
103 | # | ||
104 | .Lsense: | ||
105 | st %r14,.Lsnsret | ||
106 | la %r7,.Lorbsense | ||
107 | ssch 0(%r7) # start sense command | ||
108 | bnz .Llderr | ||
109 | bas %r14,.Lwait4io | ||
110 | l %r14,.Lsnsret | ||
111 | tm 8(%r5),0x82 # do we have a problem ? | ||
112 | bnz .Llderr | ||
113 | br %r14 | ||
114 | # | ||
115 | # Wait for interrupt subroutine | ||
116 | # | ||
117 | .Lwait4io: | ||
118 | lpsw .Lwaitpsw | ||
119 | .Lioint: | ||
120 | c %r1,0xb8 # compare subchannel number | ||
121 | bne .Lwait4io | ||
122 | tsch 0(%r5) | ||
123 | slr %r0,%r0 | ||
124 | tm 8(%r5),0x82 # do we have a problem ? | ||
125 | bnz .Lwtexit | ||
126 | tm 8(%r5),0x04 # got device end ? | ||
127 | bz .Lwait4io | ||
128 | .Lwtexit: | ||
129 | br %r14 | ||
130 | .Llderr: | ||
131 | lpsw .Lcrash | ||
132 | |||
133 | .align 8 | ||
134 | .Lorbread: | ||
135 | .long 0x00000000,0x0080ff00,.Lccwread | ||
136 | .align 8 | ||
137 | .Lorbsense: | ||
138 | .long 0x00000000,0x0080ff00,.Lccwsense | ||
139 | .align 8 | ||
140 | .Lccwread: | ||
141 | .long 0x02200000+IPL_BS,0x00000000 | ||
142 | .Lccwsense: | ||
143 | .long 0x04200001,0x00000000 | ||
144 | .Lwaitpsw: | ||
145 | .long 0x020a0000,0x80000000+.Lioint | ||
146 | |||
147 | .Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | ||
148 | .Lcr6: .long 0xff000000 | ||
149 | .align 8 | ||
150 | .Lcrash:.long 0x000a0000,0x00000000 | ||
151 | .Lldret:.long 0 | ||
152 | .Lsnsret: .long 0 | ||
153 | #endif /* CONFIG_IPL_TAPE */ | ||
154 | |||
155 | #ifdef CONFIG_IPL_VM | ||
156 | #define IPL_BS 0x730 | 38 | #define IPL_BS 0x730 |
157 | .org 0 | 39 | .org 0 |
158 | .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded | 40 | .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded |
@@ -256,7 +138,6 @@ __HEAD | |||
256 | .long 0x02600050,0x00000000 | 138 | .long 0x02600050,0x00000000 |
257 | .endr | 139 | .endr |
258 | .long 0x02200050,0x00000000 | 140 | .long 0x02200050,0x00000000 |
259 | #endif /* CONFIG_IPL_VM */ | ||
260 | 141 | ||
261 | iplstart: | 142 | iplstart: |
262 | lh %r1,0xb8 # test if subchannel number | 143 | lh %r1,0xb8 # test if subchannel number |
@@ -325,7 +206,6 @@ iplstart: | |||
325 | clc 0(3,%r2),.L_eof | 206 | clc 0(3,%r2),.L_eof |
326 | bz .Lagain2 | 207 | bz .Lagain2 |
327 | 208 | ||
328 | #ifdef CONFIG_IPL_VM | ||
329 | # | 209 | # |
330 | # reset files in VM reader | 210 | # reset files in VM reader |
331 | # | 211 | # |
@@ -358,7 +238,6 @@ iplstart: | |||
358 | .long 0x00080000,0x80000000+.Lrdrint | 238 | .long 0x00080000,0x80000000+.Lrdrint |
359 | .Lrdrwaitpsw: | 239 | .Lrdrwaitpsw: |
360 | .long 0x020a0000,0x80000000+.Lrdrint | 240 | .long 0x020a0000,0x80000000+.Lrdrint |
361 | #endif | ||
362 | 241 | ||
363 | # | 242 | # |
364 | # everything loaded, go for it | 243 | # everything loaded, go for it |
@@ -376,8 +255,6 @@ iplstart: | |||
376 | .L_eof: .long 0xc5d6c600 /* C'EOF' */ | 255 | .L_eof: .long 0xc5d6c600 /* C'EOF' */ |
377 | .L_hdr: .long 0xc8c4d900 /* C'HDR' */ | 256 | .L_hdr: .long 0xc8c4d900 /* C'HDR' */ |
378 | 257 | ||
379 | #endif /* CONFIG_IPL */ | ||
380 | |||
381 | # | 258 | # |
382 | # SALIPL loader support. Based on a patch by Rob van der Heij. | 259 | # SALIPL loader support. Based on a patch by Rob van der Heij. |
383 | # This entry point is called directly from the SALIPL loader and | 260 | # This entry point is called directly from the SALIPL loader and |
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index f7582b27f600..8a4e2b760d56 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -235,13 +235,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | |||
235 | sp = current->sas_ss_sp + current->sas_ss_size; | 235 | sp = current->sas_ss_sp + current->sas_ss_size; |
236 | } | 236 | } |
237 | 237 | ||
238 | /* This is the legacy signal stack switching. */ | ||
239 | else if (!user_mode(regs) && | ||
240 | !(ka->sa.sa_flags & SA_RESTORER) && | ||
241 | ka->sa.sa_restorer) { | ||
242 | sp = (unsigned long) ka->sa.sa_restorer; | ||
243 | } | ||
244 | |||
245 | return (void __user *)((sp - frame_size) & -8ul); | 238 | return (void __user *)((sp - frame_size) & -8ul); |
246 | } | 239 | } |
247 | 240 | ||
@@ -414,15 +407,6 @@ void do_signal(struct pt_regs *regs) | |||
414 | struct k_sigaction ka; | 407 | struct k_sigaction ka; |
415 | sigset_t *oldset; | 408 | sigset_t *oldset; |
416 | 409 | ||
417 | /* | ||
418 | * We want the common case to go fast, which | ||
419 | * is why we may in certain cases get here from | ||
420 | * kernel mode. Just return without doing anything | ||
421 | * if so. | ||
422 | */ | ||
423 | if (!user_mode(regs)) | ||
424 | return; | ||
425 | |||
426 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 410 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
427 | oldset = ¤t->saved_sigmask; | 411 | oldset = ¤t->saved_sigmask; |
428 | else | 412 | else |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f77227669e8..e505458c6899 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -226,6 +226,8 @@ out: | |||
226 | return -ENOMEM; | 226 | return -ENOMEM; |
227 | } | 227 | } |
228 | 228 | ||
229 | #ifdef CONFIG_HOTPLUG_CPU | ||
230 | |||
229 | static void pcpu_free_lowcore(struct pcpu *pcpu) | 231 | static void pcpu_free_lowcore(struct pcpu *pcpu) |
230 | { | 232 | { |
231 | pcpu_sigp_retry(pcpu, sigp_set_prefix, 0); | 233 | pcpu_sigp_retry(pcpu, sigp_set_prefix, 0); |
@@ -247,6 +249,8 @@ static void pcpu_free_lowcore(struct pcpu *pcpu) | |||
247 | } | 249 | } |
248 | } | 250 | } |
249 | 251 | ||
252 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
253 | |||
250 | static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) | 254 | static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) |
251 | { | 255 | { |
252 | struct _lowcore *lc = pcpu->lowcore; | 256 | struct _lowcore *lc = pcpu->lowcore; |
diff --git a/arch/s390/kernel/vdso32/.gitignore b/arch/s390/kernel/vdso32/.gitignore new file mode 100644 index 000000000000..e45fba9d0ced --- /dev/null +++ b/arch/s390/kernel/vdso32/.gitignore | |||
@@ -0,0 +1 @@ | |||
vdso32.lds | |||
diff --git a/arch/s390/kernel/vdso64/.gitignore b/arch/s390/kernel/vdso64/.gitignore new file mode 100644 index 000000000000..3fd18cf9fec2 --- /dev/null +++ b/arch/s390/kernel/vdso64/.gitignore | |||
@@ -0,0 +1 @@ | |||
vdso64.lds | |||
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 46ef3fd0663b..72cec9ecd96c 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -294,7 +294,7 @@ static inline int do_exception(struct pt_regs *regs, int access) | |||
294 | down_read(&mm->mmap_sem); | 294 | down_read(&mm->mmap_sem); |
295 | 295 | ||
296 | #ifdef CONFIG_PGSTE | 296 | #ifdef CONFIG_PGSTE |
297 | if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) { | 297 | if ((current->flags & PF_VCPU) && S390_lowcore.gmap) { |
298 | address = __gmap_fault(address, | 298 | address = __gmap_fault(address, |
299 | (struct gmap *) S390_lowcore.gmap); | 299 | (struct gmap *) S390_lowcore.gmap); |
300 | if (address == -EFAULT) { | 300 | if (address == -EFAULT) { |
@@ -549,19 +549,15 @@ static void pfault_interrupt(struct ext_code ext_code, | |||
549 | if ((subcode & 0xff00) != __SUBCODE_MASK) | 549 | if ((subcode & 0xff00) != __SUBCODE_MASK) |
550 | return; | 550 | return; |
551 | kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; | 551 | kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; |
552 | if (subcode & 0x0080) { | 552 | /* Get the token (= pid of the affected task). */ |
553 | /* Get the token (= pid of the affected task). */ | 553 | pid = sizeof(void *) == 4 ? param32 : param64; |
554 | pid = sizeof(void *) == 4 ? param32 : param64; | 554 | rcu_read_lock(); |
555 | rcu_read_lock(); | 555 | tsk = find_task_by_pid_ns(pid, &init_pid_ns); |
556 | tsk = find_task_by_pid_ns(pid, &init_pid_ns); | 556 | if (tsk) |
557 | if (tsk) | 557 | get_task_struct(tsk); |
558 | get_task_struct(tsk); | 558 | rcu_read_unlock(); |
559 | rcu_read_unlock(); | 559 | if (!tsk) |
560 | if (!tsk) | 560 | return; |
561 | return; | ||
562 | } else { | ||
563 | tsk = current; | ||
564 | } | ||
565 | spin_lock(&pfault_lock); | 561 | spin_lock(&pfault_lock); |
566 | if (subcode & 0x0080) { | 562 | if (subcode & 0x0080) { |
567 | /* signal bit is set -> a page has been swapped in by VM */ | 563 | /* signal bit is set -> a page has been swapped in by VM */ |
@@ -574,6 +570,7 @@ static void pfault_interrupt(struct ext_code ext_code, | |||
574 | tsk->thread.pfault_wait = 0; | 570 | tsk->thread.pfault_wait = 0; |
575 | list_del(&tsk->thread.list); | 571 | list_del(&tsk->thread.list); |
576 | wake_up_process(tsk); | 572 | wake_up_process(tsk); |
573 | put_task_struct(tsk); | ||
577 | } else { | 574 | } else { |
578 | /* Completion interrupt was faster than initial | 575 | /* Completion interrupt was faster than initial |
579 | * interrupt. Set pfault_wait to -1 so the initial | 576 | * interrupt. Set pfault_wait to -1 so the initial |
@@ -585,24 +582,35 @@ static void pfault_interrupt(struct ext_code ext_code, | |||
585 | if (tsk->state == TASK_RUNNING) | 582 | if (tsk->state == TASK_RUNNING) |
586 | tsk->thread.pfault_wait = -1; | 583 | tsk->thread.pfault_wait = -1; |
587 | } | 584 | } |
588 | put_task_struct(tsk); | ||
589 | } else { | 585 | } else { |
590 | /* signal bit not set -> a real page is missing. */ | 586 | /* signal bit not set -> a real page is missing. */ |
591 | if (tsk->thread.pfault_wait == -1) { | 587 | if (WARN_ON_ONCE(tsk != current)) |
588 | goto out; | ||
589 | if (tsk->thread.pfault_wait == 1) { | ||
590 | /* Already on the list with a reference: put to sleep */ | ||
591 | __set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
592 | set_tsk_need_resched(tsk); | ||
593 | } else if (tsk->thread.pfault_wait == -1) { | ||
592 | /* Completion interrupt was faster than the initial | 594 | /* Completion interrupt was faster than the initial |
593 | * interrupt (pfault_wait == -1). Set pfault_wait | 595 | * interrupt (pfault_wait == -1). Set pfault_wait |
594 | * back to zero and exit. */ | 596 | * back to zero and exit. */ |
595 | tsk->thread.pfault_wait = 0; | 597 | tsk->thread.pfault_wait = 0; |
596 | } else { | 598 | } else { |
597 | /* Initial interrupt arrived before completion | 599 | /* Initial interrupt arrived before completion |
598 | * interrupt. Let the task sleep. */ | 600 | * interrupt. Let the task sleep. |
601 | * An extra task reference is needed since a different | ||
602 | * cpu may set the task state to TASK_RUNNING again | ||
603 | * before the scheduler is reached. */ | ||
604 | get_task_struct(tsk); | ||
599 | tsk->thread.pfault_wait = 1; | 605 | tsk->thread.pfault_wait = 1; |
600 | list_add(&tsk->thread.list, &pfault_list); | 606 | list_add(&tsk->thread.list, &pfault_list); |
601 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | 607 | __set_task_state(tsk, TASK_UNINTERRUPTIBLE); |
602 | set_tsk_need_resched(tsk); | 608 | set_tsk_need_resched(tsk); |
603 | } | 609 | } |
604 | } | 610 | } |
611 | out: | ||
605 | spin_unlock(&pfault_lock); | 612 | spin_unlock(&pfault_lock); |
613 | put_task_struct(tsk); | ||
606 | } | 614 | } |
607 | 615 | ||
608 | static int __cpuinit pfault_cpu_notify(struct notifier_block *self, | 616 | static int __cpuinit pfault_cpu_notify(struct notifier_block *self, |
@@ -620,6 +628,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self, | |||
620 | list_del(&thread->list); | 628 | list_del(&thread->list); |
621 | tsk = container_of(thread, struct task_struct, thread); | 629 | tsk = container_of(thread, struct task_struct, thread); |
622 | wake_up_process(tsk); | 630 | wake_up_process(tsk); |
631 | put_task_struct(tsk); | ||
623 | } | 632 | } |
624 | spin_unlock_irq(&pfault_lock); | 633 | spin_unlock_irq(&pfault_lock); |
625 | break; | 634 | break; |
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index 597bb2d27c3c..900de2b3cf28 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c | |||
@@ -58,6 +58,8 @@ void arch_release_hugepage(struct page *page) | |||
58 | ptep = (pte_t *) page[1].index; | 58 | ptep = (pte_t *) page[1].index; |
59 | if (!ptep) | 59 | if (!ptep) |
60 | return; | 60 | return; |
61 | clear_table((unsigned long *) ptep, _PAGE_TYPE_EMPTY, | ||
62 | PTRS_PER_PTE * sizeof(pte_t)); | ||
61 | page_table_free(&init_mm, (unsigned long *) ptep); | 63 | page_table_free(&init_mm, (unsigned long *) ptep); |
62 | page[1].index = 0; | 64 | page[1].index = 0; |
63 | } | 65 | } |
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index e1335dc2b1b7..795a0a9bb2eb 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/gfp.h> | 14 | #include <linux/gfp.h> |
15 | #include <linux/cpu.h> | ||
15 | #include <asm/ctl_reg.h> | 16 | #include <asm/ctl_reg.h> |
16 | 17 | ||
17 | /* | 18 | /* |
@@ -166,3 +167,69 @@ out: | |||
166 | free_page((unsigned long) buf); | 167 | free_page((unsigned long) buf); |
167 | return rc; | 168 | return rc; |
168 | } | 169 | } |
170 | |||
171 | /* | ||
172 | * Check if physical address is within prefix or zero page | ||
173 | */ | ||
174 | static int is_swapped(unsigned long addr) | ||
175 | { | ||
176 | unsigned long lc; | ||
177 | int cpu; | ||
178 | |||
179 | if (addr < sizeof(struct _lowcore)) | ||
180 | return 1; | ||
181 | for_each_online_cpu(cpu) { | ||
182 | lc = (unsigned long) lowcore_ptr[cpu]; | ||
183 | if (addr > lc + sizeof(struct _lowcore) - 1 || addr < lc) | ||
184 | continue; | ||
185 | return 1; | ||
186 | } | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Return swapped prefix or zero page address | ||
192 | */ | ||
193 | static unsigned long get_swapped(unsigned long addr) | ||
194 | { | ||
195 | unsigned long prefix = store_prefix(); | ||
196 | |||
197 | if (addr < sizeof(struct _lowcore)) | ||
198 | return addr + prefix; | ||
199 | if (addr >= prefix && addr < prefix + sizeof(struct _lowcore)) | ||
200 | return addr - prefix; | ||
201 | return addr; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Convert a physical pointer for /dev/mem access | ||
206 | * | ||
207 | * For swapped prefix pages a new buffer is returned that contains a copy of | ||
208 | * the absolute memory. The buffer size is maximum one page large. | ||
209 | */ | ||
210 | void *xlate_dev_mem_ptr(unsigned long addr) | ||
211 | { | ||
212 | void *bounce = (void *) addr; | ||
213 | unsigned long size; | ||
214 | |||
215 | get_online_cpus(); | ||
216 | preempt_disable(); | ||
217 | if (is_swapped(addr)) { | ||
218 | size = PAGE_SIZE - (addr & ~PAGE_MASK); | ||
219 | bounce = (void *) __get_free_page(GFP_ATOMIC); | ||
220 | if (bounce) | ||
221 | memcpy_real(bounce, (void *) get_swapped(addr), size); | ||
222 | } | ||
223 | preempt_enable(); | ||
224 | put_online_cpus(); | ||
225 | return bounce; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Free converted buffer for /dev/mem access (if necessary) | ||
230 | */ | ||
231 | void unxlate_dev_mem_ptr(unsigned long addr, void *buf) | ||
232 | { | ||
233 | if ((void *) addr != buf) | ||
234 | free_page((unsigned long) buf); | ||
235 | } | ||
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6e765bf00670..a3db5a3ea083 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -822,6 +822,8 @@ int s390_enable_sie(void) | |||
822 | 822 | ||
823 | /* we copy the mm and let dup_mm create the page tables with_pgstes */ | 823 | /* we copy the mm and let dup_mm create the page tables with_pgstes */ |
824 | tsk->mm->context.alloc_pgste = 1; | 824 | tsk->mm->context.alloc_pgste = 1; |
825 | /* make sure that both mms have a correct rss state */ | ||
826 | sync_mm_rss(tsk->mm); | ||
825 | mm = dup_mm(tsk); | 827 | mm = dup_mm(tsk); |
826 | tsk->mm->context.alloc_pgste = 0; | 828 | tsk->mm->context.alloc_pgste = 0; |
827 | if (!mm) | 829 | if (!mm) |
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c index d513a07f44bb..1104acac780b 100644 --- a/block/partitions/ibm.c +++ b/block/partitions/ibm.c | |||
@@ -253,7 +253,7 @@ int ibm_partition(struct parsed_partitions *state) | |||
253 | /* Are we not supposed to report this ? */ | 253 | /* Are we not supposed to report this ? */ |
254 | goto out_readerr; | 254 | goto out_readerr; |
255 | } else | 255 | } else |
256 | printk(KERN_WARNING "Warning, expected Label VOL1 not " | 256 | printk(KERN_INFO "Expected Label VOL1 not " |
257 | "found, treating as CDL formated Disk"); | 257 | "found, treating as CDL formated Disk"); |
258 | 258 | ||
259 | } | 259 | } |
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index dd414d9350ef..371f13cc38eb 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -111,6 +111,7 @@ config CRYPTO_DES_S390 | |||
111 | depends on S390 | 111 | depends on S390 |
112 | select CRYPTO_ALGAPI | 112 | select CRYPTO_ALGAPI |
113 | select CRYPTO_BLKCIPHER | 113 | select CRYPTO_BLKCIPHER |
114 | select CRYPTO_DES | ||
114 | help | 115 | help |
115 | This is the s390 hardware accelerated implementation of the | 116 | This is the s390 hardware accelerated implementation of the |
116 | DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). | 117 | DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 231a1d85127b..36506366158d 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -352,7 +352,17 @@ out: | |||
352 | 352 | ||
353 | static int sclp_assign_storage(u16 rn) | 353 | static int sclp_assign_storage(u16 rn) |
354 | { | 354 | { |
355 | return do_assign_storage(0x000d0001, rn); | 355 | unsigned long long start, address; |
356 | int rc; | ||
357 | |||
358 | rc = do_assign_storage(0x000d0001, rn); | ||
359 | if (rc) | ||
360 | goto out; | ||
361 | start = address = rn2addr(rn); | ||
362 | for (; address < start + rzm; address += PAGE_SIZE) | ||
363 | page_set_storage_key(address, PAGE_DEFAULT_KEY, 0); | ||
364 | out: | ||
365 | return rc; | ||
356 | } | 366 | } |
357 | 367 | ||
358 | static int sclp_unassign_storage(u16 rn) | 368 | static int sclp_unassign_storage(u16 rn) |
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index 267b54e8ff5a..bc6c7cfd36b6 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h | |||
@@ -154,12 +154,6 @@ struct tape_discipline { | |||
154 | struct tape_request *(*read_block)(struct tape_device *, size_t); | 154 | struct tape_request *(*read_block)(struct tape_device *, size_t); |
155 | struct tape_request *(*write_block)(struct tape_device *, size_t); | 155 | struct tape_request *(*write_block)(struct tape_device *, size_t); |
156 | void (*process_eov)(struct tape_device*); | 156 | void (*process_eov)(struct tape_device*); |
157 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
158 | /* Block device stuff. */ | ||
159 | struct tape_request *(*bread)(struct tape_device *, struct request *); | ||
160 | void (*check_locate)(struct tape_device *, struct tape_request *); | ||
161 | void (*free_bread)(struct tape_request *); | ||
162 | #endif | ||
163 | /* ioctl function for additional ioctls. */ | 157 | /* ioctl function for additional ioctls. */ |
164 | int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long); | 158 | int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long); |
165 | /* Array of tape commands with TAPE_NR_MTOPS entries */ | 159 | /* Array of tape commands with TAPE_NR_MTOPS entries */ |
@@ -182,26 +176,6 @@ struct tape_char_data { | |||
182 | int block_size; /* of size block_size. */ | 176 | int block_size; /* of size block_size. */ |
183 | }; | 177 | }; |
184 | 178 | ||
185 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
186 | /* Block Frontend Data */ | ||
187 | struct tape_blk_data | ||
188 | { | ||
189 | struct tape_device * device; | ||
190 | /* Block device request queue. */ | ||
191 | struct request_queue * request_queue; | ||
192 | spinlock_t request_queue_lock; | ||
193 | |||
194 | /* Task to move entries from block request to CCS request queue. */ | ||
195 | struct work_struct requeue_task; | ||
196 | atomic_t requeue_scheduled; | ||
197 | |||
198 | /* Current position on the tape. */ | ||
199 | long block_position; | ||
200 | int medium_changed; | ||
201 | struct gendisk * disk; | ||
202 | }; | ||
203 | #endif | ||
204 | |||
205 | /* Tape Info */ | 179 | /* Tape Info */ |
206 | struct tape_device { | 180 | struct tape_device { |
207 | /* entry in tape_device_list */ | 181 | /* entry in tape_device_list */ |
@@ -248,10 +222,6 @@ struct tape_device { | |||
248 | 222 | ||
249 | /* Character device frontend data */ | 223 | /* Character device frontend data */ |
250 | struct tape_char_data char_data; | 224 | struct tape_char_data char_data; |
251 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
252 | /* Block dev frontend data */ | ||
253 | struct tape_blk_data blk_data; | ||
254 | #endif | ||
255 | 225 | ||
256 | /* Function to start or stop the next request later. */ | 226 | /* Function to start or stop the next request later. */ |
257 | struct delayed_work tape_dnr; | 227 | struct delayed_work tape_dnr; |
@@ -313,19 +283,6 @@ extern void tapechar_exit(void); | |||
313 | extern int tapechar_setup_device(struct tape_device *); | 283 | extern int tapechar_setup_device(struct tape_device *); |
314 | extern void tapechar_cleanup_device(struct tape_device *); | 284 | extern void tapechar_cleanup_device(struct tape_device *); |
315 | 285 | ||
316 | /* Externals from tape_block.c */ | ||
317 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
318 | extern int tapeblock_init (void); | ||
319 | extern void tapeblock_exit(void); | ||
320 | extern int tapeblock_setup_device(struct tape_device *); | ||
321 | extern void tapeblock_cleanup_device(struct tape_device *); | ||
322 | #else | ||
323 | static inline int tapeblock_init (void) {return 0;} | ||
324 | static inline void tapeblock_exit (void) {;} | ||
325 | static inline int tapeblock_setup_device(struct tape_device *t) {return 0;} | ||
326 | static inline void tapeblock_cleanup_device (struct tape_device *t) {;} | ||
327 | #endif | ||
328 | |||
329 | /* tape initialisation functions */ | 286 | /* tape initialisation functions */ |
330 | #ifdef CONFIG_PROC_FS | 287 | #ifdef CONFIG_PROC_FS |
331 | extern void tape_proc_init (void); | 288 | extern void tape_proc_init (void); |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 934ef33eb9a4..b28de80b7ca4 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -323,20 +323,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
323 | inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0; | 323 | inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0; |
324 | sense = irb->ecw; | 324 | sense = irb->ecw; |
325 | 325 | ||
326 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
327 | if (request->op == TO_BLOCK) { | ||
328 | /* | ||
329 | * Recovery for block device requests. Set the block_position | ||
330 | * to something invalid and retry. | ||
331 | */ | ||
332 | device->blk_data.block_position = -1; | ||
333 | if (request->retries-- <= 0) | ||
334 | return tape_34xx_erp_failed(request, -EIO); | ||
335 | else | ||
336 | return tape_34xx_erp_retry(request); | ||
337 | } | ||
338 | #endif | ||
339 | |||
340 | if ( | 326 | if ( |
341 | sense[0] & SENSE_COMMAND_REJECT && | 327 | sense[0] & SENSE_COMMAND_REJECT && |
342 | sense[1] & SENSE_WRITE_PROTECT | 328 | sense[1] & SENSE_WRITE_PROTECT |
@@ -1129,123 +1115,6 @@ tape_34xx_mtseek(struct tape_device *device, int mt_count) | |||
1129 | return tape_do_io_free(device, request); | 1115 | return tape_do_io_free(device, request); |
1130 | } | 1116 | } |
1131 | 1117 | ||
1132 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
1133 | /* | ||
1134 | * Tape block read for 34xx. | ||
1135 | */ | ||
1136 | static struct tape_request * | ||
1137 | tape_34xx_bread(struct tape_device *device, struct request *req) | ||
1138 | { | ||
1139 | struct tape_request *request; | ||
1140 | struct ccw1 *ccw; | ||
1141 | int count = 0; | ||
1142 | unsigned off; | ||
1143 | char *dst; | ||
1144 | struct bio_vec *bv; | ||
1145 | struct req_iterator iter; | ||
1146 | struct tape_34xx_block_id * start_block; | ||
1147 | |||
1148 | DBF_EVENT(6, "xBREDid:"); | ||
1149 | |||
1150 | /* Count the number of blocks for the request. */ | ||
1151 | rq_for_each_segment(bv, req, iter) | ||
1152 | count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); | ||
1153 | |||
1154 | /* Allocate the ccw request. */ | ||
1155 | request = tape_alloc_request(3+count+1, 8); | ||
1156 | if (IS_ERR(request)) | ||
1157 | return request; | ||
1158 | |||
1159 | /* Setup ccws. */ | ||
1160 | request->op = TO_BLOCK; | ||
1161 | start_block = (struct tape_34xx_block_id *) request->cpdata; | ||
1162 | start_block->block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B; | ||
1163 | DBF_EVENT(6, "start_block = %i\n", start_block->block); | ||
1164 | |||
1165 | ccw = request->cpaddr; | ||
1166 | ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte); | ||
1167 | |||
1168 | /* | ||
1169 | * We always setup a nop after the mode set ccw. This slot is | ||
1170 | * used in tape_std_check_locate to insert a locate ccw if the | ||
1171 | * current tape position doesn't match the start block to be read. | ||
1172 | * The second nop will be filled with a read block id which is in | ||
1173 | * turn used by tape_34xx_free_bread to populate the segment bid | ||
1174 | * table. | ||
1175 | */ | ||
1176 | ccw = tape_ccw_cc(ccw, NOP, 0, NULL); | ||
1177 | ccw = tape_ccw_cc(ccw, NOP, 0, NULL); | ||
1178 | |||
1179 | rq_for_each_segment(bv, req, iter) { | ||
1180 | dst = kmap(bv->bv_page) + bv->bv_offset; | ||
1181 | for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { | ||
1182 | ccw->flags = CCW_FLAG_CC; | ||
1183 | ccw->cmd_code = READ_FORWARD; | ||
1184 | ccw->count = TAPEBLOCK_HSEC_SIZE; | ||
1185 | set_normalized_cda(ccw, (void*) __pa(dst)); | ||
1186 | ccw++; | ||
1187 | dst += TAPEBLOCK_HSEC_SIZE; | ||
1188 | } | ||
1189 | } | ||
1190 | |||
1191 | ccw = tape_ccw_end(ccw, NOP, 0, NULL); | ||
1192 | DBF_EVENT(6, "xBREDccwg\n"); | ||
1193 | return request; | ||
1194 | } | ||
1195 | |||
1196 | static void | ||
1197 | tape_34xx_free_bread (struct tape_request *request) | ||
1198 | { | ||
1199 | struct ccw1* ccw; | ||
1200 | |||
1201 | ccw = request->cpaddr; | ||
1202 | if ((ccw + 2)->cmd_code == READ_BLOCK_ID) { | ||
1203 | struct { | ||
1204 | struct tape_34xx_block_id cbid; | ||
1205 | struct tape_34xx_block_id dbid; | ||
1206 | } __attribute__ ((packed)) *rbi_data; | ||
1207 | |||
1208 | rbi_data = request->cpdata; | ||
1209 | |||
1210 | if (request->device) | ||
1211 | tape_34xx_add_sbid(request->device, rbi_data->cbid); | ||
1212 | } | ||
1213 | |||
1214 | /* Last ccw is a nop and doesn't need clear_normalized_cda */ | ||
1215 | for (; ccw->flags & CCW_FLAG_CC; ccw++) | ||
1216 | if (ccw->cmd_code == READ_FORWARD) | ||
1217 | clear_normalized_cda(ccw); | ||
1218 | tape_free_request(request); | ||
1219 | } | ||
1220 | |||
1221 | /* | ||
1222 | * check_locate is called just before the tape request is passed to | ||
1223 | * the common io layer for execution. It has to check the current | ||
1224 | * tape position and insert a locate ccw if it doesn't match the | ||
1225 | * start block for the request. | ||
1226 | */ | ||
1227 | static void | ||
1228 | tape_34xx_check_locate(struct tape_device *device, struct tape_request *request) | ||
1229 | { | ||
1230 | struct tape_34xx_block_id * start_block; | ||
1231 | |||
1232 | start_block = (struct tape_34xx_block_id *) request->cpdata; | ||
1233 | if (start_block->block == device->blk_data.block_position) | ||
1234 | return; | ||
1235 | |||
1236 | DBF_LH(4, "Block seek(%06d+%06d)\n", start_block->block, device->bof); | ||
1237 | start_block->wrap = 0; | ||
1238 | start_block->segment = 1; | ||
1239 | start_block->format = (*device->modeset_byte & 0x08) ? | ||
1240 | TAPE34XX_FMT_3480_XF : | ||
1241 | TAPE34XX_FMT_3480; | ||
1242 | start_block->block = start_block->block + device->bof; | ||
1243 | tape_34xx_merge_sbid(device, start_block); | ||
1244 | tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata); | ||
1245 | tape_ccw_cc(request->cpaddr + 2, READ_BLOCK_ID, 8, request->cpdata); | ||
1246 | } | ||
1247 | #endif | ||
1248 | |||
1249 | /* | 1118 | /* |
1250 | * List of 3480/3490 magnetic tape commands. | 1119 | * List of 3480/3490 magnetic tape commands. |
1251 | */ | 1120 | */ |
@@ -1295,11 +1164,6 @@ static struct tape_discipline tape_discipline_34xx = { | |||
1295 | .irq = tape_34xx_irq, | 1164 | .irq = tape_34xx_irq, |
1296 | .read_block = tape_std_read_block, | 1165 | .read_block = tape_std_read_block, |
1297 | .write_block = tape_std_write_block, | 1166 | .write_block = tape_std_write_block, |
1298 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
1299 | .bread = tape_34xx_bread, | ||
1300 | .free_bread = tape_34xx_free_bread, | ||
1301 | .check_locate = tape_34xx_check_locate, | ||
1302 | #endif | ||
1303 | .ioctl_fn = tape_34xx_ioctl, | 1167 | .ioctl_fn = tape_34xx_ioctl, |
1304 | .mtop_array = tape_34xx_mtop | 1168 | .mtop_array = tape_34xx_mtop |
1305 | }; | 1169 | }; |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 49c6aab7ad78..a5c6614b0db2 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -670,92 +670,6 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op) | |||
670 | return 0; | 670 | return 0; |
671 | } | 671 | } |
672 | 672 | ||
673 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
674 | /* | ||
675 | * Tape Block READ | ||
676 | */ | ||
677 | static struct tape_request * | ||
678 | tape_3590_bread(struct tape_device *device, struct request *req) | ||
679 | { | ||
680 | struct tape_request *request; | ||
681 | struct ccw1 *ccw; | ||
682 | int count = 0, start_block; | ||
683 | unsigned off; | ||
684 | char *dst; | ||
685 | struct bio_vec *bv; | ||
686 | struct req_iterator iter; | ||
687 | |||
688 | DBF_EVENT(6, "xBREDid:"); | ||
689 | start_block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B; | ||
690 | DBF_EVENT(6, "start_block = %i\n", start_block); | ||
691 | |||
692 | rq_for_each_segment(bv, req, iter) | ||
693 | count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9); | ||
694 | |||
695 | request = tape_alloc_request(2 + count + 1, 4); | ||
696 | if (IS_ERR(request)) | ||
697 | return request; | ||
698 | request->op = TO_BLOCK; | ||
699 | *(__u32 *) request->cpdata = start_block; | ||
700 | ccw = request->cpaddr; | ||
701 | ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte); | ||
702 | |||
703 | /* | ||
704 | * We always setup a nop after the mode set ccw. This slot is | ||
705 | * used in tape_std_check_locate to insert a locate ccw if the | ||
706 | * current tape position doesn't match the start block to be read. | ||
707 | */ | ||
708 | ccw = tape_ccw_cc(ccw, NOP, 0, NULL); | ||
709 | |||
710 | rq_for_each_segment(bv, req, iter) { | ||
711 | dst = page_address(bv->bv_page) + bv->bv_offset; | ||
712 | for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) { | ||
713 | ccw->flags = CCW_FLAG_CC; | ||
714 | ccw->cmd_code = READ_FORWARD; | ||
715 | ccw->count = TAPEBLOCK_HSEC_SIZE; | ||
716 | set_normalized_cda(ccw, (void *) __pa(dst)); | ||
717 | ccw++; | ||
718 | dst += TAPEBLOCK_HSEC_SIZE; | ||
719 | } | ||
720 | BUG_ON(off > bv->bv_len); | ||
721 | } | ||
722 | ccw = tape_ccw_end(ccw, NOP, 0, NULL); | ||
723 | DBF_EVENT(6, "xBREDccwg\n"); | ||
724 | return request; | ||
725 | } | ||
726 | |||
727 | static void | ||
728 | tape_3590_free_bread(struct tape_request *request) | ||
729 | { | ||
730 | struct ccw1 *ccw; | ||
731 | |||
732 | /* Last ccw is a nop and doesn't need clear_normalized_cda */ | ||
733 | for (ccw = request->cpaddr; ccw->flags & CCW_FLAG_CC; ccw++) | ||
734 | if (ccw->cmd_code == READ_FORWARD) | ||
735 | clear_normalized_cda(ccw); | ||
736 | tape_free_request(request); | ||
737 | } | ||
738 | |||
739 | /* | ||
740 | * check_locate is called just before the tape request is passed to | ||
741 | * the common io layer for execution. It has to check the current | ||
742 | * tape position and insert a locate ccw if it doesn't match the | ||
743 | * start block for the request. | ||
744 | */ | ||
745 | static void | ||
746 | tape_3590_check_locate(struct tape_device *device, struct tape_request *request) | ||
747 | { | ||
748 | __u32 *start_block; | ||
749 | |||
750 | start_block = (__u32 *) request->cpdata; | ||
751 | if (*start_block != device->blk_data.block_position) { | ||
752 | /* Add the start offset of the file to get the real block. */ | ||
753 | *start_block += device->bof; | ||
754 | tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata); | ||
755 | } | ||
756 | } | ||
757 | #endif | ||
758 | |||
759 | static void tape_3590_med_state_set(struct tape_device *device, | 673 | static void tape_3590_med_state_set(struct tape_device *device, |
760 | struct tape_3590_med_sense *sense) | 674 | struct tape_3590_med_sense *sense) |
761 | { | 675 | { |
@@ -1423,20 +1337,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1423 | { | 1337 | { |
1424 | struct tape_3590_sense *sense; | 1338 | struct tape_3590_sense *sense; |
1425 | 1339 | ||
1426 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
1427 | if (request->op == TO_BLOCK) { | ||
1428 | /* | ||
1429 | * Recovery for block device requests. Set the block_position | ||
1430 | * to something invalid and retry. | ||
1431 | */ | ||
1432 | device->blk_data.block_position = -1; | ||
1433 | if (request->retries-- <= 0) | ||
1434 | return tape_3590_erp_failed(device, request, irb, -EIO); | ||
1435 | else | ||
1436 | return tape_3590_erp_retry(device, request, irb); | ||
1437 | } | ||
1438 | #endif | ||
1439 | |||
1440 | sense = (struct tape_3590_sense *) irb->ecw; | 1340 | sense = (struct tape_3590_sense *) irb->ecw; |
1441 | 1341 | ||
1442 | DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc); | 1342 | DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc); |
@@ -1729,11 +1629,6 @@ static struct tape_discipline tape_discipline_3590 = { | |||
1729 | .irq = tape_3590_irq, | 1629 | .irq = tape_3590_irq, |
1730 | .read_block = tape_std_read_block, | 1630 | .read_block = tape_std_read_block, |
1731 | .write_block = tape_std_write_block, | 1631 | .write_block = tape_std_write_block, |
1732 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
1733 | .bread = tape_3590_bread, | ||
1734 | .free_bread = tape_3590_free_bread, | ||
1735 | .check_locate = tape_3590_check_locate, | ||
1736 | #endif | ||
1737 | .ioctl_fn = tape_3590_ioctl, | 1632 | .ioctl_fn = tape_3590_ioctl, |
1738 | .mtop_array = tape_3590_mtop | 1633 | .mtop_array = tape_3590_mtop |
1739 | }; | 1634 | }; |
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 87cd0ab242de..46886a7578c6 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c | |||
@@ -161,11 +161,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) | |||
161 | if (rc) | 161 | if (rc) |
162 | return rc; | 162 | return rc; |
163 | 163 | ||
164 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
165 | /* Changes position. */ | ||
166 | device->blk_data.medium_changed = 1; | ||
167 | #endif | ||
168 | |||
169 | DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size); | 164 | DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size); |
170 | /* Let the discipline build the ccw chain. */ | 165 | /* Let the discipline build the ccw chain. */ |
171 | request = device->discipline->read_block(device, block_size); | 166 | request = device->discipline->read_block(device, block_size); |
@@ -218,11 +213,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t | |||
218 | if (rc) | 213 | if (rc) |
219 | return rc; | 214 | return rc; |
220 | 215 | ||
221 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
222 | /* Changes position. */ | ||
223 | device->blk_data.medium_changed = 1; | ||
224 | #endif | ||
225 | |||
226 | DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size); | 216 | DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size); |
227 | DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks); | 217 | DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks); |
228 | /* Let the discipline build the ccw chain. */ | 218 | /* Let the discipline build the ccw chain. */ |
@@ -379,9 +369,6 @@ __tapechar_ioctl(struct tape_device *device, | |||
379 | case MTBSFM: | 369 | case MTBSFM: |
380 | case MTFSFM: | 370 | case MTFSFM: |
381 | case MTSEEK: | 371 | case MTSEEK: |
382 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
383 | device->blk_data.medium_changed = 1; | ||
384 | #endif | ||
385 | if (device->required_tapemarks) | 372 | if (device->required_tapemarks) |
386 | tape_std_terminate_write(device); | 373 | tape_std_terminate_write(device); |
387 | default: | 374 | default: |
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index b3a3e8e8656e..585618663ba4 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -401,9 +401,6 @@ tape_generic_online(struct tape_device *device, | |||
401 | rc = tapechar_setup_device(device); | 401 | rc = tapechar_setup_device(device); |
402 | if (rc) | 402 | if (rc) |
403 | goto out_minor; | 403 | goto out_minor; |
404 | rc = tapeblock_setup_device(device); | ||
405 | if (rc) | ||
406 | goto out_char; | ||
407 | 404 | ||
408 | tape_state_set(device, TS_UNUSED); | 405 | tape_state_set(device, TS_UNUSED); |
409 | 406 | ||
@@ -411,8 +408,6 @@ tape_generic_online(struct tape_device *device, | |||
411 | 408 | ||
412 | return 0; | 409 | return 0; |
413 | 410 | ||
414 | out_char: | ||
415 | tapechar_cleanup_device(device); | ||
416 | out_minor: | 411 | out_minor: |
417 | tape_remove_minor(device); | 412 | tape_remove_minor(device); |
418 | out_discipline: | 413 | out_discipline: |
@@ -426,7 +421,6 @@ out: | |||
426 | static void | 421 | static void |
427 | tape_cleanup_device(struct tape_device *device) | 422 | tape_cleanup_device(struct tape_device *device) |
428 | { | 423 | { |
429 | tapeblock_cleanup_device(device); | ||
430 | tapechar_cleanup_device(device); | 424 | tapechar_cleanup_device(device); |
431 | device->discipline->cleanup_device(device); | 425 | device->discipline->cleanup_device(device); |
432 | module_put(device->discipline->owner); | 426 | module_put(device->discipline->owner); |
@@ -785,10 +779,6 @@ __tape_start_io(struct tape_device *device, struct tape_request *request) | |||
785 | { | 779 | { |
786 | int rc; | 780 | int rc; |
787 | 781 | ||
788 | #ifdef CONFIG_S390_TAPE_BLOCK | ||
789 | if (request->op == TO_BLOCK) | ||
790 | device->discipline->check_locate(device, request); | ||
791 | #endif | ||
792 | rc = ccw_device_start( | 782 | rc = ccw_device_start( |
793 | device->cdev, | 783 | device->cdev, |
794 | request->cpaddr, | 784 | request->cpaddr, |
@@ -1253,7 +1243,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1253 | } | 1243 | } |
1254 | 1244 | ||
1255 | /* | 1245 | /* |
1256 | * Tape device open function used by tape_char & tape_block frontends. | 1246 | * Tape device open function used by tape_char frontend. |
1257 | */ | 1247 | */ |
1258 | int | 1248 | int |
1259 | tape_open(struct tape_device *device) | 1249 | tape_open(struct tape_device *device) |
@@ -1283,7 +1273,7 @@ tape_open(struct tape_device *device) | |||
1283 | } | 1273 | } |
1284 | 1274 | ||
1285 | /* | 1275 | /* |
1286 | * Tape device release function used by tape_char & tape_block frontends. | 1276 | * Tape device release function used by tape_char frontend. |
1287 | */ | 1277 | */ |
1288 | int | 1278 | int |
1289 | tape_release(struct tape_device *device) | 1279 | tape_release(struct tape_device *device) |
@@ -1344,7 +1334,6 @@ tape_init (void) | |||
1344 | DBF_EVENT(3, "tape init\n"); | 1334 | DBF_EVENT(3, "tape init\n"); |
1345 | tape_proc_init(); | 1335 | tape_proc_init(); |
1346 | tapechar_init (); | 1336 | tapechar_init (); |
1347 | tapeblock_init (); | ||
1348 | return 0; | 1337 | return 0; |
1349 | } | 1338 | } |
1350 | 1339 | ||
@@ -1358,7 +1347,6 @@ tape_exit(void) | |||
1358 | 1347 | ||
1359 | /* Get rid of the frontends */ | 1348 | /* Get rid of the frontends */ |
1360 | tapechar_exit(); | 1349 | tapechar_exit(); |
1361 | tapeblock_exit(); | ||
1362 | tape_proc_cleanup(); | 1350 | tape_proc_cleanup(); |
1363 | debug_unregister (TAPE_DBF_AREA); | 1351 | debug_unregister (TAPE_DBF_AREA); |
1364 | } | 1352 | } |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5f1dc6fb5708..731470e68493 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * bus driver for ccwgroup | 2 | * bus driver for ccwgroup |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2002, 2009 | 4 | * Copyright IBM Corp. 2002, 2012 |
5 | * | 5 | * |
6 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) | 6 | * Author(s): Arnd Bergmann (arndb@de.ibm.com) |
7 | * Cornelia Huck (cornelia.huck@de.ibm.com) | 7 | * Cornelia Huck (cornelia.huck@de.ibm.com) |
@@ -15,10 +15,13 @@ | |||
15 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
16 | #include <linux/dcache.h> | 16 | #include <linux/dcache.h> |
17 | 17 | ||
18 | #include <asm/cio.h> | ||
18 | #include <asm/ccwdev.h> | 19 | #include <asm/ccwdev.h> |
19 | #include <asm/ccwgroup.h> | 20 | #include <asm/ccwgroup.h> |
20 | 21 | ||
21 | #define CCW_BUS_ID_SIZE 20 | 22 | #include "device.h" |
23 | |||
24 | #define CCW_BUS_ID_SIZE 10 | ||
22 | 25 | ||
23 | /* In Linux 2.4, we had a channel device layer called "chandev" | 26 | /* In Linux 2.4, we had a channel device layer called "chandev" |
24 | * that did all sorts of obscure stuff for networking devices. | 27 | * that did all sorts of obscure stuff for networking devices. |
@@ -27,19 +30,6 @@ | |||
27 | * to devices that use multiple subchannels. | 30 | * to devices that use multiple subchannels. |
28 | */ | 31 | */ |
29 | 32 | ||
30 | /* a device matches a driver if all its slave devices match the same | ||
31 | * entry of the driver */ | ||
32 | static int ccwgroup_bus_match(struct device *dev, struct device_driver * drv) | ||
33 | { | ||
34 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | ||
35 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(drv); | ||
36 | |||
37 | if (gdev->creator_id == gdrv->driver_id) | ||
38 | return 1; | ||
39 | |||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static struct bus_type ccwgroup_bus_type; | 33 | static struct bus_type ccwgroup_bus_type; |
44 | 34 | ||
45 | static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) | 35 | static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) |
@@ -254,9 +244,10 @@ static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) | |||
254 | return 0; | 244 | return 0; |
255 | } | 245 | } |
256 | 246 | ||
257 | static int __get_next_bus_id(const char **buf, char *bus_id) | 247 | static int __get_next_id(const char **buf, struct ccw_dev_id *id) |
258 | { | 248 | { |
259 | int rc, len; | 249 | unsigned int cssid, ssid, devno; |
250 | int ret = 0, len; | ||
260 | char *start, *end; | 251 | char *start, *end; |
261 | 252 | ||
262 | start = (char *)*buf; | 253 | start = (char *)*buf; |
@@ -271,49 +262,40 @@ static int __get_next_bus_id(const char **buf, char *bus_id) | |||
271 | len = end - start + 1; | 262 | len = end - start + 1; |
272 | end++; | 263 | end++; |
273 | } | 264 | } |
274 | if (len < CCW_BUS_ID_SIZE) { | 265 | if (len <= CCW_BUS_ID_SIZE) { |
275 | strlcpy(bus_id, start, len); | 266 | if (sscanf(start, "%2x.%1x.%04x", &cssid, &ssid, &devno) != 3) |
276 | rc = 0; | 267 | ret = -EINVAL; |
277 | } else | 268 | } else |
278 | rc = -EINVAL; | 269 | ret = -EINVAL; |
279 | *buf = end; | ||
280 | return rc; | ||
281 | } | ||
282 | |||
283 | static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE]) | ||
284 | { | ||
285 | int cssid, ssid, devno; | ||
286 | 270 | ||
287 | /* Must be of form %x.%x.%04x */ | 271 | if (!ret) { |
288 | if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3) | 272 | id->ssid = ssid; |
289 | return 0; | 273 | id->devno = devno; |
290 | return 1; | 274 | } |
275 | *buf = end; | ||
276 | return ret; | ||
291 | } | 277 | } |
292 | 278 | ||
293 | /** | 279 | /** |
294 | * ccwgroup_create_from_string() - create and register a ccw group device | 280 | * ccwgroup_create_dev() - create and register a ccw group device |
295 | * @root: parent device for the new device | 281 | * @parent: parent device for the new device |
296 | * @creator_id: identifier of creating driver | 282 | * @gdrv: driver for the new group device |
297 | * @cdrv: ccw driver of slave devices | ||
298 | * @num_devices: number of slave devices | 283 | * @num_devices: number of slave devices |
299 | * @buf: buffer containing comma separated bus ids of slave devices | 284 | * @buf: buffer containing comma separated bus ids of slave devices |
300 | * | 285 | * |
301 | * Create and register a new ccw group device as a child of @root. Slave | 286 | * Create and register a new ccw group device as a child of @parent. Slave |
302 | * devices are obtained from the list of bus ids given in @buf and must all | 287 | * devices are obtained from the list of bus ids given in @buf. |
303 | * belong to @cdrv. | ||
304 | * Returns: | 288 | * Returns: |
305 | * %0 on success and an error code on failure. | 289 | * %0 on success and an error code on failure. |
306 | * Context: | 290 | * Context: |
307 | * non-atomic | 291 | * non-atomic |
308 | */ | 292 | */ |
309 | int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | 293 | int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, |
310 | struct ccw_driver *cdrv, int num_devices, | 294 | int num_devices, const char *buf) |
311 | const char *buf) | ||
312 | { | 295 | { |
313 | struct ccwgroup_device *gdev; | 296 | struct ccwgroup_device *gdev; |
297 | struct ccw_dev_id dev_id; | ||
314 | int rc, i; | 298 | int rc, i; |
315 | char tmp_bus_id[CCW_BUS_ID_SIZE]; | ||
316 | const char *curr_buf; | ||
317 | 299 | ||
318 | gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), | 300 | gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), |
319 | GFP_KERNEL); | 301 | GFP_KERNEL); |
@@ -323,29 +305,24 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
323 | atomic_set(&gdev->onoff, 0); | 305 | atomic_set(&gdev->onoff, 0); |
324 | mutex_init(&gdev->reg_mutex); | 306 | mutex_init(&gdev->reg_mutex); |
325 | mutex_lock(&gdev->reg_mutex); | 307 | mutex_lock(&gdev->reg_mutex); |
326 | gdev->creator_id = creator_id; | ||
327 | gdev->count = num_devices; | 308 | gdev->count = num_devices; |
328 | gdev->dev.bus = &ccwgroup_bus_type; | 309 | gdev->dev.bus = &ccwgroup_bus_type; |
329 | gdev->dev.parent = root; | 310 | gdev->dev.parent = parent; |
330 | gdev->dev.release = ccwgroup_release; | 311 | gdev->dev.release = ccwgroup_release; |
331 | device_initialize(&gdev->dev); | 312 | device_initialize(&gdev->dev); |
332 | 313 | ||
333 | curr_buf = buf; | 314 | for (i = 0; i < num_devices && buf; i++) { |
334 | for (i = 0; i < num_devices && curr_buf; i++) { | 315 | rc = __get_next_id(&buf, &dev_id); |
335 | rc = __get_next_bus_id(&curr_buf, tmp_bus_id); | ||
336 | if (rc != 0) | 316 | if (rc != 0) |
337 | goto error; | 317 | goto error; |
338 | if (!__is_valid_bus_id(tmp_bus_id)) { | 318 | gdev->cdev[i] = get_ccwdev_by_dev_id(&dev_id); |
339 | rc = -EINVAL; | ||
340 | goto error; | ||
341 | } | ||
342 | gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id); | ||
343 | /* | 319 | /* |
344 | * All devices have to be of the same type in | 320 | * All devices have to be of the same type in |
345 | * order to be grouped. | 321 | * order to be grouped. |
346 | */ | 322 | */ |
347 | if (!gdev->cdev[i] | 323 | if (!gdev->cdev[i] || !gdev->cdev[i]->drv || |
348 | || gdev->cdev[i]->id.driver_info != | 324 | gdev->cdev[i]->drv != gdev->cdev[0]->drv || |
325 | gdev->cdev[i]->id.driver_info != | ||
349 | gdev->cdev[0]->id.driver_info) { | 326 | gdev->cdev[0]->id.driver_info) { |
350 | rc = -EINVAL; | 327 | rc = -EINVAL; |
351 | goto error; | 328 | goto error; |
@@ -361,18 +338,25 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
361 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | 338 | spin_unlock_irq(gdev->cdev[i]->ccwlock); |
362 | } | 339 | } |
363 | /* Check for sufficient number of bus ids. */ | 340 | /* Check for sufficient number of bus ids. */ |
364 | if (i < num_devices && !curr_buf) { | 341 | if (i < num_devices) { |
365 | rc = -EINVAL; | 342 | rc = -EINVAL; |
366 | goto error; | 343 | goto error; |
367 | } | 344 | } |
368 | /* Check for trailing stuff. */ | 345 | /* Check for trailing stuff. */ |
369 | if (i == num_devices && strlen(curr_buf) > 0) { | 346 | if (i == num_devices && strlen(buf) > 0) { |
370 | rc = -EINVAL; | 347 | rc = -EINVAL; |
371 | goto error; | 348 | goto error; |
372 | } | 349 | } |
373 | 350 | ||
374 | dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); | 351 | dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); |
375 | gdev->dev.groups = ccwgroup_attr_groups; | 352 | gdev->dev.groups = ccwgroup_attr_groups; |
353 | |||
354 | if (gdrv) { | ||
355 | gdev->dev.driver = &gdrv->driver; | ||
356 | rc = gdrv->setup ? gdrv->setup(gdev) : 0; | ||
357 | if (rc) | ||
358 | goto error; | ||
359 | } | ||
376 | rc = device_add(&gdev->dev); | 360 | rc = device_add(&gdev->dev); |
377 | if (rc) | 361 | if (rc) |
378 | goto error; | 362 | goto error; |
@@ -397,7 +381,7 @@ error: | |||
397 | put_device(&gdev->dev); | 381 | put_device(&gdev->dev); |
398 | return rc; | 382 | return rc; |
399 | } | 383 | } |
400 | EXPORT_SYMBOL(ccwgroup_create_from_string); | 384 | EXPORT_SYMBOL(ccwgroup_create_dev); |
401 | 385 | ||
402 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | 386 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, |
403 | void *data) | 387 | void *data) |
@@ -440,14 +424,6 @@ module_exit(cleanup_ccwgroup); | |||
440 | 424 | ||
441 | /************************** driver stuff ******************************/ | 425 | /************************** driver stuff ******************************/ |
442 | 426 | ||
443 | static int ccwgroup_probe(struct device *dev) | ||
444 | { | ||
445 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | ||
446 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); | ||
447 | |||
448 | return gdrv->probe ? gdrv->probe(gdev) : -ENODEV; | ||
449 | } | ||
450 | |||
451 | static int ccwgroup_remove(struct device *dev) | 427 | static int ccwgroup_remove(struct device *dev) |
452 | { | 428 | { |
453 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 429 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
@@ -542,8 +518,6 @@ static const struct dev_pm_ops ccwgroup_pm_ops = { | |||
542 | 518 | ||
543 | static struct bus_type ccwgroup_bus_type = { | 519 | static struct bus_type ccwgroup_bus_type = { |
544 | .name = "ccwgroup", | 520 | .name = "ccwgroup", |
545 | .match = ccwgroup_bus_match, | ||
546 | .probe = ccwgroup_probe, | ||
547 | .remove = ccwgroup_remove, | 521 | .remove = ccwgroup_remove, |
548 | .shutdown = ccwgroup_shutdown, | 522 | .shutdown = ccwgroup_shutdown, |
549 | .pm = &ccwgroup_pm_ops, | 523 | .pm = &ccwgroup_pm_ops, |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index a49c46c91983..a6ddaed8793d 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -656,51 +656,34 @@ static struct io_subchannel_private console_priv; | |||
656 | static int console_subchannel_in_use; | 656 | static int console_subchannel_in_use; |
657 | 657 | ||
658 | /* | 658 | /* |
659 | * Use cio_tpi to get a pending interrupt and call the interrupt handler. | 659 | * Use cio_tsch to update the subchannel status and call the interrupt handler |
660 | * Return non-zero if an interrupt was processed, zero otherwise. | 660 | * if status had been pending. Called with the console_subchannel lock. |
661 | */ | 661 | */ |
662 | static int cio_tpi(void) | 662 | static void cio_tsch(struct subchannel *sch) |
663 | { | 663 | { |
664 | struct tpi_info *tpi_info; | ||
665 | struct subchannel *sch; | ||
666 | struct irb *irb; | 664 | struct irb *irb; |
667 | int irq_context; | 665 | int irq_context; |
668 | 666 | ||
669 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; | ||
670 | if (tpi(NULL) != 1) | ||
671 | return 0; | ||
672 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; | ||
673 | if (tpi_info->adapter_IO) { | ||
674 | do_adapter_IO(tpi_info->isc); | ||
675 | return 1; | ||
676 | } | ||
677 | irb = (struct irb *)&S390_lowcore.irb; | 667 | irb = (struct irb *)&S390_lowcore.irb; |
678 | /* Store interrupt response block to lowcore. */ | 668 | /* Store interrupt response block to lowcore. */ |
679 | if (tsch(tpi_info->schid, irb) != 0) { | 669 | if (tsch(sch->schid, irb) != 0) |
680 | /* Not status pending or not operational. */ | 670 | /* Not status pending or not operational. */ |
681 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 671 | return; |
682 | return 1; | 672 | memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); |
683 | } | 673 | /* Call interrupt handler with updated status. */ |
684 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; | ||
685 | if (!sch) { | ||
686 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | ||
687 | return 1; | ||
688 | } | ||
689 | irq_context = in_interrupt(); | 674 | irq_context = in_interrupt(); |
690 | if (!irq_context) | 675 | if (!irq_context) { |
691 | local_bh_disable(); | 676 | local_bh_disable(); |
692 | irq_enter(); | 677 | irq_enter(); |
693 | spin_lock(sch->lock); | 678 | } |
694 | memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); | ||
695 | if (sch->driver && sch->driver->irq) | 679 | if (sch->driver && sch->driver->irq) |
696 | sch->driver->irq(sch); | 680 | sch->driver->irq(sch); |
697 | else | 681 | else |
698 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 682 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; |
699 | spin_unlock(sch->lock); | 683 | if (!irq_context) { |
700 | irq_exit(); | 684 | irq_exit(); |
701 | if (!irq_context) | ||
702 | _local_bh_enable(); | 685 | _local_bh_enable(); |
703 | return 1; | 686 | } |
704 | } | 687 | } |
705 | 688 | ||
706 | void *cio_get_console_priv(void) | 689 | void *cio_get_console_priv(void) |
@@ -712,34 +695,16 @@ void *cio_get_console_priv(void) | |||
712 | * busy wait for the next interrupt on the console | 695 | * busy wait for the next interrupt on the console |
713 | */ | 696 | */ |
714 | void wait_cons_dev(void) | 697 | void wait_cons_dev(void) |
715 | __releases(console_subchannel.lock) | ||
716 | __acquires(console_subchannel.lock) | ||
717 | { | 698 | { |
718 | unsigned long cr6 __attribute__ ((aligned (8))); | ||
719 | unsigned long save_cr6 __attribute__ ((aligned (8))); | ||
720 | |||
721 | /* | ||
722 | * before entering the spinlock we may already have | ||
723 | * processed the interrupt on a different CPU... | ||
724 | */ | ||
725 | if (!console_subchannel_in_use) | 699 | if (!console_subchannel_in_use) |
726 | return; | 700 | return; |
727 | 701 | ||
728 | /* disable all but the console isc */ | 702 | while (1) { |
729 | __ctl_store (save_cr6, 6, 6); | 703 | cio_tsch(&console_subchannel); |
730 | cr6 = 1UL << (31 - CONSOLE_ISC); | 704 | if (console_subchannel.schib.scsw.cmd.actl == 0) |
731 | __ctl_load (cr6, 6, 6); | 705 | break; |
732 | 706 | udelay_simple(100); | |
733 | do { | 707 | } |
734 | spin_unlock(console_subchannel.lock); | ||
735 | if (!cio_tpi()) | ||
736 | cpu_relax(); | ||
737 | spin_lock(console_subchannel.lock); | ||
738 | } while (console_subchannel.schib.scsw.cmd.actl != 0); | ||
739 | /* | ||
740 | * restore previous isc value | ||
741 | */ | ||
742 | __ctl_load (save_cr6, 6, 6); | ||
743 | } | 708 | } |
744 | 709 | ||
745 | static int | 710 | static int |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 02d015259461..f8f952d52045 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -695,7 +695,17 @@ static int match_dev_id(struct device *dev, void *data) | |||
695 | return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id); | 695 | return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id); |
696 | } | 696 | } |
697 | 697 | ||
698 | static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id) | 698 | /** |
699 | * get_ccwdev_by_dev_id() - obtain device from a ccw device id | ||
700 | * @dev_id: id of the device to be searched | ||
701 | * | ||
702 | * This function searches all devices attached to the ccw bus for a device | ||
703 | * matching @dev_id. | ||
704 | * Returns: | ||
705 | * If a device is found its reference count is increased and returned; | ||
706 | * else %NULL is returned. | ||
707 | */ | ||
708 | struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id) | ||
699 | { | 709 | { |
700 | struct device *dev; | 710 | struct device *dev; |
701 | 711 | ||
@@ -703,6 +713,7 @@ static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id) | |||
703 | 713 | ||
704 | return dev ? to_ccwdev(dev) : NULL; | 714 | return dev ? to_ccwdev(dev) : NULL; |
705 | } | 715 | } |
716 | EXPORT_SYMBOL_GPL(get_ccwdev_by_dev_id); | ||
706 | 717 | ||
707 | static void ccw_device_do_unbind_bind(struct ccw_device *cdev) | 718 | static void ccw_device_do_unbind_bind(struct ccw_device *cdev) |
708 | { | 719 | { |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 179824b3082f..6bace6942396 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -101,6 +101,7 @@ int ccw_device_test_sense_data(struct ccw_device *); | |||
101 | void ccw_device_schedule_sch_unregister(struct ccw_device *); | 101 | void ccw_device_schedule_sch_unregister(struct ccw_device *); |
102 | int ccw_purge_blacklisted(void); | 102 | int ccw_purge_blacklisted(void); |
103 | void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo); | 103 | void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo); |
104 | struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id); | ||
104 | 105 | ||
105 | /* Function prototypes for device status and basic sense stuff. */ | 106 | /* Function prototypes for device status and basic sense stuff. */ |
106 | void ccw_device_accumulate_irb(struct ccw_device *, struct irb *); | 107 | void ccw_device_accumulate_irb(struct ccw_device *, struct irb *); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 35c685c374e9..7493efafa0d5 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -63,7 +63,7 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask, | |||
63 | " ipm %0\n" | 63 | " ipm %0\n" |
64 | " srl %0,28\n" | 64 | " srl %0,28\n" |
65 | : "=d" (cc) | 65 | : "=d" (cc) |
66 | : "d" (__fc), "d" (__schid), "d" (__mask) : "cc", "memory"); | 66 | : "d" (__fc), "d" (__schid), "d" (__mask) : "cc"); |
67 | return cc; | 67 | return cc; |
68 | } | 68 | } |
69 | 69 | ||
@@ -74,7 +74,7 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask, | |||
74 | * @bb: busy bit indicator, set only if SIGA-w/wt could not access a buffer | 74 | * @bb: busy bit indicator, set only if SIGA-w/wt could not access a buffer |
75 | * @fc: function code to perform | 75 | * @fc: function code to perform |
76 | * | 76 | * |
77 | * Returns cc or QDIO_ERROR_SIGA_ACCESS_EXCEPTION. | 77 | * Returns condition code. |
78 | * Note: For IQDC unicast queues only the highest priority queue is processed. | 78 | * Note: For IQDC unicast queues only the highest priority queue is processed. |
79 | */ | 79 | */ |
80 | static inline int do_siga_output(unsigned long schid, unsigned long mask, | 80 | static inline int do_siga_output(unsigned long schid, unsigned long mask, |
@@ -85,18 +85,16 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask, | |||
85 | register unsigned long __schid asm("1") = schid; | 85 | register unsigned long __schid asm("1") = schid; |
86 | register unsigned long __mask asm("2") = mask; | 86 | register unsigned long __mask asm("2") = mask; |
87 | register unsigned long __aob asm("3") = aob; | 87 | register unsigned long __aob asm("3") = aob; |
88 | int cc = QDIO_ERROR_SIGA_ACCESS_EXCEPTION; | 88 | int cc; |
89 | 89 | ||
90 | asm volatile( | 90 | asm volatile( |
91 | " siga 0\n" | 91 | " siga 0\n" |
92 | "0: ipm %0\n" | 92 | " ipm %0\n" |
93 | " srl %0,28\n" | 93 | " srl %0,28\n" |
94 | "1:\n" | 94 | : "=d" (cc), "+d" (__fc), "+d" (__aob) |
95 | EX_TABLE(0b, 1b) | 95 | : "d" (__schid), "d" (__mask) |
96 | : "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask), | 96 | : "cc"); |
97 | "+d" (__aob) | 97 | *bb = __fc >> 31; |
98 | : : "cc", "memory"); | ||
99 | *bb = ((unsigned int) __fc) >> 31; | ||
100 | return cc; | 98 | return cc; |
101 | } | 99 | } |
102 | 100 | ||
@@ -167,7 +165,7 @@ again: | |||
167 | 165 | ||
168 | DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); | 166 | DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); |
169 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); | 167 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); |
170 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 168 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_GET_BUF_STATE, |
171 | q->nr, q->first_to_kick, count, q->irq_ptr->int_parm); | 169 | q->nr, q->first_to_kick, count, q->irq_ptr->int_parm); |
172 | return 0; | 170 | return 0; |
173 | } | 171 | } |
@@ -215,7 +213,7 @@ again: | |||
215 | 213 | ||
216 | DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); | 214 | DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); |
217 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); | 215 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); |
218 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 216 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_SET_BUF_STATE, |
219 | q->nr, q->first_to_kick, count, q->irq_ptr->int_parm); | 217 | q->nr, q->first_to_kick, count, q->irq_ptr->int_parm); |
220 | return 0; | 218 | return 0; |
221 | } | 219 | } |
@@ -313,7 +311,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output, | |||
313 | cc = do_siga_sync(schid, output, input, fc); | 311 | cc = do_siga_sync(schid, output, input, fc); |
314 | if (unlikely(cc)) | 312 | if (unlikely(cc)) |
315 | DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc); | 313 | DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc); |
316 | return cc; | 314 | return (cc) ? -EIO : 0; |
317 | } | 315 | } |
318 | 316 | ||
319 | static inline int qdio_siga_sync_q(struct qdio_q *q) | 317 | static inline int qdio_siga_sync_q(struct qdio_q *q) |
@@ -384,7 +382,7 @@ static inline int qdio_siga_input(struct qdio_q *q) | |||
384 | cc = do_siga_input(schid, q->mask, fc); | 382 | cc = do_siga_input(schid, q->mask, fc); |
385 | if (unlikely(cc)) | 383 | if (unlikely(cc)) |
386 | DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc); | 384 | DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc); |
387 | return cc; | 385 | return (cc) ? -EIO : 0; |
388 | } | 386 | } |
389 | 387 | ||
390 | #define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0) | 388 | #define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0) |
@@ -443,7 +441,7 @@ static void process_buffer_error(struct qdio_q *q, int count) | |||
443 | unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT : | 441 | unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT : |
444 | SLSB_P_OUTPUT_NOT_INIT; | 442 | SLSB_P_OUTPUT_NOT_INIT; |
445 | 443 | ||
446 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; | 444 | q->qdio_error = QDIO_ERROR_SLSB_STATE; |
447 | 445 | ||
448 | /* special handling for no target buffer empty */ | 446 | /* special handling for no target buffer empty */ |
449 | if ((!q->is_input_q && | 447 | if ((!q->is_input_q && |
@@ -519,7 +517,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
519 | int count, stop; | 517 | int count, stop; |
520 | unsigned char state = 0; | 518 | unsigned char state = 0; |
521 | 519 | ||
522 | q->timestamp = get_clock_fast(); | 520 | q->timestamp = get_clock(); |
523 | 521 | ||
524 | /* | 522 | /* |
525 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 523 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
@@ -575,7 +573,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) | |||
575 | 573 | ||
576 | bufnr = get_inbound_buffer_frontier(q); | 574 | bufnr = get_inbound_buffer_frontier(q); |
577 | 575 | ||
578 | if ((bufnr != q->last_move) || q->qdio_error) { | 576 | if (bufnr != q->last_move) { |
579 | q->last_move = bufnr; | 577 | q->last_move = bufnr; |
580 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) | 578 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) |
581 | q->u.in.timestamp = get_clock(); | 579 | q->u.in.timestamp = get_clock(); |
@@ -790,7 +788,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
790 | int count, stop; | 788 | int count, stop; |
791 | unsigned char state = 0; | 789 | unsigned char state = 0; |
792 | 790 | ||
793 | q->timestamp = get_clock_fast(); | 791 | q->timestamp = get_clock(); |
794 | 792 | ||
795 | if (need_siga_sync(q)) | 793 | if (need_siga_sync(q)) |
796 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && | 794 | if (((queue_type(q) != QDIO_IQDIO_QFMT) && |
@@ -863,7 +861,7 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q) | |||
863 | 861 | ||
864 | bufnr = get_outbound_buffer_frontier(q); | 862 | bufnr = get_outbound_buffer_frontier(q); |
865 | 863 | ||
866 | if ((bufnr != q->last_move) || q->qdio_error) { | 864 | if (bufnr != q->last_move) { |
867 | q->last_move = bufnr; | 865 | q->last_move = bufnr; |
868 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); | 866 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); |
869 | return 1; | 867 | return 1; |
@@ -894,13 +892,16 @@ retry: | |||
894 | goto retry; | 892 | goto retry; |
895 | } | 893 | } |
896 | DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr); | 894 | DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr); |
897 | cc |= QDIO_ERROR_SIGA_BUSY; | 895 | cc = -EBUSY; |
898 | } else | 896 | } else { |
899 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr); | 897 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr); |
898 | cc = -ENOBUFS; | ||
899 | } | ||
900 | break; | 900 | break; |
901 | case 1: | 901 | case 1: |
902 | case 3: | 902 | case 3: |
903 | DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc); | 903 | DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc); |
904 | cc = -EIO; | ||
904 | break; | 905 | break; |
905 | } | 906 | } |
906 | if (retries) { | 907 | if (retries) { |
@@ -1090,7 +1091,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev, | |||
1090 | } | 1091 | } |
1091 | 1092 | ||
1092 | count = sub_buf(q->first_to_check, q->first_to_kick); | 1093 | count = sub_buf(q->first_to_check, q->first_to_kick); |
1093 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 1094 | q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE, |
1094 | q->nr, q->first_to_kick, count, irq_ptr->int_parm); | 1095 | q->nr, q->first_to_kick, count, irq_ptr->int_parm); |
1095 | no_handler: | 1096 | no_handler: |
1096 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | 1097 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); |
@@ -1691,7 +1692,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1691 | "do%02x b:%02x c:%02x", callflags, bufnr, count); | 1692 | "do%02x b:%02x c:%02x", callflags, bufnr, count); |
1692 | 1693 | ||
1693 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) | 1694 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) |
1694 | return -EBUSY; | 1695 | return -EIO; |
1695 | if (!count) | 1696 | if (!count) |
1696 | return 0; | 1697 | return 0; |
1697 | if (callflags & QDIO_FLAG_SYNC_INPUT) | 1698 | if (callflags & QDIO_FLAG_SYNC_INPUT) |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 7e9a72eb2fe0..b987d4619586 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -215,7 +215,7 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind) | |||
215 | register struct ap_queue_status reg1_out asm ("1"); | 215 | register struct ap_queue_status reg1_out asm ("1"); |
216 | register void *reg2 asm ("2") = ind; | 216 | register void *reg2 asm ("2") = ind; |
217 | asm volatile( | 217 | asm volatile( |
218 | ".long 0xb2af0000" /* PQAP(RAPQ) */ | 218 | ".long 0xb2af0000" /* PQAP(AQIC) */ |
219 | : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2) | 219 | : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2) |
220 | : | 220 | : |
221 | : "cc" ); | 221 | : "cc" ); |
@@ -232,7 +232,7 @@ __ap_query_functions(ap_qid_t qid, unsigned int *functions) | |||
232 | register unsigned long reg2 asm ("2"); | 232 | register unsigned long reg2 asm ("2"); |
233 | 233 | ||
234 | asm volatile( | 234 | asm volatile( |
235 | ".long 0xb2af0000\n" | 235 | ".long 0xb2af0000\n" /* PQAP(TAPQ) */ |
236 | "0:\n" | 236 | "0:\n" |
237 | EX_TABLE(0b, 0b) | 237 | EX_TABLE(0b, 0b) |
238 | : "+d" (reg0), "+d" (reg1), "=d" (reg2) | 238 | : "+d" (reg0), "+d" (reg1), "=d" (reg2) |
@@ -391,7 +391,7 @@ __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length, | |||
391 | reg0 |= 0x400000UL; | 391 | reg0 |= 0x400000UL; |
392 | 392 | ||
393 | asm volatile ( | 393 | asm volatile ( |
394 | "0: .long 0xb2ad0042\n" /* DQAP */ | 394 | "0: .long 0xb2ad0042\n" /* NQAP */ |
395 | " brc 2,0b" | 395 | " brc 2,0b" |
396 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) | 396 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) |
397 | : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg) | 397 | : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg) |
@@ -450,7 +450,7 @@ __ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) | |||
450 | 450 | ||
451 | 451 | ||
452 | asm volatile( | 452 | asm volatile( |
453 | "0: .long 0xb2ae0064\n" | 453 | "0: .long 0xb2ae0064\n" /* DQAP */ |
454 | " brc 6,0b\n" | 454 | " brc 6,0b\n" |
455 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), | 455 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), |
456 | "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7), | 456 | "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7), |
@@ -836,12 +836,12 @@ static void __ap_flush_queue(struct ap_device *ap_dev) | |||
836 | list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) { | 836 | list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) { |
837 | list_del_init(&ap_msg->list); | 837 | list_del_init(&ap_msg->list); |
838 | ap_dev->pendingq_count--; | 838 | ap_dev->pendingq_count--; |
839 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 839 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
840 | } | 840 | } |
841 | list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) { | 841 | list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) { |
842 | list_del_init(&ap_msg->list); | 842 | list_del_init(&ap_msg->list); |
843 | ap_dev->requestq_count--; | 843 | ap_dev->requestq_count--; |
844 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 844 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
845 | } | 845 | } |
846 | } | 846 | } |
847 | 847 | ||
@@ -1329,7 +1329,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) | |||
1329 | continue; | 1329 | continue; |
1330 | list_del_init(&ap_msg->list); | 1330 | list_del_init(&ap_msg->list); |
1331 | ap_dev->pendingq_count--; | 1331 | ap_dev->pendingq_count--; |
1332 | ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply); | 1332 | ap_msg->receive(ap_dev, ap_msg, ap_dev->reply); |
1333 | break; | 1333 | break; |
1334 | } | 1334 | } |
1335 | if (ap_dev->queue_count > 0) | 1335 | if (ap_dev->queue_count > 0) |
@@ -1450,10 +1450,10 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms | |||
1450 | return -EBUSY; | 1450 | return -EBUSY; |
1451 | case AP_RESPONSE_REQ_FAC_NOT_INST: | 1451 | case AP_RESPONSE_REQ_FAC_NOT_INST: |
1452 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 1452 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
1453 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); | 1453 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); |
1454 | return -EINVAL; | 1454 | return -EINVAL; |
1455 | default: /* Device is gone. */ | 1455 | default: /* Device is gone. */ |
1456 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 1456 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
1457 | return -ENODEV; | 1457 | return -ENODEV; |
1458 | } | 1458 | } |
1459 | } else { | 1459 | } else { |
@@ -1471,6 +1471,10 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) | |||
1471 | unsigned long flags; | 1471 | unsigned long flags; |
1472 | int rc; | 1472 | int rc; |
1473 | 1473 | ||
1474 | /* For asynchronous message handling a valid receive-callback | ||
1475 | * is required. */ | ||
1476 | BUG_ON(!ap_msg->receive); | ||
1477 | |||
1474 | spin_lock_bh(&ap_dev->lock); | 1478 | spin_lock_bh(&ap_dev->lock); |
1475 | if (!ap_dev->unregistered) { | 1479 | if (!ap_dev->unregistered) { |
1476 | /* Make room on the queue by polling for finished requests. */ | 1480 | /* Make room on the queue by polling for finished requests. */ |
@@ -1482,7 +1486,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) | |||
1482 | if (rc == -ENODEV) | 1486 | if (rc == -ENODEV) |
1483 | ap_dev->unregistered = 1; | 1487 | ap_dev->unregistered = 1; |
1484 | } else { | 1488 | } else { |
1485 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 1489 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
1486 | rc = -ENODEV; | 1490 | rc = -ENODEV; |
1487 | } | 1491 | } |
1488 | spin_unlock_bh(&ap_dev->lock); | 1492 | spin_unlock_bh(&ap_dev->lock); |
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index d960a6309eec..726fc65809d8 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
@@ -136,9 +136,6 @@ struct ap_driver { | |||
136 | 136 | ||
137 | int (*probe)(struct ap_device *); | 137 | int (*probe)(struct ap_device *); |
138 | void (*remove)(struct ap_device *); | 138 | void (*remove)(struct ap_device *); |
139 | /* receive is called from tasklet context */ | ||
140 | void (*receive)(struct ap_device *, struct ap_message *, | ||
141 | struct ap_message *); | ||
142 | int request_timeout; /* request timeout in jiffies */ | 139 | int request_timeout; /* request timeout in jiffies */ |
143 | }; | 140 | }; |
144 | 141 | ||
@@ -183,6 +180,9 @@ struct ap_message { | |||
183 | 180 | ||
184 | void *private; /* ap driver private pointer. */ | 181 | void *private; /* ap driver private pointer. */ |
185 | unsigned int special:1; /* Used for special commands. */ | 182 | unsigned int special:1; /* Used for special commands. */ |
183 | /* receive is called from tasklet context */ | ||
184 | void (*receive)(struct ap_device *, struct ap_message *, | ||
185 | struct ap_message *); | ||
186 | }; | 186 | }; |
187 | 187 | ||
188 | #define AP_DEVICE(dt) \ | 188 | #define AP_DEVICE(dt) \ |
@@ -199,6 +199,7 @@ static inline void ap_init_message(struct ap_message *ap_msg) | |||
199 | ap_msg->psmid = 0; | 199 | ap_msg->psmid = 0; |
200 | ap_msg->length = 0; | 200 | ap_msg->length = 0; |
201 | ap_msg->special = 0; | 201 | ap_msg->special = 0; |
202 | ap_msg->receive = NULL; | ||
202 | } | 203 | } |
203 | 204 | ||
204 | /* | 205 | /* |
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index 084286728166..46812440425a 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c | |||
@@ -77,7 +77,6 @@ static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *, | |||
77 | static struct ap_driver zcrypt_cex2a_driver = { | 77 | static struct ap_driver zcrypt_cex2a_driver = { |
78 | .probe = zcrypt_cex2a_probe, | 78 | .probe = zcrypt_cex2a_probe, |
79 | .remove = zcrypt_cex2a_remove, | 79 | .remove = zcrypt_cex2a_remove, |
80 | .receive = zcrypt_cex2a_receive, | ||
81 | .ids = zcrypt_cex2a_ids, | 80 | .ids = zcrypt_cex2a_ids, |
82 | .request_timeout = CEX2A_CLEANUP_TIME, | 81 | .request_timeout = CEX2A_CLEANUP_TIME, |
83 | }; | 82 | }; |
@@ -349,6 +348,7 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, | |||
349 | ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); | 348 | ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); |
350 | if (!ap_msg.message) | 349 | if (!ap_msg.message) |
351 | return -ENOMEM; | 350 | return -ENOMEM; |
351 | ap_msg.receive = zcrypt_cex2a_receive; | ||
352 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 352 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
353 | atomic_inc_return(&zcrypt_step); | 353 | atomic_inc_return(&zcrypt_step); |
354 | ap_msg.private = &work; | 354 | ap_msg.private = &work; |
@@ -390,6 +390,7 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, | |||
390 | ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); | 390 | ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); |
391 | if (!ap_msg.message) | 391 | if (!ap_msg.message) |
392 | return -ENOMEM; | 392 | return -ENOMEM; |
393 | ap_msg.receive = zcrypt_cex2a_receive; | ||
393 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 394 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
394 | atomic_inc_return(&zcrypt_step); | 395 | atomic_inc_return(&zcrypt_step); |
395 | ap_msg.private = &work; | 396 | ap_msg.private = &work; |
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index 0effca925451..ad7951c21b79 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
@@ -67,7 +67,6 @@ static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *, | |||
67 | static struct ap_driver zcrypt_pcica_driver = { | 67 | static struct ap_driver zcrypt_pcica_driver = { |
68 | .probe = zcrypt_pcica_probe, | 68 | .probe = zcrypt_pcica_probe, |
69 | .remove = zcrypt_pcica_remove, | 69 | .remove = zcrypt_pcica_remove, |
70 | .receive = zcrypt_pcica_receive, | ||
71 | .ids = zcrypt_pcica_ids, | 70 | .ids = zcrypt_pcica_ids, |
72 | .request_timeout = PCICA_CLEANUP_TIME, | 71 | .request_timeout = PCICA_CLEANUP_TIME, |
73 | }; | 72 | }; |
@@ -284,6 +283,7 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev, | |||
284 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); | 283 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); |
285 | if (!ap_msg.message) | 284 | if (!ap_msg.message) |
286 | return -ENOMEM; | 285 | return -ENOMEM; |
286 | ap_msg.receive = zcrypt_pcica_receive; | ||
287 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 287 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
288 | atomic_inc_return(&zcrypt_step); | 288 | atomic_inc_return(&zcrypt_step); |
289 | ap_msg.private = &work; | 289 | ap_msg.private = &work; |
@@ -322,6 +322,7 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev, | |||
322 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); | 322 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); |
323 | if (!ap_msg.message) | 323 | if (!ap_msg.message) |
324 | return -ENOMEM; | 324 | return -ENOMEM; |
325 | ap_msg.receive = zcrypt_pcica_receive; | ||
325 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 326 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
326 | atomic_inc_return(&zcrypt_step); | 327 | atomic_inc_return(&zcrypt_step); |
327 | ap_msg.private = &work; | 328 | ap_msg.private = &work; |
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index f9523c0cc8d2..e5dd335fda53 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c | |||
@@ -79,7 +79,6 @@ static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *, | |||
79 | static struct ap_driver zcrypt_pcicc_driver = { | 79 | static struct ap_driver zcrypt_pcicc_driver = { |
80 | .probe = zcrypt_pcicc_probe, | 80 | .probe = zcrypt_pcicc_probe, |
81 | .remove = zcrypt_pcicc_remove, | 81 | .remove = zcrypt_pcicc_remove, |
82 | .receive = zcrypt_pcicc_receive, | ||
83 | .ids = zcrypt_pcicc_ids, | 82 | .ids = zcrypt_pcicc_ids, |
84 | .request_timeout = PCICC_CLEANUP_TIME, | 83 | .request_timeout = PCICC_CLEANUP_TIME, |
85 | }; | 84 | }; |
@@ -488,6 +487,7 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev, | |||
488 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 487 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); |
489 | if (!ap_msg.message) | 488 | if (!ap_msg.message) |
490 | return -ENOMEM; | 489 | return -ENOMEM; |
490 | ap_msg.receive = zcrypt_pcicc_receive; | ||
491 | ap_msg.length = PAGE_SIZE; | 491 | ap_msg.length = PAGE_SIZE; |
492 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 492 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
493 | atomic_inc_return(&zcrypt_step); | 493 | atomic_inc_return(&zcrypt_step); |
@@ -527,6 +527,7 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev, | |||
527 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 527 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); |
528 | if (!ap_msg.message) | 528 | if (!ap_msg.message) |
529 | return -ENOMEM; | 529 | return -ENOMEM; |
530 | ap_msg.receive = zcrypt_pcicc_receive; | ||
530 | ap_msg.length = PAGE_SIZE; | 531 | ap_msg.length = PAGE_SIZE; |
531 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 532 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
532 | atomic_inc_return(&zcrypt_step); | 533 | atomic_inc_return(&zcrypt_step); |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index cf1cbd4747f4..f7cc43401816 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -89,7 +89,6 @@ static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *, | |||
89 | static struct ap_driver zcrypt_pcixcc_driver = { | 89 | static struct ap_driver zcrypt_pcixcc_driver = { |
90 | .probe = zcrypt_pcixcc_probe, | 90 | .probe = zcrypt_pcixcc_probe, |
91 | .remove = zcrypt_pcixcc_remove, | 91 | .remove = zcrypt_pcixcc_remove, |
92 | .receive = zcrypt_pcixcc_receive, | ||
93 | .ids = zcrypt_pcixcc_ids, | 92 | .ids = zcrypt_pcixcc_ids, |
94 | .request_timeout = PCIXCC_CLEANUP_TIME, | 93 | .request_timeout = PCIXCC_CLEANUP_TIME, |
95 | }; | 94 | }; |
@@ -698,6 +697,7 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev, | |||
698 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 697 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); |
699 | if (!ap_msg.message) | 698 | if (!ap_msg.message) |
700 | return -ENOMEM; | 699 | return -ENOMEM; |
700 | ap_msg.receive = zcrypt_pcixcc_receive; | ||
701 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 701 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
702 | atomic_inc_return(&zcrypt_step); | 702 | atomic_inc_return(&zcrypt_step); |
703 | ap_msg.private = &resp_type; | 703 | ap_msg.private = &resp_type; |
@@ -738,6 +738,7 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, | |||
738 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 738 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); |
739 | if (!ap_msg.message) | 739 | if (!ap_msg.message) |
740 | return -ENOMEM; | 740 | return -ENOMEM; |
741 | ap_msg.receive = zcrypt_pcixcc_receive; | ||
741 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 742 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
742 | atomic_inc_return(&zcrypt_step); | 743 | atomic_inc_return(&zcrypt_step); |
743 | ap_msg.private = &resp_type; | 744 | ap_msg.private = &resp_type; |
@@ -778,6 +779,7 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, | |||
778 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); | 779 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); |
779 | if (!ap_msg.message) | 780 | if (!ap_msg.message) |
780 | return -ENOMEM; | 781 | return -ENOMEM; |
782 | ap_msg.receive = zcrypt_pcixcc_receive; | ||
781 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 783 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
782 | atomic_inc_return(&zcrypt_step); | 784 | atomic_inc_return(&zcrypt_step); |
783 | ap_msg.private = &resp_type; | 785 | ap_msg.private = &resp_type; |
@@ -818,6 +820,7 @@ static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev, | |||
818 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); | 820 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); |
819 | if (!ap_msg.message) | 821 | if (!ap_msg.message) |
820 | return -ENOMEM; | 822 | return -ENOMEM; |
823 | ap_msg.receive = zcrypt_pcixcc_receive; | ||
821 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 824 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
822 | atomic_inc_return(&zcrypt_step); | 825 | atomic_inc_return(&zcrypt_step); |
823 | ap_msg.private = &resp_type; | 826 | ap_msg.private = &resp_type; |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index b41fae37d3af..6b1ff90d2f00 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -136,7 +136,6 @@ static inline void | |||
136 | claw_set_busy(struct net_device *dev) | 136 | claw_set_busy(struct net_device *dev) |
137 | { | 137 | { |
138 | ((struct claw_privbk *)dev->ml_priv)->tbusy = 1; | 138 | ((struct claw_privbk *)dev->ml_priv)->tbusy = 1; |
139 | eieio(); | ||
140 | } | 139 | } |
141 | 140 | ||
142 | static inline void | 141 | static inline void |
@@ -144,13 +143,11 @@ claw_clear_busy(struct net_device *dev) | |||
144 | { | 143 | { |
145 | clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy)); | 144 | clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy)); |
146 | netif_wake_queue(dev); | 145 | netif_wake_queue(dev); |
147 | eieio(); | ||
148 | } | 146 | } |
149 | 147 | ||
150 | static inline int | 148 | static inline int |
151 | claw_check_busy(struct net_device *dev) | 149 | claw_check_busy(struct net_device *dev) |
152 | { | 150 | { |
153 | eieio(); | ||
154 | return ((struct claw_privbk *) dev->ml_priv)->tbusy; | 151 | return ((struct claw_privbk *) dev->ml_priv)->tbusy; |
155 | } | 152 | } |
156 | 153 | ||
@@ -233,8 +230,6 @@ static ssize_t claw_rbuff_show(struct device *dev, | |||
233 | static ssize_t claw_rbuff_write(struct device *dev, | 230 | static ssize_t claw_rbuff_write(struct device *dev, |
234 | struct device_attribute *attr, | 231 | struct device_attribute *attr, |
235 | const char *buf, size_t count); | 232 | const char *buf, size_t count); |
236 | static int claw_add_files(struct device *dev); | ||
237 | static void claw_remove_files(struct device *dev); | ||
238 | 233 | ||
239 | /* Functions for System Validate */ | 234 | /* Functions for System Validate */ |
240 | static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw); | 235 | static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw); |
@@ -267,12 +262,10 @@ static struct ccwgroup_driver claw_group_driver = { | |||
267 | .owner = THIS_MODULE, | 262 | .owner = THIS_MODULE, |
268 | .name = "claw", | 263 | .name = "claw", |
269 | }, | 264 | }, |
270 | .max_slaves = 2, | 265 | .setup = claw_probe, |
271 | .driver_id = 0xC3D3C1E6, | 266 | .remove = claw_remove_device, |
272 | .probe = claw_probe, | 267 | .set_online = claw_new_device, |
273 | .remove = claw_remove_device, | 268 | .set_offline = claw_shutdown_device, |
274 | .set_online = claw_new_device, | ||
275 | .set_offline = claw_shutdown_device, | ||
276 | .prepare = claw_pm_prepare, | 269 | .prepare = claw_pm_prepare, |
277 | }; | 270 | }; |
278 | 271 | ||
@@ -293,30 +286,24 @@ static struct ccw_driver claw_ccw_driver = { | |||
293 | .int_class = IOINT_CLW, | 286 | .int_class = IOINT_CLW, |
294 | }; | 287 | }; |
295 | 288 | ||
296 | static ssize_t | 289 | static ssize_t claw_driver_group_store(struct device_driver *ddrv, |
297 | claw_driver_group_store(struct device_driver *ddrv, const char *buf, | 290 | const char *buf, size_t count) |
298 | size_t count) | ||
299 | { | 291 | { |
300 | int err; | 292 | int err; |
301 | err = ccwgroup_create_from_string(claw_root_dev, | 293 | err = ccwgroup_create_dev(claw_root_dev, &claw_group_driver, 2, buf); |
302 | claw_group_driver.driver_id, | ||
303 | &claw_ccw_driver, 2, buf); | ||
304 | return err ? err : count; | 294 | return err ? err : count; |
305 | } | 295 | } |
306 | |||
307 | static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store); | 296 | static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store); |
308 | 297 | ||
309 | static struct attribute *claw_group_attrs[] = { | 298 | static struct attribute *claw_drv_attrs[] = { |
310 | &driver_attr_group.attr, | 299 | &driver_attr_group.attr, |
311 | NULL, | 300 | NULL, |
312 | }; | 301 | }; |
313 | 302 | static struct attribute_group claw_drv_attr_group = { | |
314 | static struct attribute_group claw_group_attr_group = { | 303 | .attrs = claw_drv_attrs, |
315 | .attrs = claw_group_attrs, | ||
316 | }; | 304 | }; |
317 | 305 | static const struct attribute_group *claw_drv_attr_groups[] = { | |
318 | static const struct attribute_group *claw_group_attr_groups[] = { | 306 | &claw_drv_attr_group, |
319 | &claw_group_attr_group, | ||
320 | NULL, | 307 | NULL, |
321 | }; | 308 | }; |
322 | 309 | ||
@@ -324,60 +311,6 @@ static const struct attribute_group *claw_group_attr_groups[] = { | |||
324 | * Key functions | 311 | * Key functions |
325 | */ | 312 | */ |
326 | 313 | ||
327 | /*----------------------------------------------------------------* | ||
328 | * claw_probe * | ||
329 | * this function is called for each CLAW device. * | ||
330 | *----------------------------------------------------------------*/ | ||
331 | static int | ||
332 | claw_probe(struct ccwgroup_device *cgdev) | ||
333 | { | ||
334 | int rc; | ||
335 | struct claw_privbk *privptr=NULL; | ||
336 | |||
337 | CLAW_DBF_TEXT(2, setup, "probe"); | ||
338 | if (!get_device(&cgdev->dev)) | ||
339 | return -ENODEV; | ||
340 | privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL); | ||
341 | dev_set_drvdata(&cgdev->dev, privptr); | ||
342 | if (privptr == NULL) { | ||
343 | probe_error(cgdev); | ||
344 | put_device(&cgdev->dev); | ||
345 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
346 | return -ENOMEM; | ||
347 | } | ||
348 | privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL); | ||
349 | privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL); | ||
350 | if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) { | ||
351 | probe_error(cgdev); | ||
352 | put_device(&cgdev->dev); | ||
353 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
354 | return -ENOMEM; | ||
355 | } | ||
356 | memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8); | ||
357 | memcpy(privptr->p_env->host_name,WS_NAME_NOT_DEF,8); | ||
358 | memcpy(privptr->p_env->api_type,WS_NAME_NOT_DEF,8); | ||
359 | privptr->p_env->packing = 0; | ||
360 | privptr->p_env->write_buffers = 5; | ||
361 | privptr->p_env->read_buffers = 5; | ||
362 | privptr->p_env->read_size = CLAW_FRAME_SIZE; | ||
363 | privptr->p_env->write_size = CLAW_FRAME_SIZE; | ||
364 | rc = claw_add_files(&cgdev->dev); | ||
365 | if (rc) { | ||
366 | probe_error(cgdev); | ||
367 | put_device(&cgdev->dev); | ||
368 | dev_err(&cgdev->dev, "Creating the /proc files for a new" | ||
369 | " CLAW device failed\n"); | ||
370 | CLAW_DBF_TEXT_(2, setup, "probex%d", rc); | ||
371 | return rc; | ||
372 | } | ||
373 | privptr->p_env->p_priv = privptr; | ||
374 | cgdev->cdev[0]->handler = claw_irq_handler; | ||
375 | cgdev->cdev[1]->handler = claw_irq_handler; | ||
376 | CLAW_DBF_TEXT(2, setup, "prbext 0"); | ||
377 | |||
378 | return 0; | ||
379 | } /* end of claw_probe */ | ||
380 | |||
381 | /*-------------------------------------------------------------------* | 314 | /*-------------------------------------------------------------------* |
382 | * claw_tx * | 315 | * claw_tx * |
383 | *-------------------------------------------------------------------*/ | 316 | *-------------------------------------------------------------------*/ |
@@ -3093,7 +3026,6 @@ claw_remove_device(struct ccwgroup_device *cgdev) | |||
3093 | dev_info(&cgdev->dev, " will be removed.\n"); | 3026 | dev_info(&cgdev->dev, " will be removed.\n"); |
3094 | if (cgdev->state == CCWGROUP_ONLINE) | 3027 | if (cgdev->state == CCWGROUP_ONLINE) |
3095 | claw_shutdown_device(cgdev); | 3028 | claw_shutdown_device(cgdev); |
3096 | claw_remove_files(&cgdev->dev); | ||
3097 | kfree(priv->p_mtc_envelope); | 3029 | kfree(priv->p_mtc_envelope); |
3098 | priv->p_mtc_envelope=NULL; | 3030 | priv->p_mtc_envelope=NULL; |
3099 | kfree(priv->p_env); | 3031 | kfree(priv->p_env); |
@@ -3321,7 +3253,6 @@ claw_rbuff_write(struct device *dev, struct device_attribute *attr, | |||
3321 | CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers); | 3253 | CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers); |
3322 | return count; | 3254 | return count; |
3323 | } | 3255 | } |
3324 | |||
3325 | static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write); | 3256 | static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write); |
3326 | 3257 | ||
3327 | static struct attribute *claw_attr[] = { | 3258 | static struct attribute *claw_attr[] = { |
@@ -3332,40 +3263,73 @@ static struct attribute *claw_attr[] = { | |||
3332 | &dev_attr_host_name.attr, | 3263 | &dev_attr_host_name.attr, |
3333 | NULL, | 3264 | NULL, |
3334 | }; | 3265 | }; |
3335 | |||
3336 | static struct attribute_group claw_attr_group = { | 3266 | static struct attribute_group claw_attr_group = { |
3337 | .attrs = claw_attr, | 3267 | .attrs = claw_attr, |
3338 | }; | 3268 | }; |
3269 | static const struct attribute_group *claw_attr_groups[] = { | ||
3270 | &claw_attr_group, | ||
3271 | NULL, | ||
3272 | }; | ||
3273 | static const struct device_type claw_devtype = { | ||
3274 | .name = "claw", | ||
3275 | .groups = claw_attr_groups, | ||
3276 | }; | ||
3339 | 3277 | ||
3340 | static int | 3278 | /*----------------------------------------------------------------* |
3341 | claw_add_files(struct device *dev) | 3279 | * claw_probe * |
3280 | * this function is called for each CLAW device. * | ||
3281 | *----------------------------------------------------------------*/ | ||
3282 | static int claw_probe(struct ccwgroup_device *cgdev) | ||
3342 | { | 3283 | { |
3343 | CLAW_DBF_TEXT(2, setup, "add_file"); | 3284 | struct claw_privbk *privptr = NULL; |
3344 | return sysfs_create_group(&dev->kobj, &claw_attr_group); | ||
3345 | } | ||
3346 | 3285 | ||
3347 | static void | 3286 | CLAW_DBF_TEXT(2, setup, "probe"); |
3348 | claw_remove_files(struct device *dev) | 3287 | if (!get_device(&cgdev->dev)) |
3349 | { | 3288 | return -ENODEV; |
3350 | CLAW_DBF_TEXT(2, setup, "rem_file"); | 3289 | privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL); |
3351 | sysfs_remove_group(&dev->kobj, &claw_attr_group); | 3290 | dev_set_drvdata(&cgdev->dev, privptr); |
3352 | } | 3291 | if (privptr == NULL) { |
3292 | probe_error(cgdev); | ||
3293 | put_device(&cgdev->dev); | ||
3294 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
3295 | return -ENOMEM; | ||
3296 | } | ||
3297 | privptr->p_mtc_envelope = kzalloc(MAX_ENVELOPE_SIZE, GFP_KERNEL); | ||
3298 | privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL); | ||
3299 | if ((privptr->p_mtc_envelope == NULL) || (privptr->p_env == NULL)) { | ||
3300 | probe_error(cgdev); | ||
3301 | put_device(&cgdev->dev); | ||
3302 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
3303 | return -ENOMEM; | ||
3304 | } | ||
3305 | memcpy(privptr->p_env->adapter_name, WS_NAME_NOT_DEF, 8); | ||
3306 | memcpy(privptr->p_env->host_name, WS_NAME_NOT_DEF, 8); | ||
3307 | memcpy(privptr->p_env->api_type, WS_NAME_NOT_DEF, 8); | ||
3308 | privptr->p_env->packing = 0; | ||
3309 | privptr->p_env->write_buffers = 5; | ||
3310 | privptr->p_env->read_buffers = 5; | ||
3311 | privptr->p_env->read_size = CLAW_FRAME_SIZE; | ||
3312 | privptr->p_env->write_size = CLAW_FRAME_SIZE; | ||
3313 | privptr->p_env->p_priv = privptr; | ||
3314 | cgdev->cdev[0]->handler = claw_irq_handler; | ||
3315 | cgdev->cdev[1]->handler = claw_irq_handler; | ||
3316 | cgdev->dev.type = &claw_devtype; | ||
3317 | CLAW_DBF_TEXT(2, setup, "prbext 0"); | ||
3318 | |||
3319 | return 0; | ||
3320 | } /* end of claw_probe */ | ||
3353 | 3321 | ||
3354 | /*--------------------------------------------------------------------* | 3322 | /*--------------------------------------------------------------------* |
3355 | * claw_init and cleanup * | 3323 | * claw_init and cleanup * |
3356 | *---------------------------------------------------------------------*/ | 3324 | *---------------------------------------------------------------------*/ |
3357 | 3325 | ||
3358 | static void __exit | 3326 | static void __exit claw_cleanup(void) |
3359 | claw_cleanup(void) | ||
3360 | { | 3327 | { |
3361 | driver_remove_file(&claw_group_driver.driver, | ||
3362 | &driver_attr_group); | ||
3363 | ccwgroup_driver_unregister(&claw_group_driver); | 3328 | ccwgroup_driver_unregister(&claw_group_driver); |
3364 | ccw_driver_unregister(&claw_ccw_driver); | 3329 | ccw_driver_unregister(&claw_ccw_driver); |
3365 | root_device_unregister(claw_root_dev); | 3330 | root_device_unregister(claw_root_dev); |
3366 | claw_unregister_debug_facility(); | 3331 | claw_unregister_debug_facility(); |
3367 | pr_info("Driver unloaded\n"); | 3332 | pr_info("Driver unloaded\n"); |
3368 | |||
3369 | } | 3333 | } |
3370 | 3334 | ||
3371 | /** | 3335 | /** |
@@ -3374,8 +3338,7 @@ claw_cleanup(void) | |||
3374 | * | 3338 | * |
3375 | * @return 0 on success, !0 on error. | 3339 | * @return 0 on success, !0 on error. |
3376 | */ | 3340 | */ |
3377 | static int __init | 3341 | static int __init claw_init(void) |
3378 | claw_init(void) | ||
3379 | { | 3342 | { |
3380 | int ret = 0; | 3343 | int ret = 0; |
3381 | 3344 | ||
@@ -3394,7 +3357,7 @@ claw_init(void) | |||
3394 | ret = ccw_driver_register(&claw_ccw_driver); | 3357 | ret = ccw_driver_register(&claw_ccw_driver); |
3395 | if (ret) | 3358 | if (ret) |
3396 | goto ccw_err; | 3359 | goto ccw_err; |
3397 | claw_group_driver.driver.groups = claw_group_attr_groups; | 3360 | claw_group_driver.driver.groups = claw_drv_attr_groups; |
3398 | ret = ccwgroup_driver_register(&claw_group_driver); | 3361 | ret = ccwgroup_driver_register(&claw_group_driver); |
3399 | if (ret) | 3362 | if (ret) |
3400 | goto ccwgroup_err; | 3363 | goto ccwgroup_err; |
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 11f3b071f305..3cd25544a27a 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -1296,6 +1296,11 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1296 | 1296 | ||
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | static const struct device_type ctcm_devtype = { | ||
1300 | .name = "ctcm", | ||
1301 | .groups = ctcm_attr_groups, | ||
1302 | }; | ||
1303 | |||
1299 | /** | 1304 | /** |
1300 | * Add ctcm specific attributes. | 1305 | * Add ctcm specific attributes. |
1301 | * Add ctcm private data. | 1306 | * Add ctcm private data. |
@@ -1307,7 +1312,6 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1307 | static int ctcm_probe_device(struct ccwgroup_device *cgdev) | 1312 | static int ctcm_probe_device(struct ccwgroup_device *cgdev) |
1308 | { | 1313 | { |
1309 | struct ctcm_priv *priv; | 1314 | struct ctcm_priv *priv; |
1310 | int rc; | ||
1311 | 1315 | ||
1312 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | 1316 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1313 | "%s %p", | 1317 | "%s %p", |
@@ -1324,17 +1328,11 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev) | |||
1324 | put_device(&cgdev->dev); | 1328 | put_device(&cgdev->dev); |
1325 | return -ENOMEM; | 1329 | return -ENOMEM; |
1326 | } | 1330 | } |
1327 | |||
1328 | rc = ctcm_add_files(&cgdev->dev); | ||
1329 | if (rc) { | ||
1330 | kfree(priv); | ||
1331 | put_device(&cgdev->dev); | ||
1332 | return rc; | ||
1333 | } | ||
1334 | priv->buffer_size = CTCM_BUFSIZE_DEFAULT; | 1331 | priv->buffer_size = CTCM_BUFSIZE_DEFAULT; |
1335 | cgdev->cdev[0]->handler = ctcm_irq_handler; | 1332 | cgdev->cdev[0]->handler = ctcm_irq_handler; |
1336 | cgdev->cdev[1]->handler = ctcm_irq_handler; | 1333 | cgdev->cdev[1]->handler = ctcm_irq_handler; |
1337 | dev_set_drvdata(&cgdev->dev, priv); | 1334 | dev_set_drvdata(&cgdev->dev, priv); |
1335 | cgdev->dev.type = &ctcm_devtype; | ||
1338 | 1336 | ||
1339 | return 0; | 1337 | return 0; |
1340 | } | 1338 | } |
@@ -1611,11 +1609,6 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1611 | goto out_dev; | 1609 | goto out_dev; |
1612 | } | 1610 | } |
1613 | 1611 | ||
1614 | if (ctcm_add_attributes(&cgdev->dev)) { | ||
1615 | result = -ENODEV; | ||
1616 | goto out_unregister; | ||
1617 | } | ||
1618 | |||
1619 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); | 1612 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); |
1620 | 1613 | ||
1621 | dev_info(&dev->dev, | 1614 | dev_info(&dev->dev, |
@@ -1629,8 +1622,6 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1629 | priv->channel[CTCM_WRITE]->id, priv->protocol); | 1622 | priv->channel[CTCM_WRITE]->id, priv->protocol); |
1630 | 1623 | ||
1631 | return 0; | 1624 | return 0; |
1632 | out_unregister: | ||
1633 | unregister_netdev(dev); | ||
1634 | out_dev: | 1625 | out_dev: |
1635 | ctcm_free_netdevice(dev); | 1626 | ctcm_free_netdevice(dev); |
1636 | out_ccw2: | 1627 | out_ccw2: |
@@ -1669,7 +1660,6 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) | |||
1669 | /* Close the device */ | 1660 | /* Close the device */ |
1670 | ctcm_close(dev); | 1661 | ctcm_close(dev); |
1671 | dev->flags &= ~IFF_RUNNING; | 1662 | dev->flags &= ~IFF_RUNNING; |
1672 | ctcm_remove_attributes(&cgdev->dev); | ||
1673 | channel_free(priv->channel[CTCM_READ]); | 1663 | channel_free(priv->channel[CTCM_READ]); |
1674 | } else | 1664 | } else |
1675 | dev = NULL; | 1665 | dev = NULL; |
@@ -1711,7 +1701,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev) | |||
1711 | 1701 | ||
1712 | if (cgdev->state == CCWGROUP_ONLINE) | 1702 | if (cgdev->state == CCWGROUP_ONLINE) |
1713 | ctcm_shutdown_device(cgdev); | 1703 | ctcm_shutdown_device(cgdev); |
1714 | ctcm_remove_files(&cgdev->dev); | ||
1715 | dev_set_drvdata(&cgdev->dev, NULL); | 1704 | dev_set_drvdata(&cgdev->dev, NULL); |
1716 | kfree(priv); | 1705 | kfree(priv); |
1717 | put_device(&cgdev->dev); | 1706 | put_device(&cgdev->dev); |
@@ -1778,9 +1767,7 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1778 | .owner = THIS_MODULE, | 1767 | .owner = THIS_MODULE, |
1779 | .name = CTC_DRIVER_NAME, | 1768 | .name = CTC_DRIVER_NAME, |
1780 | }, | 1769 | }, |
1781 | .max_slaves = 2, | 1770 | .setup = ctcm_probe_device, |
1782 | .driver_id = 0xC3E3C3D4, /* CTCM */ | ||
1783 | .probe = ctcm_probe_device, | ||
1784 | .remove = ctcm_remove_device, | 1771 | .remove = ctcm_remove_device, |
1785 | .set_online = ctcm_new_device, | 1772 | .set_online = ctcm_new_device, |
1786 | .set_offline = ctcm_shutdown_device, | 1773 | .set_offline = ctcm_shutdown_device, |
@@ -1789,31 +1776,25 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1789 | .restore = ctcm_pm_resume, | 1776 | .restore = ctcm_pm_resume, |
1790 | }; | 1777 | }; |
1791 | 1778 | ||
1792 | static ssize_t | 1779 | static ssize_t ctcm_driver_group_store(struct device_driver *ddrv, |
1793 | ctcm_driver_group_store(struct device_driver *ddrv, const char *buf, | 1780 | const char *buf, size_t count) |
1794 | size_t count) | ||
1795 | { | 1781 | { |
1796 | int err; | 1782 | int err; |
1797 | 1783 | ||
1798 | err = ccwgroup_create_from_string(ctcm_root_dev, | 1784 | err = ccwgroup_create_dev(ctcm_root_dev, &ctcm_group_driver, 2, buf); |
1799 | ctcm_group_driver.driver_id, | ||
1800 | &ctcm_ccw_driver, 2, buf); | ||
1801 | return err ? err : count; | 1785 | return err ? err : count; |
1802 | } | 1786 | } |
1803 | |||
1804 | static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); | 1787 | static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); |
1805 | 1788 | ||
1806 | static struct attribute *ctcm_group_attrs[] = { | 1789 | static struct attribute *ctcm_drv_attrs[] = { |
1807 | &driver_attr_group.attr, | 1790 | &driver_attr_group.attr, |
1808 | NULL, | 1791 | NULL, |
1809 | }; | 1792 | }; |
1810 | 1793 | static struct attribute_group ctcm_drv_attr_group = { | |
1811 | static struct attribute_group ctcm_group_attr_group = { | 1794 | .attrs = ctcm_drv_attrs, |
1812 | .attrs = ctcm_group_attrs, | ||
1813 | }; | 1795 | }; |
1814 | 1796 | static const struct attribute_group *ctcm_drv_attr_groups[] = { | |
1815 | static const struct attribute_group *ctcm_group_attr_groups[] = { | 1797 | &ctcm_drv_attr_group, |
1816 | &ctcm_group_attr_group, | ||
1817 | NULL, | 1798 | NULL, |
1818 | }; | 1799 | }; |
1819 | 1800 | ||
@@ -1829,7 +1810,6 @@ static const struct attribute_group *ctcm_group_attr_groups[] = { | |||
1829 | */ | 1810 | */ |
1830 | static void __exit ctcm_exit(void) | 1811 | static void __exit ctcm_exit(void) |
1831 | { | 1812 | { |
1832 | driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group); | ||
1833 | ccwgroup_driver_unregister(&ctcm_group_driver); | 1813 | ccwgroup_driver_unregister(&ctcm_group_driver); |
1834 | ccw_driver_unregister(&ctcm_ccw_driver); | 1814 | ccw_driver_unregister(&ctcm_ccw_driver); |
1835 | root_device_unregister(ctcm_root_dev); | 1815 | root_device_unregister(ctcm_root_dev); |
@@ -1867,7 +1847,7 @@ static int __init ctcm_init(void) | |||
1867 | ret = ccw_driver_register(&ctcm_ccw_driver); | 1847 | ret = ccw_driver_register(&ctcm_ccw_driver); |
1868 | if (ret) | 1848 | if (ret) |
1869 | goto ccw_err; | 1849 | goto ccw_err; |
1870 | ctcm_group_driver.driver.groups = ctcm_group_attr_groups; | 1850 | ctcm_group_driver.driver.groups = ctcm_drv_attr_groups; |
1871 | ret = ccwgroup_driver_register(&ctcm_group_driver); | 1851 | ret = ccwgroup_driver_register(&ctcm_group_driver); |
1872 | if (ret) | 1852 | if (ret) |
1873 | goto ccwgroup_err; | 1853 | goto ccwgroup_err; |
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index 24d5215eb0c4..b9056a55d995 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h | |||
@@ -225,13 +225,7 @@ struct ctcm_priv { | |||
225 | int ctcm_open(struct net_device *dev); | 225 | int ctcm_open(struct net_device *dev); |
226 | int ctcm_close(struct net_device *dev); | 226 | int ctcm_close(struct net_device *dev); |
227 | 227 | ||
228 | /* | 228 | extern const struct attribute_group *ctcm_attr_groups[]; |
229 | * prototypes for non-static sysfs functions | ||
230 | */ | ||
231 | int ctcm_add_attributes(struct device *dev); | ||
232 | void ctcm_remove_attributes(struct device *dev); | ||
233 | int ctcm_add_files(struct device *dev); | ||
234 | void ctcm_remove_files(struct device *dev); | ||
235 | 229 | ||
236 | /* | 230 | /* |
237 | * Compatibility macros for busy handling | 231 | * Compatibility macros for busy handling |
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c index 650aec1839e9..0c27ae726475 100644 --- a/drivers/s390/net/ctcm_sysfs.c +++ b/drivers/s390/net/ctcm_sysfs.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #define KMSG_COMPONENT "ctcm" | 13 | #define KMSG_COMPONENT "ctcm" |
14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
15 | 15 | ||
16 | #include <linux/device.h> | ||
16 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include "ctcm_main.h" | 19 | #include "ctcm_main.h" |
@@ -108,10 +109,12 @@ static void ctcm_print_statistics(struct ctcm_priv *priv) | |||
108 | } | 109 | } |
109 | 110 | ||
110 | static ssize_t stats_show(struct device *dev, | 111 | static ssize_t stats_show(struct device *dev, |
111 | struct device_attribute *attr, char *buf) | 112 | struct device_attribute *attr, char *buf) |
112 | { | 113 | { |
114 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | ||
113 | struct ctcm_priv *priv = dev_get_drvdata(dev); | 115 | struct ctcm_priv *priv = dev_get_drvdata(dev); |
114 | if (!priv) | 116 | |
117 | if (!priv || gdev->state != CCWGROUP_ONLINE) | ||
115 | return -ENODEV; | 118 | return -ENODEV; |
116 | ctcm_print_statistics(priv); | 119 | ctcm_print_statistics(priv); |
117 | return sprintf(buf, "0\n"); | 120 | return sprintf(buf, "0\n"); |
@@ -190,34 +193,14 @@ static struct attribute *ctcm_attr[] = { | |||
190 | &dev_attr_protocol.attr, | 193 | &dev_attr_protocol.attr, |
191 | &dev_attr_type.attr, | 194 | &dev_attr_type.attr, |
192 | &dev_attr_buffer.attr, | 195 | &dev_attr_buffer.attr, |
196 | &dev_attr_stats.attr, | ||
193 | NULL, | 197 | NULL, |
194 | }; | 198 | }; |
195 | 199 | ||
196 | static struct attribute_group ctcm_attr_group = { | 200 | static struct attribute_group ctcm_attr_group = { |
197 | .attrs = ctcm_attr, | 201 | .attrs = ctcm_attr, |
198 | }; | 202 | }; |
199 | 203 | const struct attribute_group *ctcm_attr_groups[] = { | |
200 | int ctcm_add_attributes(struct device *dev) | 204 | &ctcm_attr_group, |
201 | { | 205 | NULL, |
202 | int rc; | 206 | }; |
203 | |||
204 | rc = device_create_file(dev, &dev_attr_stats); | ||
205 | |||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | void ctcm_remove_attributes(struct device *dev) | ||
210 | { | ||
211 | device_remove_file(dev, &dev_attr_stats); | ||
212 | } | ||
213 | |||
214 | int ctcm_add_files(struct device *dev) | ||
215 | { | ||
216 | return sysfs_create_group(&dev->kobj, &ctcm_attr_group); | ||
217 | } | ||
218 | |||
219 | void ctcm_remove_files(struct device *dev) | ||
220 | { | ||
221 | sysfs_remove_group(&dev->kobj, &ctcm_attr_group); | ||
222 | } | ||
223 | |||
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 6056cf6da035..a3adf4b1c60d 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -2040,10 +2040,17 @@ static struct attribute * lcs_attrs[] = { | |||
2040 | &dev_attr_recover.attr, | 2040 | &dev_attr_recover.attr, |
2041 | NULL, | 2041 | NULL, |
2042 | }; | 2042 | }; |
2043 | |||
2044 | static struct attribute_group lcs_attr_group = { | 2043 | static struct attribute_group lcs_attr_group = { |
2045 | .attrs = lcs_attrs, | 2044 | .attrs = lcs_attrs, |
2046 | }; | 2045 | }; |
2046 | static const struct attribute_group *lcs_attr_groups[] = { | ||
2047 | &lcs_attr_group, | ||
2048 | NULL, | ||
2049 | }; | ||
2050 | static const struct device_type lcs_devtype = { | ||
2051 | .name = "lcs", | ||
2052 | .groups = lcs_attr_groups, | ||
2053 | }; | ||
2047 | 2054 | ||
2048 | /** | 2055 | /** |
2049 | * lcs_probe_device is called on establishing a new ccwgroup_device. | 2056 | * lcs_probe_device is called on establishing a new ccwgroup_device. |
@@ -2052,7 +2059,6 @@ static int | |||
2052 | lcs_probe_device(struct ccwgroup_device *ccwgdev) | 2059 | lcs_probe_device(struct ccwgroup_device *ccwgdev) |
2053 | { | 2060 | { |
2054 | struct lcs_card *card; | 2061 | struct lcs_card *card; |
2055 | int ret; | ||
2056 | 2062 | ||
2057 | if (!get_device(&ccwgdev->dev)) | 2063 | if (!get_device(&ccwgdev->dev)) |
2058 | return -ENODEV; | 2064 | return -ENODEV; |
@@ -2064,12 +2070,6 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) | |||
2064 | put_device(&ccwgdev->dev); | 2070 | put_device(&ccwgdev->dev); |
2065 | return -ENOMEM; | 2071 | return -ENOMEM; |
2066 | } | 2072 | } |
2067 | ret = sysfs_create_group(&ccwgdev->dev.kobj, &lcs_attr_group); | ||
2068 | if (ret) { | ||
2069 | lcs_free_card(card); | ||
2070 | put_device(&ccwgdev->dev); | ||
2071 | return ret; | ||
2072 | } | ||
2073 | dev_set_drvdata(&ccwgdev->dev, card); | 2073 | dev_set_drvdata(&ccwgdev->dev, card); |
2074 | ccwgdev->cdev[0]->handler = lcs_irq; | 2074 | ccwgdev->cdev[0]->handler = lcs_irq; |
2075 | ccwgdev->cdev[1]->handler = lcs_irq; | 2075 | ccwgdev->cdev[1]->handler = lcs_irq; |
@@ -2078,7 +2078,9 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) | |||
2078 | card->thread_start_mask = 0; | 2078 | card->thread_start_mask = 0; |
2079 | card->thread_allowed_mask = 0; | 2079 | card->thread_allowed_mask = 0; |
2080 | card->thread_running_mask = 0; | 2080 | card->thread_running_mask = 0; |
2081 | return 0; | 2081 | ccwgdev->dev.type = &lcs_devtype; |
2082 | |||
2083 | return 0; | ||
2082 | } | 2084 | } |
2083 | 2085 | ||
2084 | static int | 2086 | static int |
@@ -2306,9 +2308,9 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev) | |||
2306 | } | 2308 | } |
2307 | if (card->dev) | 2309 | if (card->dev) |
2308 | unregister_netdev(card->dev); | 2310 | unregister_netdev(card->dev); |
2309 | sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group); | ||
2310 | lcs_cleanup_card(card); | 2311 | lcs_cleanup_card(card); |
2311 | lcs_free_card(card); | 2312 | lcs_free_card(card); |
2313 | dev_set_drvdata(&ccwgdev->dev, NULL); | ||
2312 | put_device(&ccwgdev->dev); | 2314 | put_device(&ccwgdev->dev); |
2313 | } | 2315 | } |
2314 | 2316 | ||
@@ -2393,9 +2395,7 @@ static struct ccwgroup_driver lcs_group_driver = { | |||
2393 | .owner = THIS_MODULE, | 2395 | .owner = THIS_MODULE, |
2394 | .name = "lcs", | 2396 | .name = "lcs", |
2395 | }, | 2397 | }, |
2396 | .max_slaves = 2, | 2398 | .setup = lcs_probe_device, |
2397 | .driver_id = 0xD3C3E2, | ||
2398 | .probe = lcs_probe_device, | ||
2399 | .remove = lcs_remove_device, | 2399 | .remove = lcs_remove_device, |
2400 | .set_online = lcs_new_device, | 2400 | .set_online = lcs_new_device, |
2401 | .set_offline = lcs_shutdown_device, | 2401 | .set_offline = lcs_shutdown_device, |
@@ -2406,30 +2406,24 @@ static struct ccwgroup_driver lcs_group_driver = { | |||
2406 | .restore = lcs_restore, | 2406 | .restore = lcs_restore, |
2407 | }; | 2407 | }; |
2408 | 2408 | ||
2409 | static ssize_t | 2409 | static ssize_t lcs_driver_group_store(struct device_driver *ddrv, |
2410 | lcs_driver_group_store(struct device_driver *ddrv, const char *buf, | 2410 | const char *buf, size_t count) |
2411 | size_t count) | ||
2412 | { | 2411 | { |
2413 | int err; | 2412 | int err; |
2414 | err = ccwgroup_create_from_string(lcs_root_dev, | 2413 | err = ccwgroup_create_dev(lcs_root_dev, &lcs_group_driver, 2, buf); |
2415 | lcs_group_driver.driver_id, | ||
2416 | &lcs_ccw_driver, 2, buf); | ||
2417 | return err ? err : count; | 2414 | return err ? err : count; |
2418 | } | 2415 | } |
2419 | |||
2420 | static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); | 2416 | static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); |
2421 | 2417 | ||
2422 | static struct attribute *lcs_group_attrs[] = { | 2418 | static struct attribute *lcs_drv_attrs[] = { |
2423 | &driver_attr_group.attr, | 2419 | &driver_attr_group.attr, |
2424 | NULL, | 2420 | NULL, |
2425 | }; | 2421 | }; |
2426 | 2422 | static struct attribute_group lcs_drv_attr_group = { | |
2427 | static struct attribute_group lcs_group_attr_group = { | 2423 | .attrs = lcs_drv_attrs, |
2428 | .attrs = lcs_group_attrs, | ||
2429 | }; | 2424 | }; |
2430 | 2425 | static const struct attribute_group *lcs_drv_attr_groups[] = { | |
2431 | static const struct attribute_group *lcs_group_attr_groups[] = { | 2426 | &lcs_drv_attr_group, |
2432 | &lcs_group_attr_group, | ||
2433 | NULL, | 2427 | NULL, |
2434 | }; | 2428 | }; |
2435 | 2429 | ||
@@ -2453,7 +2447,7 @@ __init lcs_init_module(void) | |||
2453 | rc = ccw_driver_register(&lcs_ccw_driver); | 2447 | rc = ccw_driver_register(&lcs_ccw_driver); |
2454 | if (rc) | 2448 | if (rc) |
2455 | goto ccw_err; | 2449 | goto ccw_err; |
2456 | lcs_group_driver.driver.groups = lcs_group_attr_groups; | 2450 | lcs_group_driver.driver.groups = lcs_drv_attr_groups; |
2457 | rc = ccwgroup_driver_register(&lcs_group_driver); | 2451 | rc = ccwgroup_driver_register(&lcs_group_driver); |
2458 | if (rc) | 2452 | if (rc) |
2459 | goto ccwgroup_err; | 2453 | goto ccwgroup_err; |
@@ -2479,8 +2473,6 @@ __exit lcs_cleanup_module(void) | |||
2479 | { | 2473 | { |
2480 | pr_info("Terminating lcs module.\n"); | 2474 | pr_info("Terminating lcs module.\n"); |
2481 | LCS_DBF_TEXT(0, trace, "cleanup"); | 2475 | LCS_DBF_TEXT(0, trace, "cleanup"); |
2482 | driver_remove_file(&lcs_group_driver.driver, | ||
2483 | &driver_attr_group); | ||
2484 | ccwgroup_driver_unregister(&lcs_group_driver); | 2476 | ccwgroup_driver_unregister(&lcs_group_driver); |
2485 | ccw_driver_unregister(&lcs_ccw_driver); | 2477 | ccw_driver_unregister(&lcs_ccw_driver); |
2486 | root_device_unregister(lcs_root_dev); | 2478 | root_device_unregister(lcs_root_dev); |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 40285dc9ae5c..06e8f31ff3dc 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -707,7 +707,16 @@ struct qeth_discipline { | |||
707 | qdio_handler_t *input_handler; | 707 | qdio_handler_t *input_handler; |
708 | qdio_handler_t *output_handler; | 708 | qdio_handler_t *output_handler; |
709 | int (*recover)(void *ptr); | 709 | int (*recover)(void *ptr); |
710 | struct ccwgroup_driver *ccwgdriver; | 710 | int (*setup) (struct ccwgroup_device *); |
711 | void (*remove) (struct ccwgroup_device *); | ||
712 | int (*set_online) (struct ccwgroup_device *); | ||
713 | int (*set_offline) (struct ccwgroup_device *); | ||
714 | void (*shutdown)(struct ccwgroup_device *); | ||
715 | int (*prepare) (struct ccwgroup_device *); | ||
716 | void (*complete) (struct ccwgroup_device *); | ||
717 | int (*freeze)(struct ccwgroup_device *); | ||
718 | int (*thaw) (struct ccwgroup_device *); | ||
719 | int (*restore)(struct ccwgroup_device *); | ||
711 | }; | 720 | }; |
712 | 721 | ||
713 | struct qeth_vlan_vid { | 722 | struct qeth_vlan_vid { |
@@ -771,7 +780,7 @@ struct qeth_card { | |||
771 | struct qeth_perf_stats perf_stats; | 780 | struct qeth_perf_stats perf_stats; |
772 | int read_or_write_problem; | 781 | int read_or_write_problem; |
773 | struct qeth_osn_info osn_info; | 782 | struct qeth_osn_info osn_info; |
774 | struct qeth_discipline discipline; | 783 | struct qeth_discipline *discipline; |
775 | atomic_t force_alloc_skb; | 784 | atomic_t force_alloc_skb; |
776 | struct service_level qeth_service_level; | 785 | struct service_level qeth_service_level; |
777 | struct qdio_ssqd_desc ssqd; | 786 | struct qdio_ssqd_desc ssqd; |
@@ -837,16 +846,15 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card, | |||
837 | return card->info.diagass_support & (__u32)cmd; | 846 | return card->info.diagass_support & (__u32)cmd; |
838 | } | 847 | } |
839 | 848 | ||
840 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; | 849 | extern struct qeth_discipline qeth_l2_discipline; |
841 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; | 850 | extern struct qeth_discipline qeth_l3_discipline; |
851 | extern const struct attribute_group *qeth_generic_attr_groups[]; | ||
852 | extern const struct attribute_group *qeth_osn_attr_groups[]; | ||
853 | |||
842 | const char *qeth_get_cardname_short(struct qeth_card *); | 854 | const char *qeth_get_cardname_short(struct qeth_card *); |
843 | int qeth_realloc_buffer_pool(struct qeth_card *, int); | 855 | int qeth_realloc_buffer_pool(struct qeth_card *, int); |
844 | int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id); | 856 | int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id); |
845 | void qeth_core_free_discipline(struct qeth_card *); | 857 | void qeth_core_free_discipline(struct qeth_card *); |
846 | int qeth_core_create_device_attributes(struct device *); | ||
847 | void qeth_core_remove_device_attributes(struct device *); | ||
848 | int qeth_core_create_osn_attributes(struct device *); | ||
849 | void qeth_core_remove_osn_attributes(struct device *); | ||
850 | void qeth_buffer_reclaim_work(struct work_struct *); | 858 | void qeth_buffer_reclaim_work(struct work_struct *); |
851 | 859 | ||
852 | /* exports for qeth discipline device drivers */ | 860 | /* exports for qeth discipline device drivers */ |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e000001539bf..e118e1e1e1c1 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -1363,7 +1363,7 @@ static void qeth_start_kernel_thread(struct work_struct *work) | |||
1363 | card->write.state != CH_STATE_UP) | 1363 | card->write.state != CH_STATE_UP) |
1364 | return; | 1364 | return; |
1365 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) { | 1365 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) { |
1366 | ts = kthread_run(card->discipline.recover, (void *)card, | 1366 | ts = kthread_run(card->discipline->recover, (void *)card, |
1367 | "qeth_recover"); | 1367 | "qeth_recover"); |
1368 | if (IS_ERR(ts)) { | 1368 | if (IS_ERR(ts)) { |
1369 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | 1369 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); |
@@ -3337,7 +3337,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
3337 | if (rc) { | 3337 | if (rc) { |
3338 | queue->card->stats.tx_errors += count; | 3338 | queue->card->stats.tx_errors += count; |
3339 | /* ignore temporary SIGA errors without busy condition */ | 3339 | /* ignore temporary SIGA errors without busy condition */ |
3340 | if (rc == QDIO_ERROR_SIGA_TARGET) | 3340 | if (rc == -ENOBUFS) |
3341 | return; | 3341 | return; |
3342 | QETH_CARD_TEXT(queue->card, 2, "flushbuf"); | 3342 | QETH_CARD_TEXT(queue->card, 2, "flushbuf"); |
3343 | QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no); | 3343 | QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no); |
@@ -3531,7 +3531,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
3531 | int i; | 3531 | int i; |
3532 | 3532 | ||
3533 | QETH_CARD_TEXT(card, 6, "qdouhdl"); | 3533 | QETH_CARD_TEXT(card, 6, "qdouhdl"); |
3534 | if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | 3534 | if (qdio_error & QDIO_ERROR_FATAL) { |
3535 | QETH_CARD_TEXT(card, 2, "achkcond"); | 3535 | QETH_CARD_TEXT(card, 2, "achkcond"); |
3536 | netif_stop_queue(card->dev); | 3536 | netif_stop_queue(card->dev); |
3537 | qeth_schedule_recovery(card); | 3537 | qeth_schedule_recovery(card); |
@@ -4627,7 +4627,7 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
4627 | goto out_free_in_sbals; | 4627 | goto out_free_in_sbals; |
4628 | } | 4628 | } |
4629 | for (i = 0; i < card->qdio.no_in_queues; ++i) | 4629 | for (i = 0; i < card->qdio.no_in_queues; ++i) |
4630 | queue_start_poll[i] = card->discipline.start_poll; | 4630 | queue_start_poll[i] = card->discipline->start_poll; |
4631 | 4631 | ||
4632 | qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); | 4632 | qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); |
4633 | 4633 | ||
@@ -4651,8 +4651,8 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
4651 | init_data.qib_param_field = qib_param_field; | 4651 | init_data.qib_param_field = qib_param_field; |
4652 | init_data.no_input_qs = card->qdio.no_in_queues; | 4652 | init_data.no_input_qs = card->qdio.no_in_queues; |
4653 | init_data.no_output_qs = card->qdio.no_out_queues; | 4653 | init_data.no_output_qs = card->qdio.no_out_queues; |
4654 | init_data.input_handler = card->discipline.input_handler; | 4654 | init_data.input_handler = card->discipline->input_handler; |
4655 | init_data.output_handler = card->discipline.output_handler; | 4655 | init_data.output_handler = card->discipline->output_handler; |
4656 | init_data.queue_start_poll_array = queue_start_poll; | 4656 | init_data.queue_start_poll_array = queue_start_poll; |
4657 | init_data.int_parm = (unsigned long) card; | 4657 | init_data.int_parm = (unsigned long) card; |
4658 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 4658 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
@@ -4737,13 +4737,6 @@ static struct ccw_driver qeth_ccw_driver = { | |||
4737 | .remove = ccwgroup_remove_ccwdev, | 4737 | .remove = ccwgroup_remove_ccwdev, |
4738 | }; | 4738 | }; |
4739 | 4739 | ||
4740 | static int qeth_core_driver_group(const char *buf, struct device *root_dev, | ||
4741 | unsigned long driver_id) | ||
4742 | { | ||
4743 | return ccwgroup_create_from_string(root_dev, driver_id, | ||
4744 | &qeth_ccw_driver, 3, buf); | ||
4745 | } | ||
4746 | |||
4747 | int qeth_core_hardsetup_card(struct qeth_card *card) | 4740 | int qeth_core_hardsetup_card(struct qeth_card *card) |
4748 | { | 4741 | { |
4749 | int retries = 0; | 4742 | int retries = 0; |
@@ -5040,17 +5033,15 @@ int qeth_core_load_discipline(struct qeth_card *card, | |||
5040 | mutex_lock(&qeth_mod_mutex); | 5033 | mutex_lock(&qeth_mod_mutex); |
5041 | switch (discipline) { | 5034 | switch (discipline) { |
5042 | case QETH_DISCIPLINE_LAYER3: | 5035 | case QETH_DISCIPLINE_LAYER3: |
5043 | card->discipline.ccwgdriver = try_then_request_module( | 5036 | card->discipline = try_then_request_module( |
5044 | symbol_get(qeth_l3_ccwgroup_driver), | 5037 | symbol_get(qeth_l3_discipline), "qeth_l3"); |
5045 | "qeth_l3"); | ||
5046 | break; | 5038 | break; |
5047 | case QETH_DISCIPLINE_LAYER2: | 5039 | case QETH_DISCIPLINE_LAYER2: |
5048 | card->discipline.ccwgdriver = try_then_request_module( | 5040 | card->discipline = try_then_request_module( |
5049 | symbol_get(qeth_l2_ccwgroup_driver), | 5041 | symbol_get(qeth_l2_discipline), "qeth_l2"); |
5050 | "qeth_l2"); | ||
5051 | break; | 5042 | break; |
5052 | } | 5043 | } |
5053 | if (!card->discipline.ccwgdriver) { | 5044 | if (!card->discipline) { |
5054 | dev_err(&card->gdev->dev, "There is no kernel module to " | 5045 | dev_err(&card->gdev->dev, "There is no kernel module to " |
5055 | "support discipline %d\n", discipline); | 5046 | "support discipline %d\n", discipline); |
5056 | rc = -EINVAL; | 5047 | rc = -EINVAL; |
@@ -5062,12 +5053,21 @@ int qeth_core_load_discipline(struct qeth_card *card, | |||
5062 | void qeth_core_free_discipline(struct qeth_card *card) | 5053 | void qeth_core_free_discipline(struct qeth_card *card) |
5063 | { | 5054 | { |
5064 | if (card->options.layer2) | 5055 | if (card->options.layer2) |
5065 | symbol_put(qeth_l2_ccwgroup_driver); | 5056 | symbol_put(qeth_l2_discipline); |
5066 | else | 5057 | else |
5067 | symbol_put(qeth_l3_ccwgroup_driver); | 5058 | symbol_put(qeth_l3_discipline); |
5068 | card->discipline.ccwgdriver = NULL; | 5059 | card->discipline = NULL; |
5069 | } | 5060 | } |
5070 | 5061 | ||
5062 | static const struct device_type qeth_generic_devtype = { | ||
5063 | .name = "qeth_generic", | ||
5064 | .groups = qeth_generic_attr_groups, | ||
5065 | }; | ||
5066 | static const struct device_type qeth_osn_devtype = { | ||
5067 | .name = "qeth_osn", | ||
5068 | .groups = qeth_osn_attr_groups, | ||
5069 | }; | ||
5070 | |||
5071 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) | 5071 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) |
5072 | { | 5072 | { |
5073 | struct qeth_card *card; | 5073 | struct qeth_card *card; |
@@ -5122,18 +5122,17 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) | |||
5122 | } | 5122 | } |
5123 | 5123 | ||
5124 | if (card->info.type == QETH_CARD_TYPE_OSN) | 5124 | if (card->info.type == QETH_CARD_TYPE_OSN) |
5125 | rc = qeth_core_create_osn_attributes(dev); | 5125 | gdev->dev.type = &qeth_osn_devtype; |
5126 | else | 5126 | else |
5127 | rc = qeth_core_create_device_attributes(dev); | 5127 | gdev->dev.type = &qeth_generic_devtype; |
5128 | if (rc) | 5128 | |
5129 | goto err_dbf; | ||
5130 | switch (card->info.type) { | 5129 | switch (card->info.type) { |
5131 | case QETH_CARD_TYPE_OSN: | 5130 | case QETH_CARD_TYPE_OSN: |
5132 | case QETH_CARD_TYPE_OSM: | 5131 | case QETH_CARD_TYPE_OSM: |
5133 | rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2); | 5132 | rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2); |
5134 | if (rc) | 5133 | if (rc) |
5135 | goto err_attr; | 5134 | goto err_dbf; |
5136 | rc = card->discipline.ccwgdriver->probe(card->gdev); | 5135 | rc = card->discipline->setup(card->gdev); |
5137 | if (rc) | 5136 | if (rc) |
5138 | goto err_disc; | 5137 | goto err_disc; |
5139 | case QETH_CARD_TYPE_OSD: | 5138 | case QETH_CARD_TYPE_OSD: |
@@ -5151,11 +5150,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) | |||
5151 | 5150 | ||
5152 | err_disc: | 5151 | err_disc: |
5153 | qeth_core_free_discipline(card); | 5152 | qeth_core_free_discipline(card); |
5154 | err_attr: | ||
5155 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
5156 | qeth_core_remove_osn_attributes(dev); | ||
5157 | else | ||
5158 | qeth_core_remove_device_attributes(dev); | ||
5159 | err_dbf: | 5153 | err_dbf: |
5160 | debug_unregister(card->debug); | 5154 | debug_unregister(card->debug); |
5161 | err_card: | 5155 | err_card: |
@@ -5172,14 +5166,8 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev) | |||
5172 | 5166 | ||
5173 | QETH_DBF_TEXT(SETUP, 2, "removedv"); | 5167 | QETH_DBF_TEXT(SETUP, 2, "removedv"); |
5174 | 5168 | ||
5175 | if (card->info.type == QETH_CARD_TYPE_OSN) { | 5169 | if (card->discipline) { |
5176 | qeth_core_remove_osn_attributes(&gdev->dev); | 5170 | card->discipline->remove(gdev); |
5177 | } else { | ||
5178 | qeth_core_remove_device_attributes(&gdev->dev); | ||
5179 | } | ||
5180 | |||
5181 | if (card->discipline.ccwgdriver) { | ||
5182 | card->discipline.ccwgdriver->remove(gdev); | ||
5183 | qeth_core_free_discipline(card); | 5171 | qeth_core_free_discipline(card); |
5184 | } | 5172 | } |
5185 | 5173 | ||
@@ -5199,7 +5187,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) | |||
5199 | int rc = 0; | 5187 | int rc = 0; |
5200 | int def_discipline; | 5188 | int def_discipline; |
5201 | 5189 | ||
5202 | if (!card->discipline.ccwgdriver) { | 5190 | if (!card->discipline) { |
5203 | if (card->info.type == QETH_CARD_TYPE_IQD) | 5191 | if (card->info.type == QETH_CARD_TYPE_IQD) |
5204 | def_discipline = QETH_DISCIPLINE_LAYER3; | 5192 | def_discipline = QETH_DISCIPLINE_LAYER3; |
5205 | else | 5193 | else |
@@ -5207,11 +5195,11 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) | |||
5207 | rc = qeth_core_load_discipline(card, def_discipline); | 5195 | rc = qeth_core_load_discipline(card, def_discipline); |
5208 | if (rc) | 5196 | if (rc) |
5209 | goto err; | 5197 | goto err; |
5210 | rc = card->discipline.ccwgdriver->probe(card->gdev); | 5198 | rc = card->discipline->setup(card->gdev); |
5211 | if (rc) | 5199 | if (rc) |
5212 | goto err; | 5200 | goto err; |
5213 | } | 5201 | } |
5214 | rc = card->discipline.ccwgdriver->set_online(gdev); | 5202 | rc = card->discipline->set_online(gdev); |
5215 | err: | 5203 | err: |
5216 | return rc; | 5204 | return rc; |
5217 | } | 5205 | } |
@@ -5219,58 +5207,52 @@ err: | |||
5219 | static int qeth_core_set_offline(struct ccwgroup_device *gdev) | 5207 | static int qeth_core_set_offline(struct ccwgroup_device *gdev) |
5220 | { | 5208 | { |
5221 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5209 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5222 | return card->discipline.ccwgdriver->set_offline(gdev); | 5210 | return card->discipline->set_offline(gdev); |
5223 | } | 5211 | } |
5224 | 5212 | ||
5225 | static void qeth_core_shutdown(struct ccwgroup_device *gdev) | 5213 | static void qeth_core_shutdown(struct ccwgroup_device *gdev) |
5226 | { | 5214 | { |
5227 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5215 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5228 | if (card->discipline.ccwgdriver && | 5216 | if (card->discipline && card->discipline->shutdown) |
5229 | card->discipline.ccwgdriver->shutdown) | 5217 | card->discipline->shutdown(gdev); |
5230 | card->discipline.ccwgdriver->shutdown(gdev); | ||
5231 | } | 5218 | } |
5232 | 5219 | ||
5233 | static int qeth_core_prepare(struct ccwgroup_device *gdev) | 5220 | static int qeth_core_prepare(struct ccwgroup_device *gdev) |
5234 | { | 5221 | { |
5235 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5222 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5236 | if (card->discipline.ccwgdriver && | 5223 | if (card->discipline && card->discipline->prepare) |
5237 | card->discipline.ccwgdriver->prepare) | 5224 | return card->discipline->prepare(gdev); |
5238 | return card->discipline.ccwgdriver->prepare(gdev); | ||
5239 | return 0; | 5225 | return 0; |
5240 | } | 5226 | } |
5241 | 5227 | ||
5242 | static void qeth_core_complete(struct ccwgroup_device *gdev) | 5228 | static void qeth_core_complete(struct ccwgroup_device *gdev) |
5243 | { | 5229 | { |
5244 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5230 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5245 | if (card->discipline.ccwgdriver && | 5231 | if (card->discipline && card->discipline->complete) |
5246 | card->discipline.ccwgdriver->complete) | 5232 | card->discipline->complete(gdev); |
5247 | card->discipline.ccwgdriver->complete(gdev); | ||
5248 | } | 5233 | } |
5249 | 5234 | ||
5250 | static int qeth_core_freeze(struct ccwgroup_device *gdev) | 5235 | static int qeth_core_freeze(struct ccwgroup_device *gdev) |
5251 | { | 5236 | { |
5252 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5237 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5253 | if (card->discipline.ccwgdriver && | 5238 | if (card->discipline && card->discipline->freeze) |
5254 | card->discipline.ccwgdriver->freeze) | 5239 | return card->discipline->freeze(gdev); |
5255 | return card->discipline.ccwgdriver->freeze(gdev); | ||
5256 | return 0; | 5240 | return 0; |
5257 | } | 5241 | } |
5258 | 5242 | ||
5259 | static int qeth_core_thaw(struct ccwgroup_device *gdev) | 5243 | static int qeth_core_thaw(struct ccwgroup_device *gdev) |
5260 | { | 5244 | { |
5261 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5245 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5262 | if (card->discipline.ccwgdriver && | 5246 | if (card->discipline && card->discipline->thaw) |
5263 | card->discipline.ccwgdriver->thaw) | 5247 | return card->discipline->thaw(gdev); |
5264 | return card->discipline.ccwgdriver->thaw(gdev); | ||
5265 | return 0; | 5248 | return 0; |
5266 | } | 5249 | } |
5267 | 5250 | ||
5268 | static int qeth_core_restore(struct ccwgroup_device *gdev) | 5251 | static int qeth_core_restore(struct ccwgroup_device *gdev) |
5269 | { | 5252 | { |
5270 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 5253 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5271 | if (card->discipline.ccwgdriver && | 5254 | if (card->discipline && card->discipline->restore) |
5272 | card->discipline.ccwgdriver->restore) | 5255 | return card->discipline->restore(gdev); |
5273 | return card->discipline.ccwgdriver->restore(gdev); | ||
5274 | return 0; | 5256 | return 0; |
5275 | } | 5257 | } |
5276 | 5258 | ||
@@ -5279,8 +5261,7 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = { | |||
5279 | .owner = THIS_MODULE, | 5261 | .owner = THIS_MODULE, |
5280 | .name = "qeth", | 5262 | .name = "qeth", |
5281 | }, | 5263 | }, |
5282 | .driver_id = 0xD8C5E3C8, | 5264 | .setup = qeth_core_probe_device, |
5283 | .probe = qeth_core_probe_device, | ||
5284 | .remove = qeth_core_remove_device, | 5265 | .remove = qeth_core_remove_device, |
5285 | .set_online = qeth_core_set_online, | 5266 | .set_online = qeth_core_set_online, |
5286 | .set_offline = qeth_core_set_offline, | 5267 | .set_offline = qeth_core_set_offline, |
@@ -5292,21 +5273,30 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = { | |||
5292 | .restore = qeth_core_restore, | 5273 | .restore = qeth_core_restore, |
5293 | }; | 5274 | }; |
5294 | 5275 | ||
5295 | static ssize_t | 5276 | static ssize_t qeth_core_driver_group_store(struct device_driver *ddrv, |
5296 | qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf, | 5277 | const char *buf, size_t count) |
5297 | size_t count) | ||
5298 | { | 5278 | { |
5299 | int err; | 5279 | int err; |
5300 | err = qeth_core_driver_group(buf, qeth_core_root_dev, | ||
5301 | qeth_core_ccwgroup_driver.driver_id); | ||
5302 | if (err) | ||
5303 | return err; | ||
5304 | else | ||
5305 | return count; | ||
5306 | } | ||
5307 | 5280 | ||
5281 | err = ccwgroup_create_dev(qeth_core_root_dev, | ||
5282 | &qeth_core_ccwgroup_driver, 3, buf); | ||
5283 | |||
5284 | return err ? err : count; | ||
5285 | } | ||
5308 | static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store); | 5286 | static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store); |
5309 | 5287 | ||
5288 | static struct attribute *qeth_drv_attrs[] = { | ||
5289 | &driver_attr_group.attr, | ||
5290 | NULL, | ||
5291 | }; | ||
5292 | static struct attribute_group qeth_drv_attr_group = { | ||
5293 | .attrs = qeth_drv_attrs, | ||
5294 | }; | ||
5295 | static const struct attribute_group *qeth_drv_attr_groups[] = { | ||
5296 | &qeth_drv_attr_group, | ||
5297 | NULL, | ||
5298 | }; | ||
5299 | |||
5310 | static struct { | 5300 | static struct { |
5311 | const char str[ETH_GSTRING_LEN]; | 5301 | const char str[ETH_GSTRING_LEN]; |
5312 | } qeth_ethtool_stats_keys[] = { | 5302 | } qeth_ethtool_stats_keys[] = { |
@@ -5544,49 +5534,41 @@ static int __init qeth_core_init(void) | |||
5544 | rc = qeth_register_dbf_views(); | 5534 | rc = qeth_register_dbf_views(); |
5545 | if (rc) | 5535 | if (rc) |
5546 | goto out_err; | 5536 | goto out_err; |
5547 | rc = ccw_driver_register(&qeth_ccw_driver); | ||
5548 | if (rc) | ||
5549 | goto ccw_err; | ||
5550 | rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver); | ||
5551 | if (rc) | ||
5552 | goto ccwgroup_err; | ||
5553 | rc = driver_create_file(&qeth_core_ccwgroup_driver.driver, | ||
5554 | &driver_attr_group); | ||
5555 | if (rc) | ||
5556 | goto driver_err; | ||
5557 | qeth_core_root_dev = root_device_register("qeth"); | 5537 | qeth_core_root_dev = root_device_register("qeth"); |
5558 | rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0; | 5538 | rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0; |
5559 | if (rc) | 5539 | if (rc) |
5560 | goto register_err; | 5540 | goto register_err; |
5561 | |||
5562 | qeth_core_header_cache = kmem_cache_create("qeth_hdr", | 5541 | qeth_core_header_cache = kmem_cache_create("qeth_hdr", |
5563 | sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL); | 5542 | sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL); |
5564 | if (!qeth_core_header_cache) { | 5543 | if (!qeth_core_header_cache) { |
5565 | rc = -ENOMEM; | 5544 | rc = -ENOMEM; |
5566 | goto slab_err; | 5545 | goto slab_err; |
5567 | } | 5546 | } |
5568 | |||
5569 | qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf", | 5547 | qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf", |
5570 | sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL); | 5548 | sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL); |
5571 | if (!qeth_qdio_outbuf_cache) { | 5549 | if (!qeth_qdio_outbuf_cache) { |
5572 | rc = -ENOMEM; | 5550 | rc = -ENOMEM; |
5573 | goto cqslab_err; | 5551 | goto cqslab_err; |
5574 | } | 5552 | } |
5553 | rc = ccw_driver_register(&qeth_ccw_driver); | ||
5554 | if (rc) | ||
5555 | goto ccw_err; | ||
5556 | qeth_core_ccwgroup_driver.driver.groups = qeth_drv_attr_groups; | ||
5557 | rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver); | ||
5558 | if (rc) | ||
5559 | goto ccwgroup_err; | ||
5575 | 5560 | ||
5576 | return 0; | 5561 | return 0; |
5562 | |||
5563 | ccwgroup_err: | ||
5564 | ccw_driver_unregister(&qeth_ccw_driver); | ||
5565 | ccw_err: | ||
5566 | kmem_cache_destroy(qeth_qdio_outbuf_cache); | ||
5577 | cqslab_err: | 5567 | cqslab_err: |
5578 | kmem_cache_destroy(qeth_core_header_cache); | 5568 | kmem_cache_destroy(qeth_core_header_cache); |
5579 | slab_err: | 5569 | slab_err: |
5580 | root_device_unregister(qeth_core_root_dev); | 5570 | root_device_unregister(qeth_core_root_dev); |
5581 | register_err: | 5571 | register_err: |
5582 | driver_remove_file(&qeth_core_ccwgroup_driver.driver, | ||
5583 | &driver_attr_group); | ||
5584 | driver_err: | ||
5585 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); | ||
5586 | ccwgroup_err: | ||
5587 | ccw_driver_unregister(&qeth_ccw_driver); | ||
5588 | ccw_err: | ||
5589 | QETH_DBF_MESSAGE(2, "Initialization failed with code %d\n", rc); | ||
5590 | qeth_unregister_dbf_views(); | 5572 | qeth_unregister_dbf_views(); |
5591 | out_err: | 5573 | out_err: |
5592 | pr_err("Initializing the qeth device driver failed\n"); | 5574 | pr_err("Initializing the qeth device driver failed\n"); |
@@ -5595,13 +5577,11 @@ out_err: | |||
5595 | 5577 | ||
5596 | static void __exit qeth_core_exit(void) | 5578 | static void __exit qeth_core_exit(void) |
5597 | { | 5579 | { |
5598 | root_device_unregister(qeth_core_root_dev); | ||
5599 | driver_remove_file(&qeth_core_ccwgroup_driver.driver, | ||
5600 | &driver_attr_group); | ||
5601 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); | 5580 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); |
5602 | ccw_driver_unregister(&qeth_ccw_driver); | 5581 | ccw_driver_unregister(&qeth_ccw_driver); |
5603 | kmem_cache_destroy(qeth_qdio_outbuf_cache); | 5582 | kmem_cache_destroy(qeth_qdio_outbuf_cache); |
5604 | kmem_cache_destroy(qeth_core_header_cache); | 5583 | kmem_cache_destroy(qeth_core_header_cache); |
5584 | root_device_unregister(qeth_core_root_dev); | ||
5605 | qeth_unregister_dbf_views(); | 5585 | qeth_unregister_dbf_views(); |
5606 | pr_info("core functions removed\n"); | 5586 | pr_info("core functions removed\n"); |
5607 | } | 5587 | } |
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 0a8e86c1b0ea..f163af575c48 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c | |||
@@ -434,8 +434,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, | |||
434 | goto out; | 434 | goto out; |
435 | else { | 435 | else { |
436 | card->info.mac_bits = 0; | 436 | card->info.mac_bits = 0; |
437 | if (card->discipline.ccwgdriver) { | 437 | if (card->discipline) { |
438 | card->discipline.ccwgdriver->remove(card->gdev); | 438 | card->discipline->remove(card->gdev); |
439 | qeth_core_free_discipline(card); | 439 | qeth_core_free_discipline(card); |
440 | } | 440 | } |
441 | } | 441 | } |
@@ -444,7 +444,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, | |||
444 | if (rc) | 444 | if (rc) |
445 | goto out; | 445 | goto out; |
446 | 446 | ||
447 | rc = card->discipline.ccwgdriver->probe(card->gdev); | 447 | rc = card->discipline->setup(card->gdev); |
448 | out: | 448 | out: |
449 | mutex_unlock(&card->discipline_mutex); | 449 | mutex_unlock(&card->discipline_mutex); |
450 | return rc ? rc : count; | 450 | return rc ? rc : count; |
@@ -693,7 +693,6 @@ static struct attribute *qeth_blkt_device_attrs[] = { | |||
693 | &dev_attr_inter_jumbo.attr, | 693 | &dev_attr_inter_jumbo.attr, |
694 | NULL, | 694 | NULL, |
695 | }; | 695 | }; |
696 | |||
697 | static struct attribute_group qeth_device_blkt_group = { | 696 | static struct attribute_group qeth_device_blkt_group = { |
698 | .name = "blkt", | 697 | .name = "blkt", |
699 | .attrs = qeth_blkt_device_attrs, | 698 | .attrs = qeth_blkt_device_attrs, |
@@ -716,11 +715,16 @@ static struct attribute *qeth_device_attrs[] = { | |||
716 | &dev_attr_hw_trap.attr, | 715 | &dev_attr_hw_trap.attr, |
717 | NULL, | 716 | NULL, |
718 | }; | 717 | }; |
719 | |||
720 | static struct attribute_group qeth_device_attr_group = { | 718 | static struct attribute_group qeth_device_attr_group = { |
721 | .attrs = qeth_device_attrs, | 719 | .attrs = qeth_device_attrs, |
722 | }; | 720 | }; |
723 | 721 | ||
722 | const struct attribute_group *qeth_generic_attr_groups[] = { | ||
723 | &qeth_device_attr_group, | ||
724 | &qeth_device_blkt_group, | ||
725 | NULL, | ||
726 | }; | ||
727 | |||
724 | static struct attribute *qeth_osn_device_attrs[] = { | 728 | static struct attribute *qeth_osn_device_attrs[] = { |
725 | &dev_attr_state.attr, | 729 | &dev_attr_state.attr, |
726 | &dev_attr_chpid.attr, | 730 | &dev_attr_chpid.attr, |
@@ -730,37 +734,10 @@ static struct attribute *qeth_osn_device_attrs[] = { | |||
730 | &dev_attr_recover.attr, | 734 | &dev_attr_recover.attr, |
731 | NULL, | 735 | NULL, |
732 | }; | 736 | }; |
733 | |||
734 | static struct attribute_group qeth_osn_device_attr_group = { | 737 | static struct attribute_group qeth_osn_device_attr_group = { |
735 | .attrs = qeth_osn_device_attrs, | 738 | .attrs = qeth_osn_device_attrs, |
736 | }; | 739 | }; |
737 | 740 | const struct attribute_group *qeth_osn_attr_groups[] = { | |
738 | int qeth_core_create_device_attributes(struct device *dev) | 741 | &qeth_osn_device_attr_group, |
739 | { | 742 | NULL, |
740 | int ret; | 743 | }; |
741 | ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group); | ||
742 | if (ret) | ||
743 | return ret; | ||
744 | ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group); | ||
745 | if (ret) | ||
746 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | void qeth_core_remove_device_attributes(struct device *dev) | ||
752 | { | ||
753 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
754 | sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group); | ||
755 | } | ||
756 | |||
757 | int qeth_core_create_osn_attributes(struct device *dev) | ||
758 | { | ||
759 | return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group); | ||
760 | } | ||
761 | |||
762 | void qeth_core_remove_osn_attributes(struct device *dev) | ||
763 | { | ||
764 | sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group); | ||
765 | return; | ||
766 | } | ||
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 0e7c29d1d7ef..426986518e96 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -882,12 +882,6 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
882 | INIT_LIST_HEAD(&card->mc_list); | 882 | INIT_LIST_HEAD(&card->mc_list); |
883 | card->options.layer2 = 1; | 883 | card->options.layer2 = 1; |
884 | card->info.hwtrap = 0; | 884 | card->info.hwtrap = 0; |
885 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
886 | card->discipline.input_handler = (qdio_handler_t *) | ||
887 | qeth_qdio_input_handler; | ||
888 | card->discipline.output_handler = (qdio_handler_t *) | ||
889 | qeth_qdio_output_handler; | ||
890 | card->discipline.recover = qeth_l2_recover; | ||
891 | return 0; | 885 | return 0; |
892 | } | 886 | } |
893 | 887 | ||
@@ -1227,8 +1221,12 @@ out: | |||
1227 | return rc; | 1221 | return rc; |
1228 | } | 1222 | } |
1229 | 1223 | ||
1230 | struct ccwgroup_driver qeth_l2_ccwgroup_driver = { | 1224 | struct qeth_discipline qeth_l2_discipline = { |
1231 | .probe = qeth_l2_probe_device, | 1225 | .start_poll = qeth_qdio_start_poll, |
1226 | .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, | ||
1227 | .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, | ||
1228 | .recover = qeth_l2_recover, | ||
1229 | .setup = qeth_l2_probe_device, | ||
1232 | .remove = qeth_l2_remove_device, | 1230 | .remove = qeth_l2_remove_device, |
1233 | .set_online = qeth_l2_set_online, | 1231 | .set_online = qeth_l2_set_online, |
1234 | .set_offline = qeth_l2_set_offline, | 1232 | .set_offline = qeth_l2_set_offline, |
@@ -1237,7 +1235,7 @@ struct ccwgroup_driver qeth_l2_ccwgroup_driver = { | |||
1237 | .thaw = qeth_l2_pm_resume, | 1235 | .thaw = qeth_l2_pm_resume, |
1238 | .restore = qeth_l2_pm_resume, | 1236 | .restore = qeth_l2_pm_resume, |
1239 | }; | 1237 | }; |
1240 | EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver); | 1238 | EXPORT_SYMBOL_GPL(qeth_l2_discipline); |
1241 | 1239 | ||
1242 | static int qeth_osn_send_control_data(struct qeth_card *card, int len, | 1240 | static int qeth_osn_send_control_data(struct qeth_card *card, int len, |
1243 | struct qeth_cmd_buffer *iob) | 1241 | struct qeth_cmd_buffer *iob) |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e7ad03209cb2..7be5e9775691 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -3298,12 +3298,6 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | |||
3298 | qeth_l3_create_device_attributes(&gdev->dev); | 3298 | qeth_l3_create_device_attributes(&gdev->dev); |
3299 | card->options.layer2 = 0; | 3299 | card->options.layer2 = 0; |
3300 | card->info.hwtrap = 0; | 3300 | card->info.hwtrap = 0; |
3301 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
3302 | card->discipline.input_handler = (qdio_handler_t *) | ||
3303 | qeth_qdio_input_handler; | ||
3304 | card->discipline.output_handler = (qdio_handler_t *) | ||
3305 | qeth_qdio_output_handler; | ||
3306 | card->discipline.recover = qeth_l3_recover; | ||
3307 | return 0; | 3301 | return 0; |
3308 | } | 3302 | } |
3309 | 3303 | ||
@@ -3578,8 +3572,12 @@ out: | |||
3578 | return rc; | 3572 | return rc; |
3579 | } | 3573 | } |
3580 | 3574 | ||
3581 | struct ccwgroup_driver qeth_l3_ccwgroup_driver = { | 3575 | struct qeth_discipline qeth_l3_discipline = { |
3582 | .probe = qeth_l3_probe_device, | 3576 | .start_poll = qeth_qdio_start_poll, |
3577 | .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, | ||
3578 | .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, | ||
3579 | .recover = qeth_l3_recover, | ||
3580 | .setup = qeth_l3_probe_device, | ||
3583 | .remove = qeth_l3_remove_device, | 3581 | .remove = qeth_l3_remove_device, |
3584 | .set_online = qeth_l3_set_online, | 3582 | .set_online = qeth_l3_set_online, |
3585 | .set_offline = qeth_l3_set_offline, | 3583 | .set_offline = qeth_l3_set_offline, |
@@ -3588,7 +3586,7 @@ struct ccwgroup_driver qeth_l3_ccwgroup_driver = { | |||
3588 | .thaw = qeth_l3_pm_resume, | 3586 | .thaw = qeth_l3_pm_resume, |
3589 | .restore = qeth_l3_pm_resume, | 3587 | .restore = qeth_l3_pm_resume, |
3590 | }; | 3588 | }; |
3591 | EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver); | 3589 | EXPORT_SYMBOL_GPL(qeth_l3_discipline); |
3592 | 3590 | ||
3593 | static int qeth_l3_ip_event(struct notifier_block *this, | 3591 | static int qeth_l3_ip_event(struct notifier_block *this, |
3594 | unsigned long event, void *ptr) | 3592 | unsigned long event, void *ptr) |