浏览代码

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 updates from Martin Schwidefsky:
 "Just a random collection of bug-fixes and cleanups, nothing new in
  this merge request."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (46 commits)
  s390/ap: Fix wrong or missing comments
  s390/ap: move receive callback to message struct
  s390/dasd: re-prioritize partition detection message
  s390/qeth: reshuffle initialization
  s390/qeth: cleanup drv attr usage
  s390/claw: cleanup drv attr usage
  s390/lcs: cleanup drv attr usage
  s390/ctc: cleanup drv attr usage
  s390/ccwgroup: remove ccwgroup_create_from_string
  s390/qeth: stop using struct ccwgroup driver for discipline callbacks
  s390/qeth: switch to ccwgroup_create_dev
  s390/claw: switch to ccwgroup_create_dev
  s390/lcs: switch to ccwgroup_create_dev
  s390/ctcm: switch to ccwgroup_create_dev
  s390/ccwgroup: exploit ccwdev_by_dev_id
  s390/ccwgroup: introduce ccwgroup_create_dev
  s390: fix race on TIF_MCCK_PENDING
  s390/barrier: make use of fast-bcr facility
  s390/barrier: cleanup barrier functions
  s390/claw: remove "eieio" calls
  ...
Linus Torvalds 13 年之前
父节点
当前提交
e60b9a0346
共有 54 个文件被更改,包括 592 次插入1127 次删除
  1. 26 29
      arch/s390/Kconfig
  2. 2 0
      arch/s390/boot/.gitignore
  3. 3 0
      arch/s390/boot/compressed/.gitignore
  4. 0 1
      arch/s390/defconfig
  5. 20 17
      arch/s390/include/asm/barrier.h
  6. 4 10
      arch/s390/include/asm/ccwgroup.h
  7. 2 5
      arch/s390/include/asm/io.h
  8. 9 10
      arch/s390/include/asm/qdio.h
  9. 0 3
      arch/s390/include/asm/setup.h
  10. 0 2
      arch/s390/include/asm/thread_info.h
  11. 5 12
      arch/s390/include/asm/timex.h
  12. 1 0
      arch/s390/kernel/.gitignore
  13. 0 7
      arch/s390/kernel/compat_signal.c
  14. 0 2
      arch/s390/kernel/early.c
  15. 11 10
      arch/s390/kernel/entry.S
  16. 28 23
      arch/s390/kernel/entry64.S
  17. 0 123
      arch/s390/kernel/head.S
  18. 0 16
      arch/s390/kernel/signal.c
  19. 4 0
      arch/s390/kernel/smp.c
  20. 1 0
      arch/s390/kernel/vdso32/.gitignore
  21. 1 0
      arch/s390/kernel/vdso64/.gitignore
  22. 27 18
      arch/s390/mm/fault.c
  23. 2 0
      arch/s390/mm/hugetlbpage.c
  24. 67 0
      arch/s390/mm/maccess.c
  25. 2 0
      arch/s390/mm/pgtable.c
  26. 1 1
      block/partitions/ibm.c
  27. 1 0
      drivers/crypto/Kconfig
  28. 11 1
      drivers/s390/char/sclp_cmd.c
  29. 0 43
      drivers/s390/char/tape.h
  30. 0 136
      drivers/s390/char/tape_34xx.c
  31. 0 105
      drivers/s390/char/tape_3590.c
  32. 0 13
      drivers/s390/char/tape_char.c
  33. 2 14
      drivers/s390/char/tape_core.c
  34. 43 69
      drivers/s390/cio/ccwgroup.c
  35. 19 54
      drivers/s390/cio/cio.c
  36. 12 1
      drivers/s390/cio/device.c
  37. 1 0
      drivers/s390/cio/device.h
  38. 24 23
      drivers/s390/cio/qdio_main.c
  39. 14 10
      drivers/s390/crypto/ap_bus.c
  40. 4 3
      drivers/s390/crypto/ap_bus.h
  41. 2 1
      drivers/s390/crypto/zcrypt_cex2a.c
  42. 2 1
      drivers/s390/crypto/zcrypt_pcica.c
  43. 2 1
      drivers/s390/crypto/zcrypt_pcicc.c
  44. 4 1
      drivers/s390/crypto/zcrypt_pcixcc.c
  45. 64 101
      drivers/s390/net/claw.c
  46. 16 36
      drivers/s390/net/ctcm_main.c
  47. 1 7
      drivers/s390/net/ctcm_main.h
  48. 10 27
      drivers/s390/net/ctcm_sysfs.c
  49. 22 30
      drivers/s390/net/lcs.c
  50. 16 8
      drivers/s390/net/qeth_core.h
  51. 79 99
      drivers/s390/net/qeth_core_main.c
  52. 13 36
      drivers/s390/net/qeth_core_sys.c
  53. 7 9
      drivers/s390/net/qeth_l2_main.c
  54. 7 9
      drivers/s390/net/qeth_l3_main.c

+ 26 - 29
arch/s390/Kconfig

@@ -217,7 +217,7 @@ config COMPAT
 	def_bool y
 	def_bool y
 	prompt "Kernel support for 31 bit emulation"
 	prompt "Kernel support for 31 bit emulation"
 	depends on 64BIT
 	depends on 64BIT
-	select COMPAT_BINFMT_ELF
+	select COMPAT_BINFMT_ELF if BINFMT_ELF
 	select ARCH_WANT_OLD_COMPAT_IPC
 	select ARCH_WANT_OLD_COMPAT_IPC
 	help
 	help
 	  Select this option if you want to enable your system kernel to
 	  Select this option if you want to enable your system kernel to
@@ -234,6 +234,25 @@ config KEYS_COMPAT
 config AUDIT_ARCH
 config AUDIT_ARCH
 	def_bool y
 	def_bool y
 
 
+config HAVE_MARCH_Z900_FEATURES
+	def_bool n
+
+config HAVE_MARCH_Z990_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z900_FEATURES
+
+config HAVE_MARCH_Z9_109_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z990_FEATURES
+
+config HAVE_MARCH_Z10_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z9_109_FEATURES
+
+config HAVE_MARCH_Z196_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z10_FEATURES
+
 comment "Code generation options"
 comment "Code generation options"
 
 
 choice
 choice
@@ -249,6 +268,7 @@ config MARCH_G5
 
 
 config MARCH_Z900
 config MARCH_Z900
 	bool "IBM zSeries model z800 and z900"
 	bool "IBM zSeries model z800 and z900"
+	select HAVE_MARCH_Z900_FEATURES if 64BIT
 	help
 	help
 	  Select this to enable optimizations for model z800/z900 (2064 and
 	  Select this to enable optimizations for model z800/z900 (2064 and
 	  2066 series). This will enable some optimizations that are not
 	  2066 series). This will enable some optimizations that are not
@@ -256,6 +276,7 @@ config MARCH_Z900
 
 
 config MARCH_Z990
 config MARCH_Z990
 	bool "IBM zSeries model z890 and z990"
 	bool "IBM zSeries model z890 and z990"
+	select HAVE_MARCH_Z990_FEATURES if 64BIT
 	help
 	help
 	  Select this to enable optimizations for model z890/z990 (2084 and
 	  Select this to enable optimizations for model z890/z990 (2084 and
 	  2086 series). The kernel will be slightly faster but will not work
 	  2086 series). The kernel will be slightly faster but will not work
@@ -263,6 +284,7 @@ config MARCH_Z990
 
 
 config MARCH_Z9_109
 config MARCH_Z9_109
 	bool "IBM System z9"
 	bool "IBM System z9"
+	select HAVE_MARCH_Z9_109_FEATURES if 64BIT
 	help
 	help
 	  Select this to enable optimizations for IBM System z9 (2094 and
 	  Select this to enable optimizations for IBM System z9 (2094 and
 	  2096 series). The kernel will be slightly faster but will not work
 	  2096 series). The kernel will be slightly faster but will not work
@@ -270,6 +292,7 @@ config MARCH_Z9_109
 
 
 config MARCH_Z10
 config MARCH_Z10
 	bool "IBM System z10"
 	bool "IBM System z10"
+	select HAVE_MARCH_Z10_FEATURES if 64BIT
 	help
 	help
 	  Select this to enable optimizations for IBM System z10 (2097 and
 	  Select this to enable optimizations for IBM System z10 (2097 and
 	  2098 series). The kernel will be slightly faster but will not work
 	  2098 series). The kernel will be slightly faster but will not work
@@ -277,6 +300,7 @@ config MARCH_Z10
 
 
 config MARCH_Z196
 config MARCH_Z196
 	bool "IBM zEnterprise 114 and 196"
 	bool "IBM zEnterprise 114 and 196"
+	select HAVE_MARCH_Z196_FEATURES if 64BIT
 	help
 	help
 	  Select this to enable optimizations for IBM zEnterprise 114 and 196
 	  Select this to enable optimizations for IBM zEnterprise 114 and 196
 	  (2818 and 2817 series). The kernel will be slightly faster but will
 	  (2818 and 2817 series). The kernel will be slightly faster but will
@@ -406,33 +430,6 @@ config CHSC_SCH
 
 
 comment "Misc"
 comment "Misc"
 
 
-config IPL
-	def_bool y
-	prompt "Builtin IPL record support"
-	help
-	  If you want to use the produced kernel to IPL directly from a
-	  device, you have to merge a bootsector specific to the device
-	  into the first bytes of the kernel. You will have to select the
-	  IPL device.
-
-choice
-	prompt "IPL method generated into head.S"
-	depends on IPL
-	default IPL_VM
-	help
-	  Select "tape" if you want to IPL the image from a Tape.
-
-	  Select "vm_reader" if you are running under VM/ESA and want
-	  to IPL the image from the emulated card reader.
-
-config IPL_TAPE
-	bool "tape"
-
-config IPL_VM
-	bool "vm_reader"
-
-endchoice
-
 source "fs/Kconfig.binfmt"
 source "fs/Kconfig.binfmt"
 
 
 config FORCE_MAX_ZONEORDER
 config FORCE_MAX_ZONEORDER
@@ -569,7 +566,7 @@ config KEXEC
 
 
 config CRASH_DUMP
 config CRASH_DUMP
 	bool "kernel crash dumps"
 	bool "kernel crash dumps"
-	depends on 64BIT
+	depends on 64BIT && SMP
 	select KEXEC
 	select KEXEC
 	help
 	help
 	  Generate crash dump after being started by kexec.
 	  Generate crash dump after being started by kexec.

+ 2 - 0
arch/s390/boot/.gitignore

@@ -0,0 +1,2 @@
+image
+bzImage

+ 3 - 0
arch/s390/boot/compressed/.gitignore

@@ -0,0 +1,3 @@
+sizes.h
+vmlinux
+vmlinux.lds

+ 0 - 1
arch/s390/defconfig

@@ -155,7 +155,6 @@ CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SALSA20=m

+ 20 - 17
arch/s390/include/asm/barrier.h

@@ -11,25 +11,28 @@
  * Force strict CPU ordering.
  * Force strict CPU ordering.
  * And yes, this is required on UP too when we're talking
  * And yes, this is required on UP too when we're talking
  * to devices.
  * to devices.
- *
- * This is very similar to the ppc eieio/sync instruction in that is
- * does a checkpoint syncronisation & makes sure that 
- * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
  */
  */
 
 
-#define eieio()	asm volatile("bcr 15,0" : : : "memory")
-#define SYNC_OTHER_CORES(x)   eieio()
-#define mb()    eieio()
-#define rmb()   eieio()
-#define wmb()   eieio()
-#define read_barrier_depends() do { } while(0)
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()    read_barrier_depends()
-#define smp_mb__before_clear_bit()     smp_mb()
-#define smp_mb__after_clear_bit()      smp_mb()
+static inline void mb(void)
+{
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+	/* Fast-BCR without checkpoint synchronization */
+	asm volatile("bcr 14,0" : : : "memory");
+#else
+	asm volatile("bcr 15,0" : : : "memory");
+#endif
+}
+
+#define rmb()				mb()
+#define wmb()				mb()
+#define read_barrier_depends()		do { } while(0)
+#define smp_mb()			mb()
+#define smp_rmb()			rmb()
+#define smp_wmb()			wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
+#define smp_mb__before_clear_bit()	smp_mb()
+#define smp_mb__after_clear_bit()	smp_mb()
 
 
-#define set_mb(var, value)      do { var = value; mb(); } while (0)
+#define set_mb(var, value)		do { var = value; mb(); } while (0)
 
 
 #endif /* __ASM_BARRIER_H */
 #endif /* __ASM_BARRIER_H */

+ 4 - 10
arch/s390/include/asm/ccwgroup.h

@@ -29,9 +29,7 @@ struct ccwgroup_device {
 
 
 /**
 /**
  * struct ccwgroup_driver - driver for ccw group devices
  * struct ccwgroup_driver - driver for ccw group devices
- * @max_slaves: maximum number of slave devices
- * @driver_id: unique id
- * @probe: function called on probe
+ * @setup: function called during device creation to setup the device
  * @remove: function called on remove
  * @remove: function called on remove
  * @set_online: function called when device is set online
  * @set_online: function called when device is set online
  * @set_offline: function called when device is set offline
  * @set_offline: function called when device is set offline
@@ -44,10 +42,7 @@ struct ccwgroup_device {
  * @driver: embedded driver structure
  * @driver: embedded driver structure
  */
  */
 struct ccwgroup_driver {
 struct ccwgroup_driver {
-	int max_slaves;
-	unsigned long driver_id;
-
-	int (*probe) (struct ccwgroup_device *);
+	int (*setup) (struct ccwgroup_device *);
 	void (*remove) (struct ccwgroup_device *);
 	void (*remove) (struct ccwgroup_device *);
 	int (*set_online) (struct ccwgroup_device *);
 	int (*set_online) (struct ccwgroup_device *);
 	int (*set_offline) (struct ccwgroup_device *);
 	int (*set_offline) (struct ccwgroup_device *);
@@ -63,9 +58,8 @@ struct ccwgroup_driver {
 
 
 extern int  ccwgroup_driver_register   (struct ccwgroup_driver *cdriver);
 extern int  ccwgroup_driver_register   (struct ccwgroup_driver *cdriver);
 extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
 extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
-int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
-				struct ccw_driver *cdrv, int num_devices,
-				const char *buf);
+int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv,
+			int num_devices, const char *buf);
 
 
 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);

+ 2 - 5
arch/s390/include/asm/io.h

@@ -38,11 +38,8 @@ static inline void * phys_to_virt(unsigned long address)
 	return (void *) address;
 	return (void *) address;
 }
 }
 
 
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
+void *xlate_dev_mem_ptr(unsigned long phys);
+void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
 
 
 /*
 /*
  * Convert a virtual cached pointer to an uncached pointer
  * Convert a virtual cached pointer to an uncached pointer

+ 9 - 10
arch/s390/include/asm/qdio.h

@@ -258,11 +258,6 @@ struct slsb {
 	u8 val[QDIO_MAX_BUFFERS_PER_Q];
 	u8 val[QDIO_MAX_BUFFERS_PER_Q];
 } __attribute__ ((packed, aligned(256)));
 } __attribute__ ((packed, aligned(256)));
 
 
-#define CHSC_AC2_MULTI_BUFFER_AVAILABLE	0x0080
-#define CHSC_AC2_MULTI_BUFFER_ENABLED	0x0040
-#define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
-#define CHSC_AC2_DATA_DIV_ENABLED	0x0002
-
 /**
 /**
  * struct qdio_outbuf_state - SBAL related asynchronous operation information
  * struct qdio_outbuf_state - SBAL related asynchronous operation information
  *   (for communication with upper layer programs)
  *   (for communication with upper layer programs)
@@ -293,6 +288,8 @@ struct qdio_outbuf_state {
 #define AC1_SC_QEBSM_AVAILABLE		0x02	/* available for subchannel */
 #define AC1_SC_QEBSM_AVAILABLE		0x02	/* available for subchannel */
 #define AC1_SC_QEBSM_ENABLED		0x01	/* enabled for subchannel */
 #define AC1_SC_QEBSM_ENABLED		0x01	/* enabled for subchannel */
 
 
+#define CHSC_AC2_MULTI_BUFFER_AVAILABLE	0x0080
+#define CHSC_AC2_MULTI_BUFFER_ENABLED	0x0040
 #define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
 #define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010
 #define CHSC_AC2_DATA_DIV_ENABLED	0x0002
 #define CHSC_AC2_DATA_DIV_ENABLED	0x0002
 
 
@@ -328,11 +325,13 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
 			    int, int, unsigned long);
 			    int, int, unsigned long);
 
 
 /* qdio errors reported to the upper-layer program */
 /* qdio errors reported to the upper-layer program */
-#define QDIO_ERROR_SIGA_TARGET			0x02
-#define QDIO_ERROR_SIGA_ACCESS_EXCEPTION	0x10
-#define QDIO_ERROR_SIGA_BUSY			0x20
-#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION	0x40
-#define QDIO_ERROR_SLSB_STATE			0x80
+#define QDIO_ERROR_ACTIVATE			0x0001
+#define QDIO_ERROR_GET_BUF_STATE		0x0002
+#define QDIO_ERROR_SET_BUF_STATE		0x0004
+#define QDIO_ERROR_SLSB_STATE			0x0100
+
+#define QDIO_ERROR_FATAL			0x00ff
+#define QDIO_ERROR_TEMPORARY			0xff00
 
 
 /* for qdio_cleanup */
 /* for qdio_cleanup */
 #define QDIO_FLAG_CLEANUP_USING_CLEAR		0x01
 #define QDIO_FLAG_CLEANUP_USING_CLEAR		0x01

+ 0 - 3
arch/s390/include/asm/setup.h

@@ -82,7 +82,6 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_LPAR	(1UL << 12)
 #define MACHINE_FLAG_LPAR	(1UL << 12)
 #define MACHINE_FLAG_SPP	(1UL << 13)
 #define MACHINE_FLAG_SPP	(1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY	(1UL << 14)
 #define MACHINE_FLAG_TOPOLOGY	(1UL << 14)
-#define MACHINE_FLAG_STCKF	(1UL << 15)
 
 
 #define MACHINE_IS_VM		(S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_VM		(S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM		(S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
 #define MACHINE_IS_KVM		(S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -101,7 +100,6 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF	(0)
 #define MACHINE_HAS_PFMF	(0)
 #define MACHINE_HAS_SPP		(0)
 #define MACHINE_HAS_SPP		(0)
 #define MACHINE_HAS_TOPOLOGY	(0)
 #define MACHINE_HAS_TOPOLOGY	(0)
-#define MACHINE_HAS_STCKF	(0)
 #else /* __s390x__ */
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE	(1)
 #define MACHINE_HAS_IEEE	(1)
 #define MACHINE_HAS_CSP		(1)
 #define MACHINE_HAS_CSP		(1)
@@ -113,7 +111,6 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF	(S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_PFMF	(S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP		(S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_SPP		(S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY	(S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
 #define MACHINE_HAS_TOPOLOGY	(S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
-#define MACHINE_HAS_STCKF	(S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
 #endif /* __s390x__ */
 #endif /* __s390x__ */
 
 
 #define ZFCPDUMP_HSA_SIZE	(32UL<<20)
 #define ZFCPDUMP_HSA_SIZE	(32UL<<20)

+ 0 - 2
arch/s390/include/asm/thread_info.h

@@ -95,7 +95,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
 #define TIF_SECCOMP		10	/* secure computing */
 #define TIF_SECCOMP		10	/* secure computing */
 #define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */
 #define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */
-#define TIF_SIE			12	/* guest execution active */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 					   TIF_NEED_RESCHED */
 #define TIF_31BIT		17	/* 32bit process */
 #define TIF_31BIT		17	/* 32bit process */
@@ -114,7 +113,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
-#define _TIF_SIE		(1<<TIF_SIE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
 #define _TIF_31BIT		(1<<TIF_31BIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)

+ 5 - 12
arch/s390/include/asm/timex.h

@@ -73,11 +73,15 @@ static inline void local_tick_enable(unsigned long long comp)
 
 
 typedef unsigned long long cycles_t;
 typedef unsigned long long cycles_t;
 
 
-static inline unsigned long long get_clock (void)
+static inline unsigned long long get_clock(void)
 {
 {
 	unsigned long long clk;
 	unsigned long long clk;
 
 
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+	asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
+#else
 	asm volatile("stck %0" : "=Q" (clk) : : "cc");
 	asm volatile("stck %0" : "=Q" (clk) : : "cc");
+#endif
 	return clk;
 	return clk;
 }
 }
 
 
@@ -86,17 +90,6 @@ static inline void get_clock_ext(char *clk)
 	asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
 	asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
 }
 }
 
 
-static inline unsigned long long get_clock_fast(void)
-{
-	unsigned long long clk;
-
-	if (MACHINE_HAS_STCKF)
-		asm volatile(".insn	s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
-	else
-		clk = get_clock();
-	return clk;
-}
-
 static inline unsigned long long get_clock_xt(void)
 static inline unsigned long long get_clock_xt(void)
 {
 {
 	unsigned char clk[16];
 	unsigned char clk[16];

+ 1 - 0
arch/s390/kernel/.gitignore

@@ -0,0 +1 @@
+vmlinux.lds

+ 0 - 7
arch/s390/kernel/compat_signal.c

@@ -437,13 +437,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 			sp = current->sas_ss_sp + current->sas_ss_size;
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	}
 
 
-	/* This is the legacy signal stack switching. */
-	else if (!user_mode(regs) &&
-		 !(ka->sa.sa_flags & SA_RESTORER) &&
-		 ka->sa.sa_restorer) {
-		sp = (unsigned long) ka->sa.sa_restorer;
-	}
-
 	return (void __user *)((sp - frame_size) & -8ul);
 	return (void __user *)((sp - frame_size) & -8ul);
 }
 }
 
 

+ 0 - 2
arch/s390/kernel/early.c

@@ -374,8 +374,6 @@ static __init void detect_machine_facilities(void)
 		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
 		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
 	if (test_facility(40))
 	if (test_facility(40))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
 		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
-	if (test_facility(25))
-		S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
 #endif
 #endif
 }
 }
 
 

+ 11 - 10
arch/s390/kernel/entry.S

@@ -145,22 +145,23 @@ STACK_SIZE  = 1 << STACK_SHIFT
  *  gpr2 = prev
  *  gpr2 = prev
  */
  */
 ENTRY(__switch_to)
 ENTRY(__switch_to)
+	stm	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
+	st	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
 	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	l	%r5,__THREAD_info(%r3)		# get thread_info of next
 	l	%r5,__THREAD_info(%r3)		# get thread_info of next
+	lr	%r15,%r5
+	ahi	%r15,STACK_SIZE			# end of kernel stack of next
+	st	%r3,__LC_CURRENT		# store task struct of next
+	st	%r5,__LC_THREAD_INFO		# store thread info of next
+	st	%r15,__LC_KERNEL_STACK		# store end of kernel stack
+	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
+	mvc	__LC_CURRENT_PID(4,%r0),__TASK_pid(%r3)	# store pid of next
+	l	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
 	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
 	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
 	jz	0f
 	jz	0f
 	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
 	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
 	oi	__TI_flags+3(%r5),_TIF_MCCK_PENDING	# set it in next
 	oi	__TI_flags+3(%r5),_TIF_MCCK_PENDING	# set it in next
-0:	stm	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
-	st	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
-	l	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
-	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
-	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
-	st	%r3,__LC_CURRENT		# store task struct of next
-	mvc	__LC_CURRENT_PID(4,%r0),__TASK_pid(%r3)	# store pid of next
-	st	%r5,__LC_THREAD_INFO		# store thread info of next
-	ahi	%r5,STACK_SIZE			# end of kernel stack of next
-	st	%r5,__LC_KERNEL_STACK		# store end of kernel stack
+0:	lm	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
 	br	%r14
 	br	%r14
 
 
 __critical_start:
 __critical_start:

+ 28 - 23
arch/s390/kernel/entry64.S

@@ -81,16 +81,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 
 	.macro	HANDLE_SIE_INTERCEPT scratch
 	.macro	HANDLE_SIE_INTERCEPT scratch
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-	tm	__TI_flags+6(%r12),_TIF_SIE>>8
-	jz	.+42
-	tm	__LC_MACHINE_FLAGS+6,0x20	# MACHINE_FLAG_SPP
-	jz	.+8
-	.insn	s,0xb2800000,BASED(.Lhost_id)	# set host id
+	tmhh	%r8,0x0001		# interrupting from user ?
+	jnz	.+42
 	lgr	\scratch,%r9
 	lgr	\scratch,%r9
 	slg	\scratch,BASED(.Lsie_loop)
 	slg	\scratch,BASED(.Lsie_loop)
 	clg	\scratch,BASED(.Lsie_length)
 	clg	\scratch,BASED(.Lsie_length)
-	jhe	.+10
+	jhe	.+22
 	lg	%r9,BASED(.Lsie_loop)
 	lg	%r9,BASED(.Lsie_loop)
+	SPP	BASED(.Lhost_id)	# set host id
 #endif
 #endif
 	.endm
 	.endm
 
 
@@ -148,6 +146,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 	ssm	__LC_RETURN_PSW
 	ssm	__LC_RETURN_PSW
 	.endm
 	.endm
 
 
+	.macro STCK savearea
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+	.insn	s,0xb27c0000,\savearea		# store clock fast
+#else
+	.insn	s,0xb2050000,\savearea		# store clock
+#endif
+	.endm
+
 	.section .kprobes.text, "ax"
 	.section .kprobes.text, "ax"
 
 
 /*
 /*
@@ -158,22 +164,23 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
  *  gpr2 = prev
  *  gpr2 = prev
  */
  */
 ENTRY(__switch_to)
 ENTRY(__switch_to)
+	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
+	stg	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
 	lg	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	lg	%r4,__THREAD_info(%r2)		# get thread_info of prev
 	lg	%r5,__THREAD_info(%r3)		# get thread_info of next
 	lg	%r5,__THREAD_info(%r3)		# get thread_info of next
+	lgr	%r15,%r5
+	aghi	%r15,STACK_SIZE			# end of kernel stack of next
+	stg	%r3,__LC_CURRENT		# store task struct of next
+	stg	%r5,__LC_THREAD_INFO		# store thread info of next
+	stg	%r15,__LC_KERNEL_STACK		# store end of kernel stack
+	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
+	mvc	__LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
+	lg	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
 	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
 	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
 	jz	0f
 	jz	0f
 	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
 	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING	# clear flag in prev
 	oi	__TI_flags+7(%r5),_TIF_MCCK_PENDING	# set it in next
 	oi	__TI_flags+7(%r5),_TIF_MCCK_PENDING	# set it in next
-0:	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
-	stg	%r15,__THREAD_ksp(%r2)		# store kernel stack of prev
-	lg	%r15,__THREAD_ksp(%r3)		# load kernel stack of next
-	lctl	%c4,%c4,__TASK_pid(%r3)		# load pid to control reg. 4
-	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
-	stg	%r3,__LC_CURRENT		# store task struct of next
-	mvc	__LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
-	stg	%r5,__LC_THREAD_INFO		# store thread info of next
-	aghi	%r5,STACK_SIZE			# end of kernel stack of next
-	stg	%r5,__LC_KERNEL_STACK		# store end of kernel stack
+0:	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
 	br	%r14
 	br	%r14
 
 
 __critical_start:
 __critical_start:
@@ -458,7 +465,7 @@ pgm_svcper:
  * IO interrupt handler routine
  * IO interrupt handler routine
  */
  */
 ENTRY(io_int_handler)
 ENTRY(io_int_handler)
-	stck	__LC_INT_CLOCK
+	STCK	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
 	stpt	__LC_ASYNC_ENTER_TIMER
 	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
 	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
 	lg	%r10,__LC_LAST_BREAK
 	lg	%r10,__LC_LAST_BREAK
@@ -604,7 +611,7 @@ io_notify_resume:
  * External interrupt handler routine
  * External interrupt handler routine
  */
  */
 ENTRY(ext_int_handler)
 ENTRY(ext_int_handler)
-	stck	__LC_INT_CLOCK
+	STCK	__LC_INT_CLOCK
 	stpt	__LC_ASYNC_ENTER_TIMER
 	stpt	__LC_ASYNC_ENTER_TIMER
 	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
 	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
 	lg	%r10,__LC_LAST_BREAK
 	lg	%r10,__LC_LAST_BREAK
@@ -622,6 +629,7 @@ ext_skip:
 	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
 	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
 	stmg	%r8,%r9,__PT_PSW(%r11)
 	stmg	%r8,%r9,__PT_PSW(%r11)
 	TRACE_IRQS_OFF
 	TRACE_IRQS_OFF
+	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 	lghi	%r1,4096
 	lghi	%r1,4096
 	lgr	%r2,%r11		# pass pointer to pt_regs
 	lgr	%r2,%r11		# pass pointer to pt_regs
 	llgf	%r3,__LC_EXT_CPU_ADDR	# get cpu address + interruption code
 	llgf	%r3,__LC_EXT_CPU_ADDR	# get cpu address + interruption code
@@ -638,7 +646,7 @@ ENTRY(psw_idle)
 	larl	%r1,psw_idle_lpsw+4
 	larl	%r1,psw_idle_lpsw+4
 	stg	%r1,__SF_EMPTY+8(%r15)
 	stg	%r1,__SF_EMPTY+8(%r15)
 	larl	%r1,.Lvtimer_max
 	larl	%r1,.Lvtimer_max
-	stck	__IDLE_ENTER(%r2)
+	STCK	__IDLE_ENTER(%r2)
 	ltr	%r5,%r5
 	ltr	%r5,%r5
 	stpt	__VQ_IDLE_ENTER(%r3)
 	stpt	__VQ_IDLE_ENTER(%r3)
 	jz	psw_idle_lpsw
 	jz	psw_idle_lpsw
@@ -654,7 +662,7 @@ __critical_end:
  * Machine check handler routines
  * Machine check handler routines
  */
  */
 ENTRY(mcck_int_handler)
 ENTRY(mcck_int_handler)
-	stck	__LC_MCCK_CLOCK
+	STCK	__LC_MCCK_CLOCK
 	la	%r1,4095		# revalidate r1
 	la	%r1,4095		# revalidate r1
 	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
 	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
 	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
 	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
@@ -967,7 +975,6 @@ ENTRY(sie64a)
 	xc	__SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
 	xc	__SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
 	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
 	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
-	oi	__TI_flags+6(%r14),_TIF_SIE>>8
 sie_loop:
 sie_loop:
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	tm	__TI_flags+7(%r14),_TIF_EXIT_SIE
 	tm	__TI_flags+7(%r14),_TIF_EXIT_SIE
@@ -985,7 +992,6 @@ sie_done:
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 sie_exit:
 sie_exit:
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
-	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
 	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
 	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
 	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
 	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
@@ -994,7 +1000,6 @@ sie_exit:
 sie_fault:
 sie_fault:
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
 	lg	%r14,__LC_THREAD_INFO		# pointer thread_info struct
-	ni	__TI_flags+6(%r14),255-(_TIF_SIE>>8)
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
 	lg	%r14,__SF_EMPTY+8(%r15)		# load guest register save area
 	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
 	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
 	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
 	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers

+ 0 - 123
arch/s390/kernel/head.S

@@ -34,125 +34,7 @@
 #endif
 #endif
 
 
 __HEAD
 __HEAD
-#ifndef CONFIG_IPL
-	.org   0
-	.long  0x00080000,0x80000000+startup	# Just a restart PSW
-#else
-#ifdef CONFIG_IPL_TAPE
-#define IPL_BS 1024
-	.org   0
-	.long  0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
-	.long  0x27000000,0x60000001		# by ipl to addresses 0-23.
-	.long  0x02000000,0x20000000+IPL_BS	# (a PSW and two CCWs).
-	.long  0x00000000,0x00000000		# external old psw
-	.long  0x00000000,0x00000000		# svc old psw
-	.long  0x00000000,0x00000000		# program check old psw
-	.long  0x00000000,0x00000000		# machine check old psw
-	.long  0x00000000,0x00000000		# io old psw
-	.long  0x00000000,0x00000000
-	.long  0x00000000,0x00000000
-	.long  0x00000000,0x00000000
-	.long  0x000a0000,0x00000058		# external new psw
-	.long  0x000a0000,0x00000060		# svc new psw
-	.long  0x000a0000,0x00000068		# program check new psw
-	.long  0x000a0000,0x00000070		# machine check new psw
-	.long  0x00080000,0x80000000+.Lioint	# io new psw
 
 
-	.org   0x100
-#
-# subroutine for loading from tape
-# Parameters:
-#  R1 = device number
-#  R2 = load address
-.Lloader:
-	st	%r14,.Lldret
-	la	%r3,.Lorbread		# r3 = address of orb
-	la	%r5,.Lirb		# r5 = address of irb
-	st	%r2,.Lccwread+4 	# initialize CCW data addresses
-	lctl	%c6,%c6,.Lcr6
-	slr	%r2,%r2
-.Lldlp:
-	la	%r6,3			# 3 retries
-.Lssch:
-	ssch	0(%r3)			# load chunk of IPL_BS bytes
-	bnz	.Llderr
-.Lw4end:
-	bas	%r14,.Lwait4io
-	tm	8(%r5),0x82		# do we have a problem ?
-	bnz	.Lrecov
-	slr	%r7,%r7
-	icm	%r7,3,10(%r5)		# get residual count
-	lcr	%r7,%r7
-	la	%r7,IPL_BS(%r7) 	# IPL_BS-residual=#bytes read
-	ar	%r2,%r7 		# add to total size
-	tm	8(%r5),0x01		# found a tape mark ?
-	bnz	.Ldone
-	l	%r0,.Lccwread+4 	# update CCW data addresses
-	ar	%r0,%r7
-	st	%r0,.Lccwread+4
-	b	.Lldlp
-.Ldone:
-	l	%r14,.Lldret
-	br	%r14			# r2 contains the total size
-.Lrecov:
-	bas	%r14,.Lsense		# do the sensing
-	bct	%r6,.Lssch		# dec. retry count & branch
-	b	.Llderr
-#
-# Sense subroutine
-#
-.Lsense:
-	st	%r14,.Lsnsret
-	la	%r7,.Lorbsense
-	ssch	0(%r7)			# start sense command
-	bnz	.Llderr
-	bas	%r14,.Lwait4io
-	l	%r14,.Lsnsret
-	tm	8(%r5),0x82		# do we have a problem ?
-	bnz	.Llderr
-	br	%r14
-#
-# Wait for interrupt subroutine
-#
-.Lwait4io:
-	lpsw	.Lwaitpsw
-.Lioint:
-	c	%r1,0xb8		# compare subchannel number
-	bne	.Lwait4io
-	tsch	0(%r5)
-	slr	%r0,%r0
-	tm	8(%r5),0x82		# do we have a problem ?
-	bnz	.Lwtexit
-	tm	8(%r5),0x04		# got device end ?
-	bz	.Lwait4io
-.Lwtexit:
-	br	%r14
-.Llderr:
-	lpsw	.Lcrash
-
-	.align	8
-.Lorbread:
-	.long	0x00000000,0x0080ff00,.Lccwread
-	.align	8
-.Lorbsense:
-	.long	0x00000000,0x0080ff00,.Lccwsense
-	.align	8
-.Lccwread:
-	.long	0x02200000+IPL_BS,0x00000000
-.Lccwsense:
-	.long	0x04200001,0x00000000
-.Lwaitpsw:
-	.long	0x020a0000,0x80000000+.Lioint
-
-.Lirb:	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6:	.long	0xff000000
-	.align	8
-.Lcrash:.long	0x000a0000,0x00000000
-.Lldret:.long	0
-.Lsnsret: .long 0
-#endif	/* CONFIG_IPL_TAPE */
-
-#ifdef CONFIG_IPL_VM
 #define IPL_BS	0x730
 #define IPL_BS	0x730
 	.org	0
 	.org	0
 	.long	0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
 	.long	0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
@@ -256,7 +138,6 @@ __HEAD
 	.long	0x02600050,0x00000000
 	.long	0x02600050,0x00000000
 	.endr
 	.endr
 	.long	0x02200050,0x00000000
 	.long	0x02200050,0x00000000
-#endif	/* CONFIG_IPL_VM */
 
 
 iplstart:
 iplstart:
 	lh	%r1,0xb8		# test if subchannel number
 	lh	%r1,0xb8		# test if subchannel number
@@ -325,7 +206,6 @@ iplstart:
 	clc	0(3,%r2),.L_eof
 	clc	0(3,%r2),.L_eof
 	bz	.Lagain2
 	bz	.Lagain2
 
 
-#ifdef CONFIG_IPL_VM
 #
 #
 # reset files in VM reader
 # reset files in VM reader
 #
 #
@@ -358,7 +238,6 @@ iplstart:
 	.long	0x00080000,0x80000000+.Lrdrint
 	.long	0x00080000,0x80000000+.Lrdrint
 .Lrdrwaitpsw:
 .Lrdrwaitpsw:
 	.long	0x020a0000,0x80000000+.Lrdrint
 	.long	0x020a0000,0x80000000+.Lrdrint
-#endif
 
 
 #
 #
 # everything loaded, go for it
 # everything loaded, go for it
@@ -376,8 +255,6 @@ iplstart:
 .L_eof: .long	0xc5d6c600	 /* C'EOF' */
 .L_eof: .long	0xc5d6c600	 /* C'EOF' */
 .L_hdr: .long	0xc8c4d900	 /* C'HDR' */
 .L_hdr: .long	0xc8c4d900	 /* C'HDR' */
 
 
-#endif	/* CONFIG_IPL */
-
 #
 #
 # SALIPL loader support. Based on a patch by Rob van der Heij.
 # SALIPL loader support. Based on a patch by Rob van der Heij.
 # This entry point is called directly from the SALIPL loader and
 # This entry point is called directly from the SALIPL loader and

+ 0 - 16
arch/s390/kernel/signal.c

@@ -235,13 +235,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 			sp = current->sas_ss_sp + current->sas_ss_size;
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	}
 
 
-	/* This is the legacy signal stack switching. */
-	else if (!user_mode(regs) &&
-		 !(ka->sa.sa_flags & SA_RESTORER) &&
-		 ka->sa.sa_restorer) {
-		sp = (unsigned long) ka->sa.sa_restorer;
-	}
-
 	return (void __user *)((sp - frame_size) & -8ul);
 	return (void __user *)((sp - frame_size) & -8ul);
 }
 }
 
 
@@ -414,15 +407,6 @@ void do_signal(struct pt_regs *regs)
 	struct k_sigaction ka;
 	struct k_sigaction ka;
 	sigset_t *oldset;
 	sigset_t *oldset;
 
 
-	/*
-	 * We want the common case to go fast, which
-	 * is why we may in certain cases get here from
-	 * kernel mode. Just return without doing anything
-	 * if so.
-	 */
-	if (!user_mode(regs))
-		return;
-
 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
 		oldset = &current->saved_sigmask;
 		oldset = &current->saved_sigmask;
 	else
 	else

+ 4 - 0
arch/s390/kernel/smp.c

@@ -226,6 +226,8 @@ out:
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
 
 
+#ifdef CONFIG_HOTPLUG_CPU
+
 static void pcpu_free_lowcore(struct pcpu *pcpu)
 static void pcpu_free_lowcore(struct pcpu *pcpu)
 {
 {
 	pcpu_sigp_retry(pcpu, sigp_set_prefix, 0);
 	pcpu_sigp_retry(pcpu, sigp_set_prefix, 0);
@@ -247,6 +249,8 @@ static void pcpu_free_lowcore(struct pcpu *pcpu)
 	}
 	}
 }
 }
 
 
+#endif /* CONFIG_HOTPLUG_CPU */
+
 static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
 static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
 {
 {
 	struct _lowcore *lc = pcpu->lowcore;
 	struct _lowcore *lc = pcpu->lowcore;

+ 1 - 0
arch/s390/kernel/vdso32/.gitignore

@@ -0,0 +1 @@
+vdso32.lds

+ 1 - 0
arch/s390/kernel/vdso64/.gitignore

@@ -0,0 +1 @@
+vdso64.lds

+ 27 - 18
arch/s390/mm/fault.c

@@ -294,7 +294,7 @@ static inline int do_exception(struct pt_regs *regs, int access)
 	down_read(&mm->mmap_sem);
 	down_read(&mm->mmap_sem);
 
 
 #ifdef CONFIG_PGSTE
 #ifdef CONFIG_PGSTE
-	if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
+	if ((current->flags & PF_VCPU) && S390_lowcore.gmap) {
 		address = __gmap_fault(address,
 		address = __gmap_fault(address,
 				     (struct gmap *) S390_lowcore.gmap);
 				     (struct gmap *) S390_lowcore.gmap);
 		if (address == -EFAULT) {
 		if (address == -EFAULT) {
@@ -549,19 +549,15 @@ static void pfault_interrupt(struct ext_code ext_code,
 	if ((subcode & 0xff00) != __SUBCODE_MASK)
 	if ((subcode & 0xff00) != __SUBCODE_MASK)
 		return;
 		return;
 	kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
 	kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
-	if (subcode & 0x0080) {
-		/* Get the token (= pid of the affected task). */
-		pid = sizeof(void *) == 4 ? param32 : param64;
-		rcu_read_lock();
-		tsk = find_task_by_pid_ns(pid, &init_pid_ns);
-		if (tsk)
-			get_task_struct(tsk);
-		rcu_read_unlock();
-		if (!tsk)
-			return;
-	} else {
-		tsk = current;
-	}
+	/* Get the token (= pid of the affected task). */
+	pid = sizeof(void *) == 4 ? param32 : param64;
+	rcu_read_lock();
+	tsk = find_task_by_pid_ns(pid, &init_pid_ns);
+	if (tsk)
+		get_task_struct(tsk);
+	rcu_read_unlock();
+	if (!tsk)
+		return;
 	spin_lock(&pfault_lock);
 	spin_lock(&pfault_lock);
 	if (subcode & 0x0080) {
 	if (subcode & 0x0080) {
 		/* signal bit is set -> a page has been swapped in by VM */
 		/* 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,
 			tsk->thread.pfault_wait = 0;
 			tsk->thread.pfault_wait = 0;
 			list_del(&tsk->thread.list);
 			list_del(&tsk->thread.list);
 			wake_up_process(tsk);
 			wake_up_process(tsk);
+			put_task_struct(tsk);
 		} else {
 		} else {
 			/* Completion interrupt was faster than initial
 			/* Completion interrupt was faster than initial
 			 * interrupt. Set pfault_wait to -1 so the initial
 			 * interrupt. Set pfault_wait to -1 so the initial
@@ -585,24 +582,35 @@ static void pfault_interrupt(struct ext_code ext_code,
 			if (tsk->state == TASK_RUNNING)
 			if (tsk->state == TASK_RUNNING)
 				tsk->thread.pfault_wait = -1;
 				tsk->thread.pfault_wait = -1;
 		}
 		}
-		put_task_struct(tsk);
 	} else {
 	} else {
 		/* signal bit not set -> a real page is missing. */
 		/* signal bit not set -> a real page is missing. */
-		if (tsk->thread.pfault_wait == -1) {
+		if (WARN_ON_ONCE(tsk != current))
+			goto out;
+		if (tsk->thread.pfault_wait == 1) {
+			/* Already on the list with a reference: put to sleep */
+			__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			set_tsk_need_resched(tsk);
+		} else if (tsk->thread.pfault_wait == -1) {
 			/* Completion interrupt was faster than the initial
 			/* Completion interrupt was faster than the initial
 			 * interrupt (pfault_wait == -1). Set pfault_wait
 			 * interrupt (pfault_wait == -1). Set pfault_wait
 			 * back to zero and exit. */
 			 * back to zero and exit. */
 			tsk->thread.pfault_wait = 0;
 			tsk->thread.pfault_wait = 0;
 		} else {
 		} else {
 			/* Initial interrupt arrived before completion
 			/* Initial interrupt arrived before completion
-			 * interrupt. Let the task sleep. */
+			 * interrupt. Let the task sleep.
+			 * An extra task reference is needed since a different
+			 * cpu may set the task state to TASK_RUNNING again
+			 * before the scheduler is reached. */
+			get_task_struct(tsk);
 			tsk->thread.pfault_wait = 1;
 			tsk->thread.pfault_wait = 1;
 			list_add(&tsk->thread.list, &pfault_list);
 			list_add(&tsk->thread.list, &pfault_list);
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 			set_tsk_need_resched(tsk);
 			set_tsk_need_resched(tsk);
 		}
 		}
 	}
 	}
+out:
 	spin_unlock(&pfault_lock);
 	spin_unlock(&pfault_lock);
+	put_task_struct(tsk);
 }
 }
 
 
 static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
 static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
@@ -620,6 +628,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
 			list_del(&thread->list);
 			list_del(&thread->list);
 			tsk = container_of(thread, struct task_struct, thread);
 			tsk = container_of(thread, struct task_struct, thread);
 			wake_up_process(tsk);
 			wake_up_process(tsk);
+			put_task_struct(tsk);
 		}
 		}
 		spin_unlock_irq(&pfault_lock);
 		spin_unlock_irq(&pfault_lock);
 		break;
 		break;

+ 2 - 0
arch/s390/mm/hugetlbpage.c

@@ -58,6 +58,8 @@ void arch_release_hugepage(struct page *page)
 	ptep = (pte_t *) page[1].index;
 	ptep = (pte_t *) page[1].index;
 	if (!ptep)
 	if (!ptep)
 		return;
 		return;
+	clear_table((unsigned long *) ptep, _PAGE_TYPE_EMPTY,
+		    PTRS_PER_PTE * sizeof(pte_t));
 	page_table_free(&init_mm, (unsigned long *) ptep);
 	page_table_free(&init_mm, (unsigned long *) ptep);
 	page[1].index = 0;
 	page[1].index = 0;
 }
 }

+ 67 - 0
arch/s390/mm/maccess.c

@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/gfp.h>
 #include <linux/gfp.h>
+#include <linux/cpu.h>
 #include <asm/ctl_reg.h>
 #include <asm/ctl_reg.h>
 
 
 /*
 /*
@@ -166,3 +167,69 @@ out:
 	free_page((unsigned long) buf);
 	free_page((unsigned long) buf);
 	return rc;
 	return rc;
 }
 }
+
+/*
+ * Check if physical address is within prefix or zero page
+ */
+static int is_swapped(unsigned long addr)
+{
+	unsigned long lc;
+	int cpu;
+
+	if (addr < sizeof(struct _lowcore))
+		return 1;
+	for_each_online_cpu(cpu) {
+		lc = (unsigned long) lowcore_ptr[cpu];
+		if (addr > lc + sizeof(struct _lowcore) - 1 || addr < lc)
+			continue;
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * Return swapped prefix or zero page address
+ */
+static unsigned long get_swapped(unsigned long addr)
+{
+	unsigned long prefix = store_prefix();
+
+	if (addr < sizeof(struct _lowcore))
+		return addr + prefix;
+	if (addr >= prefix && addr < prefix + sizeof(struct _lowcore))
+		return addr - prefix;
+	return addr;
+}
+
+/*
+ * Convert a physical pointer for /dev/mem access
+ *
+ * For swapped prefix pages a new buffer is returned that contains a copy of
+ * the absolute memory. The buffer size is maximum one page large.
+ */
+void *xlate_dev_mem_ptr(unsigned long addr)
+{
+	void *bounce = (void *) addr;
+	unsigned long size;
+
+	get_online_cpus();
+	preempt_disable();
+	if (is_swapped(addr)) {
+		size = PAGE_SIZE - (addr & ~PAGE_MASK);
+		bounce = (void *) __get_free_page(GFP_ATOMIC);
+		if (bounce)
+			memcpy_real(bounce, (void *) get_swapped(addr), size);
+	}
+	preempt_enable();
+	put_online_cpus();
+	return bounce;
+}
+
+/*
+ * Free converted buffer for /dev/mem access (if necessary)
+ */
+void unxlate_dev_mem_ptr(unsigned long addr, void *buf)
+{
+	if ((void *) addr != buf)
+		free_page((unsigned long) buf);
+}

+ 2 - 0
arch/s390/mm/pgtable.c

@@ -822,6 +822,8 @@ int s390_enable_sie(void)
 
 
 	/* we copy the mm and let dup_mm create the page tables with_pgstes */
 	/* we copy the mm and let dup_mm create the page tables with_pgstes */
 	tsk->mm->context.alloc_pgste = 1;
 	tsk->mm->context.alloc_pgste = 1;
+	/* make sure that both mms have a correct rss state */
+	sync_mm_rss(tsk->mm);
 	mm = dup_mm(tsk);
 	mm = dup_mm(tsk);
 	tsk->mm->context.alloc_pgste = 0;
 	tsk->mm->context.alloc_pgste = 0;
 	if (!mm)
 	if (!mm)

+ 1 - 1
block/partitions/ibm.c

@@ -253,7 +253,7 @@ int ibm_partition(struct parsed_partitions *state)
 				/* Are we not supposed to report this ? */
 				/* Are we not supposed to report this ? */
 				goto out_readerr;
 				goto out_readerr;
 		} else
 		} else
-			printk(KERN_WARNING "Warning, expected Label VOL1 not "
+			printk(KERN_INFO "Expected Label VOL1 not "
 			       "found, treating as CDL formated Disk");
 			       "found, treating as CDL formated Disk");
 
 
 	}
 	}

+ 1 - 0
drivers/crypto/Kconfig

@@ -111,6 +111,7 @@ config CRYPTO_DES_S390
 	depends on S390
 	depends on S390
 	select CRYPTO_ALGAPI
 	select CRYPTO_ALGAPI
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_BLKCIPHER
+	select CRYPTO_DES
 	help
 	help
 	  This is the s390 hardware accelerated implementation of the
 	  This is the s390 hardware accelerated implementation of the
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).

+ 11 - 1
drivers/s390/char/sclp_cmd.c

@@ -352,7 +352,17 @@ out:
 
 
 static int sclp_assign_storage(u16 rn)
 static int sclp_assign_storage(u16 rn)
 {
 {
-	return do_assign_storage(0x000d0001, rn);
+	unsigned long long start, address;
+	int rc;
+
+	rc = do_assign_storage(0x000d0001, rn);
+	if (rc)
+		goto out;
+	start = address = rn2addr(rn);
+	for (; address < start + rzm; address += PAGE_SIZE)
+		page_set_storage_key(address, PAGE_DEFAULT_KEY, 0);
+out:
+	return rc;
 }
 }
 
 
 static int sclp_unassign_storage(u16 rn)
 static int sclp_unassign_storage(u16 rn)

+ 0 - 43
drivers/s390/char/tape.h

@@ -154,12 +154,6 @@ struct tape_discipline {
 	struct tape_request *(*read_block)(struct tape_device *, size_t);
 	struct tape_request *(*read_block)(struct tape_device *, size_t);
 	struct tape_request *(*write_block)(struct tape_device *, size_t);
 	struct tape_request *(*write_block)(struct tape_device *, size_t);
 	void (*process_eov)(struct tape_device*);
 	void (*process_eov)(struct tape_device*);
-#ifdef CONFIG_S390_TAPE_BLOCK
-	/* Block device stuff. */
-	struct tape_request *(*bread)(struct tape_device *, struct request *);
-	void (*check_locate)(struct tape_device *, struct tape_request *);
-	void (*free_bread)(struct tape_request *);
-#endif
 	/* ioctl function for additional ioctls. */
 	/* ioctl function for additional ioctls. */
 	int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
 	int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
 	/* Array of tape commands with TAPE_NR_MTOPS entries */
 	/* Array of tape commands with TAPE_NR_MTOPS entries */
@@ -182,26 +176,6 @@ struct tape_char_data {
 	int block_size;			/*   of size block_size. */
 	int block_size;			/*   of size block_size. */
 };
 };
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-/* Block Frontend Data */
-struct tape_blk_data
-{
-	struct tape_device *	device;
-	/* Block device request queue. */
-	struct request_queue *	request_queue;
-	spinlock_t		request_queue_lock;
-
-	/* Task to move entries from block request to CCS request queue. */
-	struct work_struct	requeue_task;
-	atomic_t		requeue_scheduled;
-
-	/* Current position on the tape. */
-	long			block_position;
-	int			medium_changed;
-	struct gendisk *	disk;
-};
-#endif
-
 /* Tape Info */
 /* Tape Info */
 struct tape_device {
 struct tape_device {
 	/* entry in tape_device_list */
 	/* entry in tape_device_list */
@@ -248,10 +222,6 @@ struct tape_device {
 
 
 	/* Character device frontend data */
 	/* Character device frontend data */
 	struct tape_char_data		char_data;
 	struct tape_char_data		char_data;
-#ifdef CONFIG_S390_TAPE_BLOCK
-	/* Block dev frontend data */
-	struct tape_blk_data		blk_data;
-#endif
 
 
 	/* Function to start or stop the next request later. */
 	/* Function to start or stop the next request later. */
 	struct delayed_work		tape_dnr;
 	struct delayed_work		tape_dnr;
@@ -313,19 +283,6 @@ extern void tapechar_exit(void);
 extern int  tapechar_setup_device(struct tape_device *);
 extern int  tapechar_setup_device(struct tape_device *);
 extern void tapechar_cleanup_device(struct tape_device *);
 extern void tapechar_cleanup_device(struct tape_device *);
 
 
-/* Externals from tape_block.c */
-#ifdef CONFIG_S390_TAPE_BLOCK
-extern int tapeblock_init (void);
-extern void tapeblock_exit(void);
-extern int tapeblock_setup_device(struct tape_device *);
-extern void tapeblock_cleanup_device(struct tape_device *);
-#else
-static inline int tapeblock_init (void) {return 0;}
-static inline void tapeblock_exit (void) {;}
-static inline int tapeblock_setup_device(struct tape_device *t) {return 0;}
-static inline void tapeblock_cleanup_device (struct tape_device *t) {;}
-#endif
-
 /* tape initialisation functions */
 /* tape initialisation functions */
 #ifdef CONFIG_PROC_FS
 #ifdef CONFIG_PROC_FS
 extern void tape_proc_init (void);
 extern void tape_proc_init (void);

+ 0 - 136
drivers/s390/char/tape_34xx.c

@@ -323,20 +323,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
 	inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
 	inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
 	sense = irb->ecw;
 	sense = irb->ecw;
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-	if (request->op == TO_BLOCK) {
-		/*
-		 * Recovery for block device requests. Set the block_position
-		 * to something invalid and retry.
-		 */
-		device->blk_data.block_position = -1;
-		if (request->retries-- <= 0)
-			return tape_34xx_erp_failed(request, -EIO);
-		else
-			return tape_34xx_erp_retry(request);
-	}
-#endif
-
 	if (
 	if (
 		sense[0] & SENSE_COMMAND_REJECT &&
 		sense[0] & SENSE_COMMAND_REJECT &&
 		sense[1] & SENSE_WRITE_PROTECT
 		sense[1] & SENSE_WRITE_PROTECT
@@ -1129,123 +1115,6 @@ tape_34xx_mtseek(struct tape_device *device, int mt_count)
 	return tape_do_io_free(device, request);
 	return tape_do_io_free(device, request);
 }
 }
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-/*
- * Tape block read for 34xx.
- */
-static struct tape_request *
-tape_34xx_bread(struct tape_device *device, struct request *req)
-{
-	struct tape_request *request;
-	struct ccw1 *ccw;
-	int count = 0;
-	unsigned off;
-	char *dst;
-	struct bio_vec *bv;
-	struct req_iterator iter;
-	struct tape_34xx_block_id *	start_block;
-
-	DBF_EVENT(6, "xBREDid:");
-
-	/* Count the number of blocks for the request. */
-	rq_for_each_segment(bv, req, iter)
-		count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9);
-
-	/* Allocate the ccw request. */
-	request = tape_alloc_request(3+count+1, 8);
-	if (IS_ERR(request))
-		return request;
-
-	/* Setup ccws. */
-	request->op = TO_BLOCK;
-	start_block = (struct tape_34xx_block_id *) request->cpdata;
-	start_block->block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B;
-	DBF_EVENT(6, "start_block = %i\n", start_block->block);
-
-	ccw = request->cpaddr;
-	ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte);
-
-	/*
-	 * We always setup a nop after the mode set ccw. This slot is
-	 * used in tape_std_check_locate to insert a locate ccw if the
-	 * current tape position doesn't match the start block to be read.
-	 * The second nop will be filled with a read block id which is in
-	 * turn used by tape_34xx_free_bread to populate the segment bid
-	 * table.
-	 */
-	ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
-	ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
-
-	rq_for_each_segment(bv, req, iter) {
-		dst = kmap(bv->bv_page) + bv->bv_offset;
-		for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) {
-			ccw->flags = CCW_FLAG_CC;
-			ccw->cmd_code = READ_FORWARD;
-			ccw->count = TAPEBLOCK_HSEC_SIZE;
-			set_normalized_cda(ccw, (void*) __pa(dst));
-			ccw++;
-			dst += TAPEBLOCK_HSEC_SIZE;
-		}
-	}
-
-	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
-	DBF_EVENT(6, "xBREDccwg\n");
-	return request;
-}
-
-static void
-tape_34xx_free_bread (struct tape_request *request)
-{
-	struct ccw1* ccw;
-
-	ccw = request->cpaddr;
-	if ((ccw + 2)->cmd_code == READ_BLOCK_ID) {
-		struct {
-			struct tape_34xx_block_id	cbid;
-			struct tape_34xx_block_id	dbid;
-		} __attribute__ ((packed)) *rbi_data;
-
-		rbi_data = request->cpdata;
-
-		if (request->device)
-			tape_34xx_add_sbid(request->device, rbi_data->cbid);
-	}
-
-	/* Last ccw is a nop and doesn't need clear_normalized_cda */
-	for (; ccw->flags & CCW_FLAG_CC; ccw++)
-		if (ccw->cmd_code == READ_FORWARD)
-			clear_normalized_cda(ccw);
-	tape_free_request(request);
-}
-
-/*
- * check_locate is called just before the tape request is passed to
- * the common io layer for execution. It has to check the current
- * tape position and insert a locate ccw if it doesn't match the
- * start block for the request.
- */
-static void
-tape_34xx_check_locate(struct tape_device *device, struct tape_request *request)
-{
-	struct tape_34xx_block_id *	start_block;
-
-	start_block = (struct tape_34xx_block_id *) request->cpdata;
-	if (start_block->block == device->blk_data.block_position)
-		return;
-
-	DBF_LH(4, "Block seek(%06d+%06d)\n", start_block->block, device->bof);
-	start_block->wrap    = 0;
-	start_block->segment = 1;
-	start_block->format  = (*device->modeset_byte & 0x08) ?
-				TAPE34XX_FMT_3480_XF :
-				TAPE34XX_FMT_3480;
-	start_block->block   = start_block->block + device->bof;
-	tape_34xx_merge_sbid(device, start_block);
-	tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
-	tape_ccw_cc(request->cpaddr + 2, READ_BLOCK_ID, 8, request->cpdata);
-}
-#endif
-
 /*
 /*
  * List of 3480/3490 magnetic tape commands.
  * List of 3480/3490 magnetic tape commands.
  */
  */
@@ -1295,11 +1164,6 @@ static struct tape_discipline tape_discipline_34xx = {
 	.irq = tape_34xx_irq,
 	.irq = tape_34xx_irq,
 	.read_block = tape_std_read_block,
 	.read_block = tape_std_read_block,
 	.write_block = tape_std_write_block,
 	.write_block = tape_std_write_block,
-#ifdef CONFIG_S390_TAPE_BLOCK
-	.bread = tape_34xx_bread,
-	.free_bread = tape_34xx_free_bread,
-	.check_locate = tape_34xx_check_locate,
-#endif
 	.ioctl_fn = tape_34xx_ioctl,
 	.ioctl_fn = tape_34xx_ioctl,
 	.mtop_array = tape_34xx_mtop
 	.mtop_array = tape_34xx_mtop
 };
 };

+ 0 - 105
drivers/s390/char/tape_3590.c

@@ -670,92 +670,6 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
 	return 0;
 	return 0;
 }
 }
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-/*
- * Tape Block READ
- */
-static struct tape_request *
-tape_3590_bread(struct tape_device *device, struct request *req)
-{
-	struct tape_request *request;
-	struct ccw1 *ccw;
-	int count = 0, start_block;
-	unsigned off;
-	char *dst;
-	struct bio_vec *bv;
-	struct req_iterator iter;
-
-	DBF_EVENT(6, "xBREDid:");
-	start_block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B;
-	DBF_EVENT(6, "start_block = %i\n", start_block);
-
-	rq_for_each_segment(bv, req, iter)
-		count += bv->bv_len >> (TAPEBLOCK_HSEC_S2B + 9);
-
-	request = tape_alloc_request(2 + count + 1, 4);
-	if (IS_ERR(request))
-		return request;
-	request->op = TO_BLOCK;
-	*(__u32 *) request->cpdata = start_block;
-	ccw = request->cpaddr;
-	ccw = tape_ccw_cc(ccw, MODE_SET_DB, 1, device->modeset_byte);
-
-	/*
-	 * We always setup a nop after the mode set ccw. This slot is
-	 * used in tape_std_check_locate to insert a locate ccw if the
-	 * current tape position doesn't match the start block to be read.
-	 */
-	ccw = tape_ccw_cc(ccw, NOP, 0, NULL);
-
-	rq_for_each_segment(bv, req, iter) {
-		dst = page_address(bv->bv_page) + bv->bv_offset;
-		for (off = 0; off < bv->bv_len; off += TAPEBLOCK_HSEC_SIZE) {
-			ccw->flags = CCW_FLAG_CC;
-			ccw->cmd_code = READ_FORWARD;
-			ccw->count = TAPEBLOCK_HSEC_SIZE;
-			set_normalized_cda(ccw, (void *) __pa(dst));
-			ccw++;
-			dst += TAPEBLOCK_HSEC_SIZE;
-		}
-		BUG_ON(off > bv->bv_len);
-	}
-	ccw = tape_ccw_end(ccw, NOP, 0, NULL);
-	DBF_EVENT(6, "xBREDccwg\n");
-	return request;
-}
-
-static void
-tape_3590_free_bread(struct tape_request *request)
-{
-	struct ccw1 *ccw;
-
-	/* Last ccw is a nop and doesn't need clear_normalized_cda */
-	for (ccw = request->cpaddr; ccw->flags & CCW_FLAG_CC; ccw++)
-		if (ccw->cmd_code == READ_FORWARD)
-			clear_normalized_cda(ccw);
-	tape_free_request(request);
-}
-
-/*
- * check_locate is called just before the tape request is passed to
- * the common io layer for execution. It has to check the current
- * tape position and insert a locate ccw if it doesn't match the
- * start block for the request.
- */
-static void
-tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
-{
-	__u32 *start_block;
-
-	start_block = (__u32 *) request->cpdata;
-	if (*start_block != device->blk_data.block_position) {
-		/* Add the start offset of the file to get the real block. */
-		*start_block += device->bof;
-		tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
-	}
-}
-#endif
-
 static void tape_3590_med_state_set(struct tape_device *device,
 static void tape_3590_med_state_set(struct tape_device *device,
 				    struct tape_3590_med_sense *sense)
 				    struct tape_3590_med_sense *sense)
 {
 {
@@ -1423,20 +1337,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
 {
 {
 	struct tape_3590_sense *sense;
 	struct tape_3590_sense *sense;
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-	if (request->op == TO_BLOCK) {
-		/*
-		 * Recovery for block device requests. Set the block_position
-		 * to something invalid and retry.
-		 */
-		device->blk_data.block_position = -1;
-		if (request->retries-- <= 0)
-			return tape_3590_erp_failed(device, request, irb, -EIO);
-		else
-			return tape_3590_erp_retry(device, request, irb);
-	}
-#endif
-
 	sense = (struct tape_3590_sense *) irb->ecw;
 	sense = (struct tape_3590_sense *) irb->ecw;
 
 
 	DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
 	DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
@@ -1729,11 +1629,6 @@ static struct tape_discipline tape_discipline_3590 = {
 	.irq = tape_3590_irq,
 	.irq = tape_3590_irq,
 	.read_block = tape_std_read_block,
 	.read_block = tape_std_read_block,
 	.write_block = tape_std_write_block,
 	.write_block = tape_std_write_block,
-#ifdef CONFIG_S390_TAPE_BLOCK
-	.bread = tape_3590_bread,
-	.free_bread = tape_3590_free_bread,
-	.check_locate = tape_3590_check_locate,
-#endif
 	.ioctl_fn = tape_3590_ioctl,
 	.ioctl_fn = tape_3590_ioctl,
 	.mtop_array = tape_3590_mtop
 	.mtop_array = tape_3590_mtop
 };
 };

+ 0 - 13
drivers/s390/char/tape_char.c

@@ -161,11 +161,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-	/* Changes position. */
-	device->blk_data.medium_changed = 1;
-#endif
-
 	DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
 	DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
 	/* Let the discipline build the ccw chain. */
 	/* Let the discipline build the ccw chain. */
 	request = device->discipline->read_block(device, block_size);
 	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
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-	/* Changes position. */
-	device->blk_data.medium_changed = 1;
-#endif
-
 	DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
 	DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
 	DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
 	DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
 	/* Let the discipline build the ccw chain. */
 	/* Let the discipline build the ccw chain. */
@@ -379,9 +369,6 @@ __tapechar_ioctl(struct tape_device *device,
 			case MTBSFM:
 			case MTBSFM:
 			case MTFSFM:
 			case MTFSFM:
 			case MTSEEK:
 			case MTSEEK:
-#ifdef CONFIG_S390_TAPE_BLOCK
-				device->blk_data.medium_changed = 1;
-#endif
 				if (device->required_tapemarks)
 				if (device->required_tapemarks)
 					tape_std_terminate_write(device);
 					tape_std_terminate_write(device);
 			default:
 			default:

+ 2 - 14
drivers/s390/char/tape_core.c

@@ -401,9 +401,6 @@ tape_generic_online(struct tape_device *device,
 	rc = tapechar_setup_device(device);
 	rc = tapechar_setup_device(device);
 	if (rc)
 	if (rc)
 		goto out_minor;
 		goto out_minor;
-	rc = tapeblock_setup_device(device);
-	if (rc)
-		goto out_char;
 
 
 	tape_state_set(device, TS_UNUSED);
 	tape_state_set(device, TS_UNUSED);
 
 
@@ -411,8 +408,6 @@ tape_generic_online(struct tape_device *device,
 
 
 	return 0;
 	return 0;
 
 
-out_char:
-	tapechar_cleanup_device(device);
 out_minor:
 out_minor:
 	tape_remove_minor(device);
 	tape_remove_minor(device);
 out_discipline:
 out_discipline:
@@ -426,7 +421,6 @@ out:
 static void
 static void
 tape_cleanup_device(struct tape_device *device)
 tape_cleanup_device(struct tape_device *device)
 {
 {
-	tapeblock_cleanup_device(device);
 	tapechar_cleanup_device(device);
 	tapechar_cleanup_device(device);
 	device->discipline->cleanup_device(device);
 	device->discipline->cleanup_device(device);
 	module_put(device->discipline->owner);
 	module_put(device->discipline->owner);
@@ -785,10 +779,6 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
 {
 {
 	int rc;
 	int rc;
 
 
-#ifdef CONFIG_S390_TAPE_BLOCK
-	if (request->op == TO_BLOCK)
-		device->discipline->check_locate(device, request);
-#endif
 	rc = ccw_device_start(
 	rc = ccw_device_start(
 		device->cdev,
 		device->cdev,
 		request->cpaddr,
 		request->cpaddr,
@@ -1253,7 +1243,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 }
 }
 
 
 /*
 /*
- * Tape device open function used by tape_char & tape_block frontends.
+ * Tape device open function used by tape_char frontend.
  */
  */
 int
 int
 tape_open(struct tape_device *device)
 tape_open(struct tape_device *device)
@@ -1283,7 +1273,7 @@ tape_open(struct tape_device *device)
 }
 }
 
 
 /*
 /*
- * Tape device release function used by tape_char & tape_block frontends.
+ * Tape device release function used by tape_char frontend.
  */
  */
 int
 int
 tape_release(struct tape_device *device)
 tape_release(struct tape_device *device)
@@ -1344,7 +1334,6 @@ tape_init (void)
 	DBF_EVENT(3, "tape init\n");
 	DBF_EVENT(3, "tape init\n");
 	tape_proc_init();
 	tape_proc_init();
 	tapechar_init ();
 	tapechar_init ();
-	tapeblock_init ();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1358,7 +1347,6 @@ tape_exit(void)
 
 
 	/* Get rid of the frontends */
 	/* Get rid of the frontends */
 	tapechar_exit();
 	tapechar_exit();
-	tapeblock_exit();
 	tape_proc_cleanup();
 	tape_proc_cleanup();
 	debug_unregister (TAPE_DBF_AREA);
 	debug_unregister (TAPE_DBF_AREA);
 }
 }

+ 43 - 69
drivers/s390/cio/ccwgroup.c

@@ -1,7 +1,7 @@
 /*
 /*
  *  bus driver for ccwgroup
  *  bus driver for ccwgroup
  *
  *
- *  Copyright IBM Corp. 2002, 2009
+ *  Copyright IBM Corp. 2002, 2012
  *
  *
  *  Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *  Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *	       Cornelia Huck (cornelia.huck@de.ibm.com)
  *	       Cornelia Huck (cornelia.huck@de.ibm.com)
@@ -15,10 +15,13 @@
 #include <linux/ctype.h>
 #include <linux/ctype.h>
 #include <linux/dcache.h>
 #include <linux/dcache.h>
 
 
+#include <asm/cio.h>
 #include <asm/ccwdev.h>
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 #include <asm/ccwgroup.h>
 
 
-#define CCW_BUS_ID_SIZE		20
+#include "device.h"
+
+#define CCW_BUS_ID_SIZE		10
 
 
 /* In Linux 2.4, we had a channel device layer called "chandev"
 /* In Linux 2.4, we had a channel device layer called "chandev"
  * that did all sorts of obscure stuff for networking devices.
  * that did all sorts of obscure stuff for networking devices.
@@ -27,19 +30,6 @@
  * to devices that use multiple subchannels.
  * to devices that use multiple subchannels.
  */
  */
 
 
-/* a device matches a driver if all its slave devices match the same
- * entry of the driver */
-static int ccwgroup_bus_match(struct device *dev, struct device_driver * drv)
-{
-	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
-	struct ccwgroup_driver *gdrv = to_ccwgroupdrv(drv);
-
-	if (gdev->creator_id == gdrv->driver_id)
-		return 1;
-
-	return 0;
-}
-
 static struct bus_type ccwgroup_bus_type;
 static struct bus_type ccwgroup_bus_type;
 
 
 static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
@@ -254,9 +244,10 @@ static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int __get_next_bus_id(const char **buf, char *bus_id)
+static int __get_next_id(const char **buf, struct ccw_dev_id *id)
 {
 {
-	int rc, len;
+	unsigned int cssid, ssid, devno;
+	int ret = 0, len;
 	char *start, *end;
 	char *start, *end;
 
 
 	start = (char *)*buf;
 	start = (char *)*buf;
@@ -271,49 +262,40 @@ static int __get_next_bus_id(const char **buf, char *bus_id)
 		len = end - start + 1;
 		len = end - start + 1;
 		end++;
 		end++;
 	}
 	}
-	if (len < CCW_BUS_ID_SIZE) {
-		strlcpy(bus_id, start, len);
-		rc = 0;
+	if (len <= CCW_BUS_ID_SIZE) {
+		if (sscanf(start, "%2x.%1x.%04x", &cssid, &ssid, &devno) != 3)
+			ret = -EINVAL;
 	} else
 	} else
-		rc = -EINVAL;
-	*buf = end;
-	return rc;
-}
-
-static int __is_valid_bus_id(char bus_id[CCW_BUS_ID_SIZE])
-{
-	int cssid, ssid, devno;
+		ret = -EINVAL;
 
 
-	/* Must be of form %x.%x.%04x */
-	if (sscanf(bus_id, "%x.%1x.%04x", &cssid, &ssid, &devno) != 3)
-		return 0;
-	return 1;
+	if (!ret) {
+		id->ssid = ssid;
+		id->devno = devno;
+	}
+	*buf = end;
+	return ret;
 }
 }
 
 
 /**
 /**
- * ccwgroup_create_from_string() - create and register a ccw group device
- * @root: parent device for the new device
- * @creator_id: identifier of creating driver
- * @cdrv: ccw driver of slave devices
+ * ccwgroup_create_dev() - create and register a ccw group device
+ * @parent: parent device for the new device
+ * @gdrv: driver for the new group device
  * @num_devices: number of slave devices
  * @num_devices: number of slave devices
  * @buf: buffer containing comma separated bus ids of slave devices
  * @buf: buffer containing comma separated bus ids of slave devices
  *
  *
- * Create and register a new ccw group device as a child of @root. Slave
- * devices are obtained from the list of bus ids given in @buf and must all
- * belong to @cdrv.
+ * Create and register a new ccw group device as a child of @parent. Slave
+ * devices are obtained from the list of bus ids given in @buf.
  * Returns:
  * Returns:
  *  %0 on success and an error code on failure.
  *  %0 on success and an error code on failure.
  * Context:
  * Context:
  *  non-atomic
  *  non-atomic
  */
  */
-int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
-				struct ccw_driver *cdrv, int num_devices,
-				const char *buf)
+int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv,
+			int num_devices, const char *buf)
 {
 {
 	struct ccwgroup_device *gdev;
 	struct ccwgroup_device *gdev;
+	struct ccw_dev_id dev_id;
 	int rc, i;
 	int rc, i;
-	char tmp_bus_id[CCW_BUS_ID_SIZE];
-	const char *curr_buf;
 
 
 	gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]),
 	gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]),
 		       GFP_KERNEL);
 		       GFP_KERNEL);
@@ -323,29 +305,24 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
 	atomic_set(&gdev->onoff, 0);
 	atomic_set(&gdev->onoff, 0);
 	mutex_init(&gdev->reg_mutex);
 	mutex_init(&gdev->reg_mutex);
 	mutex_lock(&gdev->reg_mutex);
 	mutex_lock(&gdev->reg_mutex);
-	gdev->creator_id = creator_id;
 	gdev->count = num_devices;
 	gdev->count = num_devices;
 	gdev->dev.bus = &ccwgroup_bus_type;
 	gdev->dev.bus = &ccwgroup_bus_type;
-	gdev->dev.parent = root;
+	gdev->dev.parent = parent;
 	gdev->dev.release = ccwgroup_release;
 	gdev->dev.release = ccwgroup_release;
 	device_initialize(&gdev->dev);
 	device_initialize(&gdev->dev);
 
 
-	curr_buf = buf;
-	for (i = 0; i < num_devices && curr_buf; i++) {
-		rc = __get_next_bus_id(&curr_buf, tmp_bus_id);
+	for (i = 0; i < num_devices && buf; i++) {
+		rc = __get_next_id(&buf, &dev_id);
 		if (rc != 0)
 		if (rc != 0)
 			goto error;
 			goto error;
-		if (!__is_valid_bus_id(tmp_bus_id)) {
-			rc = -EINVAL;
-			goto error;
-		}
-		gdev->cdev[i] = get_ccwdev_by_busid(cdrv, tmp_bus_id);
+		gdev->cdev[i] = get_ccwdev_by_dev_id(&dev_id);
 		/*
 		/*
 		 * All devices have to be of the same type in
 		 * All devices have to be of the same type in
 		 * order to be grouped.
 		 * order to be grouped.
 		 */
 		 */
-		if (!gdev->cdev[i]
-		    || gdev->cdev[i]->id.driver_info !=
+		if (!gdev->cdev[i] || !gdev->cdev[i]->drv ||
+		    gdev->cdev[i]->drv != gdev->cdev[0]->drv ||
+		    gdev->cdev[i]->id.driver_info !=
 		    gdev->cdev[0]->id.driver_info) {
 		    gdev->cdev[0]->id.driver_info) {
 			rc = -EINVAL;
 			rc = -EINVAL;
 			goto error;
 			goto error;
@@ -361,18 +338,25 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
 		spin_unlock_irq(gdev->cdev[i]->ccwlock);
 		spin_unlock_irq(gdev->cdev[i]->ccwlock);
 	}
 	}
 	/* Check for sufficient number of bus ids. */
 	/* Check for sufficient number of bus ids. */
-	if (i < num_devices && !curr_buf) {
+	if (i < num_devices) {
 		rc = -EINVAL;
 		rc = -EINVAL;
 		goto error;
 		goto error;
 	}
 	}
 	/* Check for trailing stuff. */
 	/* Check for trailing stuff. */
-	if (i == num_devices && strlen(curr_buf) > 0) {
+	if (i == num_devices && strlen(buf) > 0) {
 		rc = -EINVAL;
 		rc = -EINVAL;
 		goto error;
 		goto error;
 	}
 	}
 
 
 	dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
 	dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev));
 	gdev->dev.groups = ccwgroup_attr_groups;
 	gdev->dev.groups = ccwgroup_attr_groups;
+
+	if (gdrv) {
+		gdev->dev.driver = &gdrv->driver;
+		rc = gdrv->setup ? gdrv->setup(gdev) : 0;
+		if (rc)
+			goto error;
+	}
 	rc = device_add(&gdev->dev);
 	rc = device_add(&gdev->dev);
 	if (rc)
 	if (rc)
 		goto error;
 		goto error;
@@ -397,7 +381,7 @@ error:
 	put_device(&gdev->dev);
 	put_device(&gdev->dev);
 	return rc;
 	return rc;
 }
 }
-EXPORT_SYMBOL(ccwgroup_create_from_string);
+EXPORT_SYMBOL(ccwgroup_create_dev);
 
 
 static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
 static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
 			     void *data)
 			     void *data)
@@ -440,14 +424,6 @@ module_exit(cleanup_ccwgroup);
 
 
 /************************** driver stuff ******************************/
 /************************** driver stuff ******************************/
 
 
-static int ccwgroup_probe(struct device *dev)
-{
-	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
-	struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
-
-	return gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
-}
-
 static int ccwgroup_remove(struct device *dev)
 static int ccwgroup_remove(struct device *dev)
 {
 {
 	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
 	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
@@ -542,8 +518,6 @@ static const struct dev_pm_ops ccwgroup_pm_ops = {
 
 
 static struct bus_type ccwgroup_bus_type = {
 static struct bus_type ccwgroup_bus_type = {
 	.name   = "ccwgroup",
 	.name   = "ccwgroup",
-	.match  = ccwgroup_bus_match,
-	.probe  = ccwgroup_probe,
 	.remove = ccwgroup_remove,
 	.remove = ccwgroup_remove,
 	.shutdown = ccwgroup_shutdown,
 	.shutdown = ccwgroup_shutdown,
 	.pm = &ccwgroup_pm_ops,
 	.pm = &ccwgroup_pm_ops,

+ 19 - 54
drivers/s390/cio/cio.c

@@ -656,51 +656,34 @@ static struct io_subchannel_private console_priv;
 static int console_subchannel_in_use;
 static int console_subchannel_in_use;
 
 
 /*
 /*
- * Use cio_tpi to get a pending interrupt and call the interrupt handler.
- * Return non-zero if an interrupt was processed, zero otherwise.
+ * Use cio_tsch to update the subchannel status and call the interrupt handler
+ * if status had been pending. Called with the console_subchannel lock.
  */
  */
-static int cio_tpi(void)
+static void cio_tsch(struct subchannel *sch)
 {
 {
-	struct tpi_info *tpi_info;
-	struct subchannel *sch;
 	struct irb *irb;
 	struct irb *irb;
 	int irq_context;
 	int irq_context;
 
 
-	tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
-	if (tpi(NULL) != 1)
-		return 0;
-	kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
-	if (tpi_info->adapter_IO) {
-		do_adapter_IO(tpi_info->isc);
-		return 1;
-	}
 	irb = (struct irb *)&S390_lowcore.irb;
 	irb = (struct irb *)&S390_lowcore.irb;
 	/* Store interrupt response block to lowcore. */
 	/* Store interrupt response block to lowcore. */
-	if (tsch(tpi_info->schid, irb) != 0) {
+	if (tsch(sch->schid, irb) != 0)
 		/* Not status pending or not operational. */
 		/* Not status pending or not operational. */
-		kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
-		return 1;
-	}
-	sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
-	if (!sch) {
-		kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
-		return 1;
-	}
+		return;
+	memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
+	/* Call interrupt handler with updated status. */
 	irq_context = in_interrupt();
 	irq_context = in_interrupt();
-	if (!irq_context)
+	if (!irq_context) {
 		local_bh_disable();
 		local_bh_disable();
-	irq_enter();
-	spin_lock(sch->lock);
-	memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
+		irq_enter();
+	}
 	if (sch->driver && sch->driver->irq)
 	if (sch->driver && sch->driver->irq)
 		sch->driver->irq(sch);
 		sch->driver->irq(sch);
 	else
 	else
 		kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
 		kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
-	spin_unlock(sch->lock);
-	irq_exit();
-	if (!irq_context)
+	if (!irq_context) {
+		irq_exit();
 		_local_bh_enable();
 		_local_bh_enable();
-	return 1;
+	}
 }
 }
 
 
 void *cio_get_console_priv(void)
 void *cio_get_console_priv(void)
@@ -712,34 +695,16 @@ void *cio_get_console_priv(void)
  * busy wait for the next interrupt on the console
  * busy wait for the next interrupt on the console
  */
  */
 void wait_cons_dev(void)
 void wait_cons_dev(void)
-	__releases(console_subchannel.lock)
-	__acquires(console_subchannel.lock)
 {
 {
-	unsigned long cr6      __attribute__ ((aligned (8)));
-	unsigned long save_cr6 __attribute__ ((aligned (8)));
-
-	/* 
-	 * before entering the spinlock we may already have
-	 * processed the interrupt on a different CPU...
-	 */
 	if (!console_subchannel_in_use)
 	if (!console_subchannel_in_use)
 		return;
 		return;
 
 
-	/* disable all but the console isc */
-	__ctl_store (save_cr6, 6, 6);
-	cr6 = 1UL << (31 - CONSOLE_ISC);
-	__ctl_load (cr6, 6, 6);
-
-	do {
-		spin_unlock(console_subchannel.lock);
-		if (!cio_tpi())
-			cpu_relax();
-		spin_lock(console_subchannel.lock);
-	} while (console_subchannel.schib.scsw.cmd.actl != 0);
-	/*
-	 * restore previous isc value
-	 */
-	__ctl_load (save_cr6, 6, 6);
+	while (1) {
+		cio_tsch(&console_subchannel);
+		if (console_subchannel.schib.scsw.cmd.actl == 0)
+			break;
+		udelay_simple(100);
+	}
 }
 }
 
 
 static int
 static int

+ 12 - 1
drivers/s390/cio/device.c

@@ -695,7 +695,17 @@ static int match_dev_id(struct device *dev, void *data)
 	return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
 	return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
 }
 }
 
 
-static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
+/**
+ * get_ccwdev_by_dev_id() - obtain device from a ccw device id
+ * @dev_id: id of the device to be searched
+ *
+ * This function searches all devices attached to the ccw bus for a device
+ * matching @dev_id.
+ * Returns:
+ *  If a device is found its reference count is increased and returned;
+ *  else %NULL is returned.
+ */
+struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
 {
 {
 	struct device *dev;
 	struct device *dev;
 
 
@@ -703,6 +713,7 @@ static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
 
 
 	return dev ? to_ccwdev(dev) : NULL;
 	return dev ? to_ccwdev(dev) : NULL;
 }
 }
+EXPORT_SYMBOL_GPL(get_ccwdev_by_dev_id);
 
 
 static void ccw_device_do_unbind_bind(struct ccw_device *cdev)
 static void ccw_device_do_unbind_bind(struct ccw_device *cdev)
 {
 {

+ 1 - 0
drivers/s390/cio/device.h

@@ -101,6 +101,7 @@ int ccw_device_test_sense_data(struct ccw_device *);
 void ccw_device_schedule_sch_unregister(struct ccw_device *);
 void ccw_device_schedule_sch_unregister(struct ccw_device *);
 int ccw_purge_blacklisted(void);
 int ccw_purge_blacklisted(void);
 void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo);
 void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo);
+struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id);
 
 
 /* Function prototypes for device status and basic sense stuff. */
 /* Function prototypes for device status and basic sense stuff. */
 void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
 void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);

+ 24 - 23
drivers/s390/cio/qdio_main.c

@@ -63,7 +63,7 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
 		"	ipm	%0\n"
 		"	ipm	%0\n"
 		"	srl	%0,28\n"
 		"	srl	%0,28\n"
 		: "=d" (cc)
 		: "=d" (cc)
-		: "d" (__fc), "d" (__schid), "d" (__mask) : "cc", "memory");
+		: "d" (__fc), "d" (__schid), "d" (__mask) : "cc");
 	return cc;
 	return cc;
 }
 }
 
 
@@ -74,7 +74,7 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask,
  * @bb: busy bit indicator, set only if SIGA-w/wt could not access a buffer
  * @bb: busy bit indicator, set only if SIGA-w/wt could not access a buffer
  * @fc: function code to perform
  * @fc: function code to perform
  *
  *
- * Returns cc or QDIO_ERROR_SIGA_ACCESS_EXCEPTION.
+ * Returns condition code.
  * Note: For IQDC unicast queues only the highest priority queue is processed.
  * Note: For IQDC unicast queues only the highest priority queue is processed.
  */
  */
 static inline int do_siga_output(unsigned long schid, unsigned long mask,
 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,
 	register unsigned long __schid asm("1") = schid;
 	register unsigned long __schid asm("1") = schid;
 	register unsigned long __mask asm("2") = mask;
 	register unsigned long __mask asm("2") = mask;
 	register unsigned long __aob asm("3") = aob;
 	register unsigned long __aob asm("3") = aob;
-	int cc = QDIO_ERROR_SIGA_ACCESS_EXCEPTION;
+	int cc;
 
 
 	asm volatile(
 	asm volatile(
 		"	siga	0\n"
 		"	siga	0\n"
-		"0:	ipm	%0\n"
+		"	ipm	%0\n"
 		"	srl	%0,28\n"
 		"	srl	%0,28\n"
-		"1:\n"
-		EX_TABLE(0b, 1b)
-		: "+d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask),
-		  "+d" (__aob)
-		: : "cc", "memory");
-	*bb = ((unsigned int) __fc) >> 31;
+		: "=d" (cc), "+d" (__fc), "+d" (__aob)
+		: "d" (__schid), "d" (__mask)
+		: "cc");
+	*bb = __fc >> 31;
 	return cc;
 	return cc;
 }
 }
 
 
@@ -167,7 +165,7 @@ again:
 
 
 	DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
 	DBF_ERROR("%4x EQBS ERROR", SCH_NO(q));
 	DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
 	DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
-	q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+	q->handler(q->irq_ptr->cdev, QDIO_ERROR_GET_BUF_STATE,
 		   q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
 		   q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
 	return 0;
 	return 0;
 }
 }
@@ -215,7 +213,7 @@ again:
 
 
 	DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
 	DBF_ERROR("%4x SQBS ERROR", SCH_NO(q));
 	DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
 	DBF_ERROR("%3d%3d%2d", count, tmp_count, nr);
-	q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+	q->handler(q->irq_ptr->cdev, QDIO_ERROR_SET_BUF_STATE,
 		   q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
 		   q->nr, q->first_to_kick, count, q->irq_ptr->int_parm);
 	return 0;
 	return 0;
 }
 }
@@ -313,7 +311,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output,
 	cc = do_siga_sync(schid, output, input, fc);
 	cc = do_siga_sync(schid, output, input, fc);
 	if (unlikely(cc))
 	if (unlikely(cc))
 		DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc);
 		DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc);
-	return cc;
+	return (cc) ? -EIO : 0;
 }
 }
 
 
 static inline int qdio_siga_sync_q(struct qdio_q *q)
 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)
 	cc = do_siga_input(schid, q->mask, fc);
 	cc = do_siga_input(schid, q->mask, fc);
 	if (unlikely(cc))
 	if (unlikely(cc))
 		DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc);
 		DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc);
-	return cc;
+	return (cc) ? -EIO : 0;
 }
 }
 
 
 #define qdio_siga_sync_out(q) qdio_siga_sync(q, ~0U, 0)
 #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)
 	unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
 	unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
 					SLSB_P_OUTPUT_NOT_INIT;
 					SLSB_P_OUTPUT_NOT_INIT;
 
 
-	q->qdio_error |= QDIO_ERROR_SLSB_STATE;
+	q->qdio_error = QDIO_ERROR_SLSB_STATE;
 
 
 	/* special handling for no target buffer empty */
 	/* special handling for no target buffer empty */
 	if ((!q->is_input_q &&
 	if ((!q->is_input_q &&
@@ -519,7 +517,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
 	int count, stop;
 	int count, stop;
 	unsigned char state = 0;
 	unsigned char state = 0;
 
 
-	q->timestamp = get_clock_fast();
+	q->timestamp = get_clock();
 
 
 	/*
 	/*
 	 * Don't check 128 buffers, as otherwise qdio_inbound_q_moved
 	 * 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)
 
 
 	bufnr = get_inbound_buffer_frontier(q);
 	bufnr = get_inbound_buffer_frontier(q);
 
 
-	if ((bufnr != q->last_move) || q->qdio_error) {
+	if (bufnr != q->last_move) {
 		q->last_move = bufnr;
 		q->last_move = bufnr;
 		if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR)
 		if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR)
 			q->u.in.timestamp = get_clock();
 			q->u.in.timestamp = get_clock();
@@ -790,7 +788,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
 	int count, stop;
 	int count, stop;
 	unsigned char state = 0;
 	unsigned char state = 0;
 
 
-	q->timestamp = get_clock_fast();
+	q->timestamp = get_clock();
 
 
 	if (need_siga_sync(q))
 	if (need_siga_sync(q))
 		if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
 		if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
@@ -863,7 +861,7 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q)
 
 
 	bufnr = get_outbound_buffer_frontier(q);
 	bufnr = get_outbound_buffer_frontier(q);
 
 
-	if ((bufnr != q->last_move) || q->qdio_error) {
+	if (bufnr != q->last_move) {
 		q->last_move = bufnr;
 		q->last_move = bufnr;
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr);
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr);
 		return 1;
 		return 1;
@@ -894,13 +892,16 @@ retry:
 				goto retry;
 				goto retry;
 			}
 			}
 			DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr);
 			DBF_ERROR("%4x cc2 BBC:%1d", SCH_NO(q), q->nr);
-			cc |= QDIO_ERROR_SIGA_BUSY;
-		} else
+			cc = -EBUSY;
+		} else {
 			DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr);
 			DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr);
+			cc = -ENOBUFS;
+		}
 		break;
 		break;
 	case 1:
 	case 1:
 	case 3:
 	case 3:
 		DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc);
 		DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc);
+		cc = -EIO;
 		break;
 		break;
 	}
 	}
 	if (retries) {
 	if (retries) {
@@ -1090,7 +1091,7 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
 	}
 	}
 
 
 	count = sub_buf(q->first_to_check, q->first_to_kick);
 	count = sub_buf(q->first_to_check, q->first_to_kick);
-	q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE_CHECK_CONDITION,
+	q->handler(q->irq_ptr->cdev, QDIO_ERROR_ACTIVATE,
 		   q->nr, q->first_to_kick, count, irq_ptr->int_parm);
 		   q->nr, q->first_to_kick, count, irq_ptr->int_parm);
 no_handler:
 no_handler:
 	qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
 	qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
@@ -1691,7 +1692,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
 		      "do%02x b:%02x c:%02x", callflags, bufnr, count);
 		      "do%02x b:%02x c:%02x", callflags, bufnr, count);
 
 
 	if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)
 	if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)
-		return -EBUSY;
+		return -EIO;
 	if (!count)
 	if (!count)
 		return 0;
 		return 0;
 	if (callflags & QDIO_FLAG_SYNC_INPUT)
 	if (callflags & QDIO_FLAG_SYNC_INPUT)

+ 14 - 10
drivers/s390/crypto/ap_bus.c

@@ -215,7 +215,7 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
 	register struct ap_queue_status reg1_out asm ("1");
 	register struct ap_queue_status reg1_out asm ("1");
 	register void *reg2 asm ("2") = ind;
 	register void *reg2 asm ("2") = ind;
 	asm volatile(
 	asm volatile(
-		".long 0xb2af0000"		/* PQAP(RAPQ) */
+		".long 0xb2af0000"		/* PQAP(AQIC) */
 		: "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
 		: "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
 		:
 		:
 		: "cc" );
 		: "cc" );
@@ -232,7 +232,7 @@ __ap_query_functions(ap_qid_t qid, unsigned int *functions)
 	register unsigned long reg2 asm ("2");
 	register unsigned long reg2 asm ("2");
 
 
 	asm volatile(
 	asm volatile(
-		".long 0xb2af0000\n"
+		".long 0xb2af0000\n"		/* PQAP(TAPQ) */
 		"0:\n"
 		"0:\n"
 		EX_TABLE(0b, 0b)
 		EX_TABLE(0b, 0b)
 		: "+d" (reg0), "+d" (reg1), "=d" (reg2)
 		: "+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,
 		reg0 |= 0x400000UL;
 		reg0 |= 0x400000UL;
 
 
 	asm volatile (
 	asm volatile (
-		"0: .long 0xb2ad0042\n"		/* DQAP */
+		"0: .long 0xb2ad0042\n"		/* NQAP */
 		"   brc   2,0b"
 		"   brc   2,0b"
 		: "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
 		: "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
 		: "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg)
 		: "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)
 
 
 
 
 	asm volatile(
 	asm volatile(
-		"0: .long 0xb2ae0064\n"
+		"0: .long 0xb2ae0064\n"		/* DQAP */
 		"   brc   6,0b\n"
 		"   brc   6,0b\n"
 		: "+d" (reg0), "=d" (reg1), "+d" (reg2),
 		: "+d" (reg0), "=d" (reg1), "+d" (reg2),
 		"+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
 		"+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7),
@@ -836,12 +836,12 @@ static void __ap_flush_queue(struct ap_device *ap_dev)
 	list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
 	list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) {
 		list_del_init(&ap_msg->list);
 		list_del_init(&ap_msg->list);
 		ap_dev->pendingq_count--;
 		ap_dev->pendingq_count--;
-		ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+		ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
 	}
 	}
 	list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
 	list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) {
 		list_del_init(&ap_msg->list);
 		list_del_init(&ap_msg->list);
 		ap_dev->requestq_count--;
 		ap_dev->requestq_count--;
-		ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+		ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
 	}
 	}
 }
 }
 
 
@@ -1329,7 +1329,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
 				continue;
 				continue;
 			list_del_init(&ap_msg->list);
 			list_del_init(&ap_msg->list);
 			ap_dev->pendingq_count--;
 			ap_dev->pendingq_count--;
-			ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply);
+			ap_msg->receive(ap_dev, ap_msg, ap_dev->reply);
 			break;
 			break;
 		}
 		}
 		if (ap_dev->queue_count > 0)
 		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
 			return -EBUSY;
 			return -EBUSY;
 		case AP_RESPONSE_REQ_FAC_NOT_INST:
 		case AP_RESPONSE_REQ_FAC_NOT_INST:
 		case AP_RESPONSE_MESSAGE_TOO_BIG:
 		case AP_RESPONSE_MESSAGE_TOO_BIG:
-			ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
+			ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL));
 			return -EINVAL;
 			return -EINVAL;
 		default:	/* Device is gone. */
 		default:	/* Device is gone. */
-			ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+			ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 	} else {
 	} else {
@@ -1471,6 +1471,10 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
 	unsigned long flags;
 	unsigned long flags;
 	int rc;
 	int rc;
 
 
+	/* For asynchronous message handling a valid receive-callback
+	 * is required. */
+	BUG_ON(!ap_msg->receive);
+
 	spin_lock_bh(&ap_dev->lock);
 	spin_lock_bh(&ap_dev->lock);
 	if (!ap_dev->unregistered) {
 	if (!ap_dev->unregistered) {
 		/* Make room on the queue by polling for finished requests. */
 		/* 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)
 		if (rc == -ENODEV)
 		if (rc == -ENODEV)
 			ap_dev->unregistered = 1;
 			ap_dev->unregistered = 1;
 	} else {
 	} else {
-		ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
+		ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
 		rc = -ENODEV;
 		rc = -ENODEV;
 	}
 	}
 	spin_unlock_bh(&ap_dev->lock);
 	spin_unlock_bh(&ap_dev->lock);

+ 4 - 3
drivers/s390/crypto/ap_bus.h

@@ -136,9 +136,6 @@ struct ap_driver {
 
 
 	int (*probe)(struct ap_device *);
 	int (*probe)(struct ap_device *);
 	void (*remove)(struct ap_device *);
 	void (*remove)(struct ap_device *);
-	/* receive is called from tasklet context */
-	void (*receive)(struct ap_device *, struct ap_message *,
-			struct ap_message *);
 	int request_timeout;		/* request timeout in jiffies */
 	int request_timeout;		/* request timeout in jiffies */
 };
 };
 
 
@@ -183,6 +180,9 @@ struct ap_message {
 
 
 	void *private;			/* ap driver private pointer. */
 	void *private;			/* ap driver private pointer. */
 	unsigned int special:1;		/* Used for special commands. */
 	unsigned int special:1;		/* Used for special commands. */
+	/* receive is called from tasklet context */
+	void (*receive)(struct ap_device *, struct ap_message *,
+			struct ap_message *);
 };
 };
 
 
 #define AP_DEVICE(dt)					\
 #define AP_DEVICE(dt)					\
@@ -199,6 +199,7 @@ static inline void ap_init_message(struct ap_message *ap_msg)
 	ap_msg->psmid = 0;
 	ap_msg->psmid = 0;
 	ap_msg->length = 0;
 	ap_msg->length = 0;
 	ap_msg->special = 0;
 	ap_msg->special = 0;
+	ap_msg->receive = NULL;
 }
 }
 
 
 /*
 /*

+ 2 - 1
drivers/s390/crypto/zcrypt_cex2a.c

@@ -77,7 +77,6 @@ static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *,
 static struct ap_driver zcrypt_cex2a_driver = {
 static struct ap_driver zcrypt_cex2a_driver = {
 	.probe = zcrypt_cex2a_probe,
 	.probe = zcrypt_cex2a_probe,
 	.remove = zcrypt_cex2a_remove,
 	.remove = zcrypt_cex2a_remove,
-	.receive = zcrypt_cex2a_receive,
 	.ids = zcrypt_cex2a_ids,
 	.ids = zcrypt_cex2a_ids,
 	.request_timeout = CEX2A_CLEANUP_TIME,
 	.request_timeout = CEX2A_CLEANUP_TIME,
 };
 };
@@ -349,6 +348,7 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
 		ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 		ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_cex2a_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &work;
 	ap_msg.private = &work;
@@ -390,6 +390,7 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
 		ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 		ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_cex2a_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &work;
 	ap_msg.private = &work;

+ 2 - 1
drivers/s390/crypto/zcrypt_pcica.c

@@ -67,7 +67,6 @@ static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *,
 static struct ap_driver zcrypt_pcica_driver = {
 static struct ap_driver zcrypt_pcica_driver = {
 	.probe = zcrypt_pcica_probe,
 	.probe = zcrypt_pcica_probe,
 	.remove = zcrypt_pcica_remove,
 	.remove = zcrypt_pcica_remove,
-	.receive = zcrypt_pcica_receive,
 	.ids = zcrypt_pcica_ids,
 	.ids = zcrypt_pcica_ids,
 	.request_timeout = PCICA_CLEANUP_TIME,
 	.request_timeout = PCICA_CLEANUP_TIME,
 };
 };
@@ -284,6 +283,7 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
 	ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcica_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &work;
 	ap_msg.private = &work;
@@ -322,6 +322,7 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
 	ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcica_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &work;
 	ap_msg.private = &work;

+ 2 - 1
drivers/s390/crypto/zcrypt_pcicc.c

@@ -79,7 +79,6 @@ static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *,
 static struct ap_driver zcrypt_pcicc_driver = {
 static struct ap_driver zcrypt_pcicc_driver = {
 	.probe = zcrypt_pcicc_probe,
 	.probe = zcrypt_pcicc_probe,
 	.remove = zcrypt_pcicc_remove,
 	.remove = zcrypt_pcicc_remove,
-	.receive = zcrypt_pcicc_receive,
 	.ids = zcrypt_pcicc_ids,
 	.ids = zcrypt_pcicc_ids,
 	.request_timeout = PCICC_CLEANUP_TIME,
 	.request_timeout = PCICC_CLEANUP_TIME,
 };
 };
@@ -488,6 +487,7 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcicc_receive;
 	ap_msg.length = PAGE_SIZE;
 	ap_msg.length = PAGE_SIZE;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
@@ -527,6 +527,7 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcicc_receive;
 	ap_msg.length = PAGE_SIZE;
 	ap_msg.length = PAGE_SIZE;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);

+ 4 - 1
drivers/s390/crypto/zcrypt_pcixcc.c

@@ -89,7 +89,6 @@ static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
 static struct ap_driver zcrypt_pcixcc_driver = {
 static struct ap_driver zcrypt_pcixcc_driver = {
 	.probe = zcrypt_pcixcc_probe,
 	.probe = zcrypt_pcixcc_probe,
 	.remove = zcrypt_pcixcc_remove,
 	.remove = zcrypt_pcixcc_remove,
-	.receive = zcrypt_pcixcc_receive,
 	.ids = zcrypt_pcixcc_ids,
 	.ids = zcrypt_pcixcc_ids,
 	.request_timeout = PCIXCC_CLEANUP_TIME,
 	.request_timeout = PCIXCC_CLEANUP_TIME,
 };
 };
@@ -698,6 +697,7 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcixcc_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &resp_type;
 	ap_msg.private = &resp_type;
@@ -738,6 +738,7 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcixcc_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &resp_type;
 	ap_msg.private = &resp_type;
@@ -778,6 +779,7 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
 	ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
 	ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcixcc_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &resp_type;
 	ap_msg.private = &resp_type;
@@ -818,6 +820,7 @@ static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
 	ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
 	ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
 	if (!ap_msg.message)
 	if (!ap_msg.message)
 		return -ENOMEM;
 		return -ENOMEM;
+	ap_msg.receive = zcrypt_pcixcc_receive;
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 				atomic_inc_return(&zcrypt_step);
 				atomic_inc_return(&zcrypt_step);
 	ap_msg.private = &resp_type;
 	ap_msg.private = &resp_type;

+ 64 - 101
drivers/s390/net/claw.c

@@ -136,7 +136,6 @@ static inline void
 claw_set_busy(struct net_device *dev)
 claw_set_busy(struct net_device *dev)
 {
 {
  ((struct claw_privbk *)dev->ml_priv)->tbusy = 1;
  ((struct claw_privbk *)dev->ml_priv)->tbusy = 1;
- eieio();
 }
 }
 
 
 static inline void
 static inline void
@@ -144,13 +143,11 @@ claw_clear_busy(struct net_device *dev)
 {
 {
 	clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy));
 	clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy));
 	netif_wake_queue(dev);
 	netif_wake_queue(dev);
-	eieio();
 }
 }
 
 
 static inline int
 static inline int
 claw_check_busy(struct net_device *dev)
 claw_check_busy(struct net_device *dev)
 {
 {
-	eieio();
 	return ((struct claw_privbk *) dev->ml_priv)->tbusy;
 	return ((struct claw_privbk *) dev->ml_priv)->tbusy;
 }
 }
 
 
@@ -233,8 +230,6 @@ static ssize_t claw_rbuff_show(struct device *dev,
 static ssize_t claw_rbuff_write(struct device *dev,
 static ssize_t claw_rbuff_write(struct device *dev,
 	struct device_attribute *attr,
 	struct device_attribute *attr,
 	const char *buf, size_t count);
 	const char *buf, size_t count);
-static int claw_add_files(struct device *dev);
-static void claw_remove_files(struct device *dev);
 
 
 /*   Functions for System Validate  */
 /*   Functions for System Validate  */
 static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw);
 static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw);
@@ -267,12 +262,10 @@ static struct ccwgroup_driver claw_group_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.name	= "claw",
 		.name	= "claw",
 	},
 	},
-        .max_slaves  = 2,
-        .driver_id   = 0xC3D3C1E6,
-        .probe       = claw_probe,
-        .remove      = claw_remove_device,
-        .set_online  = claw_new_device,
-        .set_offline = claw_shutdown_device,
+	.setup	     = claw_probe,
+	.remove      = claw_remove_device,
+	.set_online  = claw_new_device,
+	.set_offline = claw_shutdown_device,
 	.prepare     = claw_pm_prepare,
 	.prepare     = claw_pm_prepare,
 };
 };
 
 
@@ -293,30 +286,24 @@ static struct ccw_driver claw_ccw_driver = {
 	.int_class = IOINT_CLW,
 	.int_class = IOINT_CLW,
 };
 };
 
 
-static ssize_t
-claw_driver_group_store(struct device_driver *ddrv, const char *buf,
-			size_t count)
+static ssize_t claw_driver_group_store(struct device_driver *ddrv,
+				       const char *buf,	size_t count)
 {
 {
 	int err;
 	int err;
-	err = ccwgroup_create_from_string(claw_root_dev,
-					  claw_group_driver.driver_id,
-					  &claw_ccw_driver, 2, buf);
+	err = ccwgroup_create_dev(claw_root_dev, &claw_group_driver, 2, buf);
 	return err ? err : count;
 	return err ? err : count;
 }
 }
-
 static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store);
 static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store);
 
 
-static struct attribute *claw_group_attrs[] = {
+static struct attribute *claw_drv_attrs[] = {
 	&driver_attr_group.attr,
 	&driver_attr_group.attr,
 	NULL,
 	NULL,
 };
 };
-
-static struct attribute_group claw_group_attr_group = {
-	.attrs = claw_group_attrs,
+static struct attribute_group claw_drv_attr_group = {
+	.attrs = claw_drv_attrs,
 };
 };
-
-static const struct attribute_group *claw_group_attr_groups[] = {
-	&claw_group_attr_group,
+static const struct attribute_group *claw_drv_attr_groups[] = {
+	&claw_drv_attr_group,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -324,60 +311,6 @@ static const struct attribute_group *claw_group_attr_groups[] = {
 *       Key functions
 *       Key functions
 */
 */
 
 
-/*----------------------------------------------------------------*
- *   claw_probe                                                   *
- *      this function is called for each CLAW device.             *
- *----------------------------------------------------------------*/
-static int
-claw_probe(struct ccwgroup_device *cgdev)
-{
-	int  		rc;
-	struct claw_privbk *privptr=NULL;
-
-	CLAW_DBF_TEXT(2, setup, "probe");
-	if (!get_device(&cgdev->dev))
-		return -ENODEV;
-	privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
-	dev_set_drvdata(&cgdev->dev, privptr);
-	if (privptr == NULL) {
-		probe_error(cgdev);
-		put_device(&cgdev->dev);
-		CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
-		return -ENOMEM;
-	}
-	privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL);
-	privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL);
-        if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) {
-                probe_error(cgdev);
-		put_device(&cgdev->dev);
-		CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
-                return -ENOMEM;
-        }
-	memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8);
-	memcpy(privptr->p_env->host_name,WS_NAME_NOT_DEF,8);
-	memcpy(privptr->p_env->api_type,WS_NAME_NOT_DEF,8);
-	privptr->p_env->packing = 0;
-	privptr->p_env->write_buffers = 5;
-	privptr->p_env->read_buffers = 5;
-	privptr->p_env->read_size = CLAW_FRAME_SIZE;
-	privptr->p_env->write_size = CLAW_FRAME_SIZE;
-	rc = claw_add_files(&cgdev->dev);
-	if (rc) {
-		probe_error(cgdev);
-		put_device(&cgdev->dev);
-		dev_err(&cgdev->dev, "Creating the /proc files for a new"
-		" CLAW device failed\n");
-		CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
-		return rc;
-	}
-	privptr->p_env->p_priv = privptr;
-        cgdev->cdev[0]->handler = claw_irq_handler;
-	cgdev->cdev[1]->handler = claw_irq_handler;
-	CLAW_DBF_TEXT(2, setup, "prbext 0");
-
-        return 0;
-}  /*  end of claw_probe       */
-
 /*-------------------------------------------------------------------*
 /*-------------------------------------------------------------------*
  *   claw_tx                                                         *
  *   claw_tx                                                         *
  *-------------------------------------------------------------------*/
  *-------------------------------------------------------------------*/
@@ -3093,7 +3026,6 @@ claw_remove_device(struct ccwgroup_device *cgdev)
 	dev_info(&cgdev->dev, " will be removed.\n");
 	dev_info(&cgdev->dev, " will be removed.\n");
 	if (cgdev->state == CCWGROUP_ONLINE)
 	if (cgdev->state == CCWGROUP_ONLINE)
 		claw_shutdown_device(cgdev);
 		claw_shutdown_device(cgdev);
-	claw_remove_files(&cgdev->dev);
 	kfree(priv->p_mtc_envelope);
 	kfree(priv->p_mtc_envelope);
 	priv->p_mtc_envelope=NULL;
 	priv->p_mtc_envelope=NULL;
 	kfree(priv->p_env);
 	kfree(priv->p_env);
@@ -3321,7 +3253,6 @@ claw_rbuff_write(struct device *dev, struct device_attribute *attr,
 	CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers);
 	CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers);
 	return count;
 	return count;
 }
 }
-
 static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write);
 static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write);
 
 
 static struct attribute *claw_attr[] = {
 static struct attribute *claw_attr[] = {
@@ -3332,40 +3263,73 @@ static struct attribute *claw_attr[] = {
 	&dev_attr_host_name.attr,
 	&dev_attr_host_name.attr,
 	NULL,
 	NULL,
 };
 };
-
 static struct attribute_group claw_attr_group = {
 static struct attribute_group claw_attr_group = {
 	.attrs = claw_attr,
 	.attrs = claw_attr,
 };
 };
+static const struct attribute_group *claw_attr_groups[] = {
+	&claw_attr_group,
+	NULL,
+};
+static const struct device_type claw_devtype = {
+	.name = "claw",
+	.groups = claw_attr_groups,
+};
 
 
-static int
-claw_add_files(struct device *dev)
+/*----------------------------------------------------------------*
+ *   claw_probe 						  *
+ *	this function is called for each CLAW device.		  *
+ *----------------------------------------------------------------*/
+static int claw_probe(struct ccwgroup_device *cgdev)
 {
 {
-	CLAW_DBF_TEXT(2, setup, "add_file");
-	return sysfs_create_group(&dev->kobj, &claw_attr_group);
-}
+	struct claw_privbk *privptr = NULL;
 
 
-static void
-claw_remove_files(struct device *dev)
-{
-	CLAW_DBF_TEXT(2, setup, "rem_file");
-	sysfs_remove_group(&dev->kobj, &claw_attr_group);
-}
+	CLAW_DBF_TEXT(2, setup, "probe");
+	if (!get_device(&cgdev->dev))
+		return -ENODEV;
+	privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
+	dev_set_drvdata(&cgdev->dev, privptr);
+	if (privptr == NULL) {
+		probe_error(cgdev);
+		put_device(&cgdev->dev);
+		CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
+		return -ENOMEM;
+	}
+	privptr->p_mtc_envelope = kzalloc(MAX_ENVELOPE_SIZE, GFP_KERNEL);
+	privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL);
+	if ((privptr->p_mtc_envelope == NULL) || (privptr->p_env == NULL)) {
+		probe_error(cgdev);
+		put_device(&cgdev->dev);
+		CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
+		return -ENOMEM;
+	}
+	memcpy(privptr->p_env->adapter_name, WS_NAME_NOT_DEF, 8);
+	memcpy(privptr->p_env->host_name, WS_NAME_NOT_DEF, 8);
+	memcpy(privptr->p_env->api_type, WS_NAME_NOT_DEF, 8);
+	privptr->p_env->packing = 0;
+	privptr->p_env->write_buffers = 5;
+	privptr->p_env->read_buffers = 5;
+	privptr->p_env->read_size = CLAW_FRAME_SIZE;
+	privptr->p_env->write_size = CLAW_FRAME_SIZE;
+	privptr->p_env->p_priv = privptr;
+	cgdev->cdev[0]->handler = claw_irq_handler;
+	cgdev->cdev[1]->handler = claw_irq_handler;
+	cgdev->dev.type = &claw_devtype;
+	CLAW_DBF_TEXT(2, setup, "prbext 0");
+
+	return 0;
+}  /*  end of claw_probe       */
 
 
 /*--------------------------------------------------------------------*
 /*--------------------------------------------------------------------*
 *    claw_init  and cleanup                                           *
 *    claw_init  and cleanup                                           *
 *---------------------------------------------------------------------*/
 *---------------------------------------------------------------------*/
 
 
-static void __exit
-claw_cleanup(void)
+static void __exit claw_cleanup(void)
 {
 {
-	driver_remove_file(&claw_group_driver.driver,
-			   &driver_attr_group);
 	ccwgroup_driver_unregister(&claw_group_driver);
 	ccwgroup_driver_unregister(&claw_group_driver);
 	ccw_driver_unregister(&claw_ccw_driver);
 	ccw_driver_unregister(&claw_ccw_driver);
 	root_device_unregister(claw_root_dev);
 	root_device_unregister(claw_root_dev);
 	claw_unregister_debug_facility();
 	claw_unregister_debug_facility();
 	pr_info("Driver unloaded\n");
 	pr_info("Driver unloaded\n");
-
 }
 }
 
 
 /**
 /**
@@ -3374,8 +3338,7 @@ claw_cleanup(void)
  *
  *
  * @return 0 on success, !0 on error.
  * @return 0 on success, !0 on error.
  */
  */
-static int __init
-claw_init(void)
+static int __init claw_init(void)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
@@ -3394,7 +3357,7 @@ claw_init(void)
 	ret = ccw_driver_register(&claw_ccw_driver);
 	ret = ccw_driver_register(&claw_ccw_driver);
 	if (ret)
 	if (ret)
 		goto ccw_err;
 		goto ccw_err;
-	claw_group_driver.driver.groups = claw_group_attr_groups;
+	claw_group_driver.driver.groups = claw_drv_attr_groups;
 	ret = ccwgroup_driver_register(&claw_group_driver);
 	ret = ccwgroup_driver_register(&claw_group_driver);
 	if (ret)
 	if (ret)
 		goto ccwgroup_err;
 		goto ccwgroup_err;

+ 16 - 36
drivers/s390/net/ctcm_main.c

@@ -1296,6 +1296,11 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
 
 
 }
 }
 
 
+static const struct device_type ctcm_devtype = {
+	.name = "ctcm",
+	.groups = ctcm_attr_groups,
+};
+
 /**
 /**
  * Add ctcm specific attributes.
  * Add ctcm specific attributes.
  * Add ctcm private data.
  * Add ctcm private data.
@@ -1307,7 +1312,6 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
 static int ctcm_probe_device(struct ccwgroup_device *cgdev)
 static int ctcm_probe_device(struct ccwgroup_device *cgdev)
 {
 {
 	struct ctcm_priv *priv;
 	struct ctcm_priv *priv;
-	int rc;
 
 
 	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
 	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
 			"%s %p",
 			"%s %p",
@@ -1324,17 +1328,11 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev)
 		put_device(&cgdev->dev);
 		put_device(&cgdev->dev);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-
-	rc = ctcm_add_files(&cgdev->dev);
-	if (rc) {
-		kfree(priv);
-		put_device(&cgdev->dev);
-		return rc;
-	}
 	priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
 	priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
 	cgdev->cdev[0]->handler = ctcm_irq_handler;
 	cgdev->cdev[0]->handler = ctcm_irq_handler;
 	cgdev->cdev[1]->handler = ctcm_irq_handler;
 	cgdev->cdev[1]->handler = ctcm_irq_handler;
 	dev_set_drvdata(&cgdev->dev, priv);
 	dev_set_drvdata(&cgdev->dev, priv);
+	cgdev->dev.type = &ctcm_devtype;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1611,11 +1609,6 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
 		goto out_dev;
 		goto out_dev;
 	}
 	}
 
 
-	if (ctcm_add_attributes(&cgdev->dev)) {
-		result = -ENODEV;
-		goto out_unregister;
-	}
-
 	strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
 	strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
 
 
 	dev_info(&dev->dev,
 	dev_info(&dev->dev,
@@ -1629,8 +1622,6 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
 			priv->channel[CTCM_WRITE]->id, priv->protocol);
 			priv->channel[CTCM_WRITE]->id, priv->protocol);
 
 
 	return 0;
 	return 0;
-out_unregister:
-	unregister_netdev(dev);
 out_dev:
 out_dev:
 	ctcm_free_netdevice(dev);
 	ctcm_free_netdevice(dev);
 out_ccw2:
 out_ccw2:
@@ -1669,7 +1660,6 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
 		/* Close the device */
 		/* Close the device */
 		ctcm_close(dev);
 		ctcm_close(dev);
 		dev->flags &= ~IFF_RUNNING;
 		dev->flags &= ~IFF_RUNNING;
-		ctcm_remove_attributes(&cgdev->dev);
 		channel_free(priv->channel[CTCM_READ]);
 		channel_free(priv->channel[CTCM_READ]);
 	} else
 	} else
 		dev = NULL;
 		dev = NULL;
@@ -1711,7 +1701,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev)
 
 
 	if (cgdev->state == CCWGROUP_ONLINE)
 	if (cgdev->state == CCWGROUP_ONLINE)
 		ctcm_shutdown_device(cgdev);
 		ctcm_shutdown_device(cgdev);
-	ctcm_remove_files(&cgdev->dev);
 	dev_set_drvdata(&cgdev->dev, NULL);
 	dev_set_drvdata(&cgdev->dev, NULL);
 	kfree(priv);
 	kfree(priv);
 	put_device(&cgdev->dev);
 	put_device(&cgdev->dev);
@@ -1778,9 +1767,7 @@ static struct ccwgroup_driver ctcm_group_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.name	= CTC_DRIVER_NAME,
 		.name	= CTC_DRIVER_NAME,
 	},
 	},
-	.max_slaves  = 2,
-	.driver_id   = 0xC3E3C3D4,	/* CTCM */
-	.probe       = ctcm_probe_device,
+	.setup	     = ctcm_probe_device,
 	.remove      = ctcm_remove_device,
 	.remove      = ctcm_remove_device,
 	.set_online  = ctcm_new_device,
 	.set_online  = ctcm_new_device,
 	.set_offline = ctcm_shutdown_device,
 	.set_offline = ctcm_shutdown_device,
@@ -1789,31 +1776,25 @@ static struct ccwgroup_driver ctcm_group_driver = {
 	.restore     = ctcm_pm_resume,
 	.restore     = ctcm_pm_resume,
 };
 };
 
 
-static ssize_t
-ctcm_driver_group_store(struct device_driver *ddrv, const char *buf,
-			size_t count)
+static ssize_t ctcm_driver_group_store(struct device_driver *ddrv,
+				       const char *buf,	size_t count)
 {
 {
 	int err;
 	int err;
 
 
-	err = ccwgroup_create_from_string(ctcm_root_dev,
-					  ctcm_group_driver.driver_id,
-					  &ctcm_ccw_driver, 2, buf);
+	err = ccwgroup_create_dev(ctcm_root_dev, &ctcm_group_driver, 2, buf);
 	return err ? err : count;
 	return err ? err : count;
 }
 }
-
 static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store);
 static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store);
 
 
-static struct attribute *ctcm_group_attrs[] = {
+static struct attribute *ctcm_drv_attrs[] = {
 	&driver_attr_group.attr,
 	&driver_attr_group.attr,
 	NULL,
 	NULL,
 };
 };
-
-static struct attribute_group ctcm_group_attr_group = {
-	.attrs = ctcm_group_attrs,
+static struct attribute_group ctcm_drv_attr_group = {
+	.attrs = ctcm_drv_attrs,
 };
 };
-
-static const struct attribute_group *ctcm_group_attr_groups[] = {
-	&ctcm_group_attr_group,
+static const struct attribute_group *ctcm_drv_attr_groups[] = {
+	&ctcm_drv_attr_group,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -1829,7 +1810,6 @@ static const struct attribute_group *ctcm_group_attr_groups[] = {
  */
  */
 static void __exit ctcm_exit(void)
 static void __exit ctcm_exit(void)
 {
 {
-	driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group);
 	ccwgroup_driver_unregister(&ctcm_group_driver);
 	ccwgroup_driver_unregister(&ctcm_group_driver);
 	ccw_driver_unregister(&ctcm_ccw_driver);
 	ccw_driver_unregister(&ctcm_ccw_driver);
 	root_device_unregister(ctcm_root_dev);
 	root_device_unregister(ctcm_root_dev);
@@ -1867,7 +1847,7 @@ static int __init ctcm_init(void)
 	ret = ccw_driver_register(&ctcm_ccw_driver);
 	ret = ccw_driver_register(&ctcm_ccw_driver);
 	if (ret)
 	if (ret)
 		goto ccw_err;
 		goto ccw_err;
-	ctcm_group_driver.driver.groups = ctcm_group_attr_groups;
+	ctcm_group_driver.driver.groups = ctcm_drv_attr_groups;
 	ret = ccwgroup_driver_register(&ctcm_group_driver);
 	ret = ccwgroup_driver_register(&ctcm_group_driver);
 	if (ret)
 	if (ret)
 		goto ccwgroup_err;
 		goto ccwgroup_err;

+ 1 - 7
drivers/s390/net/ctcm_main.h

@@ -225,13 +225,7 @@ struct ctcm_priv {
 int ctcm_open(struct net_device *dev);
 int ctcm_open(struct net_device *dev);
 int ctcm_close(struct net_device *dev);
 int ctcm_close(struct net_device *dev);
 
 
-/*
- * prototypes for non-static sysfs functions
- */
-int ctcm_add_attributes(struct device *dev);
-void ctcm_remove_attributes(struct device *dev);
-int ctcm_add_files(struct device *dev);
-void ctcm_remove_files(struct device *dev);
+extern const struct attribute_group *ctcm_attr_groups[];
 
 
 /*
 /*
  * Compatibility macros for busy handling
  * Compatibility macros for busy handling

+ 10 - 27
drivers/s390/net/ctcm_sysfs.c

@@ -13,6 +13,7 @@
 #define KMSG_COMPONENT "ctcm"
 #define KMSG_COMPONENT "ctcm"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 
+#include <linux/device.h>
 #include <linux/sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include "ctcm_main.h"
 #include "ctcm_main.h"
@@ -108,10 +109,12 @@ static void ctcm_print_statistics(struct ctcm_priv *priv)
 }
 }
 
 
 static ssize_t stats_show(struct device *dev,
 static ssize_t stats_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
+			  struct device_attribute *attr, char *buf)
 {
 {
+	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
 	struct ctcm_priv *priv = dev_get_drvdata(dev);
 	struct ctcm_priv *priv = dev_get_drvdata(dev);
-	if (!priv)
+
+	if (!priv || gdev->state != CCWGROUP_ONLINE)
 		return -ENODEV;
 		return -ENODEV;
 	ctcm_print_statistics(priv);
 	ctcm_print_statistics(priv);
 	return sprintf(buf, "0\n");
 	return sprintf(buf, "0\n");
@@ -190,34 +193,14 @@ static struct attribute *ctcm_attr[] = {
 	&dev_attr_protocol.attr,
 	&dev_attr_protocol.attr,
 	&dev_attr_type.attr,
 	&dev_attr_type.attr,
 	&dev_attr_buffer.attr,
 	&dev_attr_buffer.attr,
+	&dev_attr_stats.attr,
 	NULL,
 	NULL,
 };
 };
 
 
 static struct attribute_group ctcm_attr_group = {
 static struct attribute_group ctcm_attr_group = {
 	.attrs = ctcm_attr,
 	.attrs = ctcm_attr,
 };
 };
-
-int ctcm_add_attributes(struct device *dev)
-{
-	int rc;
-
-	rc = device_create_file(dev, &dev_attr_stats);
-
-	return rc;
-}
-
-void ctcm_remove_attributes(struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_stats);
-}
-
-int ctcm_add_files(struct device *dev)
-{
-	return sysfs_create_group(&dev->kobj, &ctcm_attr_group);
-}
-
-void ctcm_remove_files(struct device *dev)
-{
-	sysfs_remove_group(&dev->kobj, &ctcm_attr_group);
-}
-
+const struct attribute_group *ctcm_attr_groups[] = {
+	&ctcm_attr_group,
+	NULL,
+};

+ 22 - 30
drivers/s390/net/lcs.c

@@ -2040,10 +2040,17 @@ static struct attribute * lcs_attrs[] = {
 	&dev_attr_recover.attr,
 	&dev_attr_recover.attr,
 	NULL,
 	NULL,
 };
 };
-
 static struct attribute_group lcs_attr_group = {
 static struct attribute_group lcs_attr_group = {
 	.attrs = lcs_attrs,
 	.attrs = lcs_attrs,
 };
 };
+static const struct attribute_group *lcs_attr_groups[] = {
+	&lcs_attr_group,
+	NULL,
+};
+static const struct device_type lcs_devtype = {
+	.name = "lcs",
+	.groups = lcs_attr_groups,
+};
 
 
 /**
 /**
  * lcs_probe_device is called on establishing a new ccwgroup_device.
  * lcs_probe_device is called on establishing a new ccwgroup_device.
@@ -2052,7 +2059,6 @@ static int
 lcs_probe_device(struct ccwgroup_device *ccwgdev)
 lcs_probe_device(struct ccwgroup_device *ccwgdev)
 {
 {
 	struct lcs_card *card;
 	struct lcs_card *card;
-	int ret;
 
 
 	if (!get_device(&ccwgdev->dev))
 	if (!get_device(&ccwgdev->dev))
 		return -ENODEV;
 		return -ENODEV;
@@ -2064,12 +2070,6 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
 		put_device(&ccwgdev->dev);
 		put_device(&ccwgdev->dev);
                 return -ENOMEM;
                 return -ENOMEM;
         }
         }
-	ret = sysfs_create_group(&ccwgdev->dev.kobj, &lcs_attr_group);
-	if (ret) {
-		lcs_free_card(card);
-		put_device(&ccwgdev->dev);
-		return ret;
-        }
 	dev_set_drvdata(&ccwgdev->dev, card);
 	dev_set_drvdata(&ccwgdev->dev, card);
 	ccwgdev->cdev[0]->handler = lcs_irq;
 	ccwgdev->cdev[0]->handler = lcs_irq;
 	ccwgdev->cdev[1]->handler = lcs_irq;
 	ccwgdev->cdev[1]->handler = lcs_irq;
@@ -2078,7 +2078,9 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
 	card->thread_start_mask = 0;
 	card->thread_start_mask = 0;
 	card->thread_allowed_mask = 0;
 	card->thread_allowed_mask = 0;
 	card->thread_running_mask = 0;
 	card->thread_running_mask = 0;
-        return 0;
+	ccwgdev->dev.type = &lcs_devtype;
+
+	return 0;
 }
 }
 
 
 static int
 static int
@@ -2306,9 +2308,9 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev)
 	}
 	}
 	if (card->dev)
 	if (card->dev)
 		unregister_netdev(card->dev);
 		unregister_netdev(card->dev);
-	sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group);
 	lcs_cleanup_card(card);
 	lcs_cleanup_card(card);
 	lcs_free_card(card);
 	lcs_free_card(card);
+	dev_set_drvdata(&ccwgdev->dev, NULL);
 	put_device(&ccwgdev->dev);
 	put_device(&ccwgdev->dev);
 }
 }
 
 
@@ -2393,9 +2395,7 @@ static struct ccwgroup_driver lcs_group_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.name	= "lcs",
 		.name	= "lcs",
 	},
 	},
-	.max_slaves  = 2,
-	.driver_id   = 0xD3C3E2,
-	.probe       = lcs_probe_device,
+	.setup	     = lcs_probe_device,
 	.remove      = lcs_remove_device,
 	.remove      = lcs_remove_device,
 	.set_online  = lcs_new_device,
 	.set_online  = lcs_new_device,
 	.set_offline = lcs_shutdown_device,
 	.set_offline = lcs_shutdown_device,
@@ -2406,30 +2406,24 @@ static struct ccwgroup_driver lcs_group_driver = {
 	.restore     = lcs_restore,
 	.restore     = lcs_restore,
 };
 };
 
 
-static ssize_t
-lcs_driver_group_store(struct device_driver *ddrv, const char *buf,
-		       size_t count)
+static ssize_t lcs_driver_group_store(struct device_driver *ddrv,
+				      const char *buf, size_t count)
 {
 {
 	int err;
 	int err;
-	err = ccwgroup_create_from_string(lcs_root_dev,
-					  lcs_group_driver.driver_id,
-					  &lcs_ccw_driver, 2, buf);
+	err = ccwgroup_create_dev(lcs_root_dev, &lcs_group_driver, 2, buf);
 	return err ? err : count;
 	return err ? err : count;
 }
 }
-
 static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store);
 static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store);
 
 
-static struct attribute *lcs_group_attrs[] = {
+static struct attribute *lcs_drv_attrs[] = {
 	&driver_attr_group.attr,
 	&driver_attr_group.attr,
 	NULL,
 	NULL,
 };
 };
-
-static struct attribute_group lcs_group_attr_group = {
-	.attrs = lcs_group_attrs,
+static struct attribute_group lcs_drv_attr_group = {
+	.attrs = lcs_drv_attrs,
 };
 };
-
-static const struct attribute_group *lcs_group_attr_groups[] = {
-	&lcs_group_attr_group,
+static const struct attribute_group *lcs_drv_attr_groups[] = {
+	&lcs_drv_attr_group,
 	NULL,
 	NULL,
 };
 };
 
 
@@ -2453,7 +2447,7 @@ __init lcs_init_module(void)
 	rc = ccw_driver_register(&lcs_ccw_driver);
 	rc = ccw_driver_register(&lcs_ccw_driver);
 	if (rc)
 	if (rc)
 		goto ccw_err;
 		goto ccw_err;
-	lcs_group_driver.driver.groups = lcs_group_attr_groups;
+	lcs_group_driver.driver.groups = lcs_drv_attr_groups;
 	rc = ccwgroup_driver_register(&lcs_group_driver);
 	rc = ccwgroup_driver_register(&lcs_group_driver);
 	if (rc)
 	if (rc)
 		goto ccwgroup_err;
 		goto ccwgroup_err;
@@ -2479,8 +2473,6 @@ __exit lcs_cleanup_module(void)
 {
 {
 	pr_info("Terminating lcs module.\n");
 	pr_info("Terminating lcs module.\n");
 	LCS_DBF_TEXT(0, trace, "cleanup");
 	LCS_DBF_TEXT(0, trace, "cleanup");
-	driver_remove_file(&lcs_group_driver.driver,
-			   &driver_attr_group);
 	ccwgroup_driver_unregister(&lcs_group_driver);
 	ccwgroup_driver_unregister(&lcs_group_driver);
 	ccw_driver_unregister(&lcs_ccw_driver);
 	ccw_driver_unregister(&lcs_ccw_driver);
 	root_device_unregister(lcs_root_dev);
 	root_device_unregister(lcs_root_dev);

+ 16 - 8
drivers/s390/net/qeth_core.h

@@ -707,7 +707,16 @@ struct qeth_discipline {
 	qdio_handler_t *input_handler;
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
 	qdio_handler_t *output_handler;
 	int (*recover)(void *ptr);
 	int (*recover)(void *ptr);
-	struct ccwgroup_driver *ccwgdriver;
+	int (*setup) (struct ccwgroup_device *);
+	void (*remove) (struct ccwgroup_device *);
+	int (*set_online) (struct ccwgroup_device *);
+	int (*set_offline) (struct ccwgroup_device *);
+	void (*shutdown)(struct ccwgroup_device *);
+	int (*prepare) (struct ccwgroup_device *);
+	void (*complete) (struct ccwgroup_device *);
+	int (*freeze)(struct ccwgroup_device *);
+	int (*thaw) (struct ccwgroup_device *);
+	int (*restore)(struct ccwgroup_device *);
 };
 };
 
 
 struct qeth_vlan_vid {
 struct qeth_vlan_vid {
@@ -771,7 +780,7 @@ struct qeth_card {
 	struct qeth_perf_stats perf_stats;
 	struct qeth_perf_stats perf_stats;
 	int read_or_write_problem;
 	int read_or_write_problem;
 	struct qeth_osn_info osn_info;
 	struct qeth_osn_info osn_info;
-	struct qeth_discipline discipline;
+	struct qeth_discipline *discipline;
 	atomic_t force_alloc_skb;
 	atomic_t force_alloc_skb;
 	struct service_level qeth_service_level;
 	struct service_level qeth_service_level;
 	struct qdio_ssqd_desc ssqd;
 	struct qdio_ssqd_desc ssqd;
@@ -837,16 +846,15 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card,
 	return card->info.diagass_support & (__u32)cmd;
 	return card->info.diagass_support & (__u32)cmd;
 }
 }
 
 
-extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
-extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
+extern struct qeth_discipline qeth_l2_discipline;
+extern struct qeth_discipline qeth_l3_discipline;
+extern const struct attribute_group *qeth_generic_attr_groups[];
+extern const struct attribute_group *qeth_osn_attr_groups[];
+
 const char *qeth_get_cardname_short(struct qeth_card *);
 const char *qeth_get_cardname_short(struct qeth_card *);
 int qeth_realloc_buffer_pool(struct qeth_card *, int);
 int qeth_realloc_buffer_pool(struct qeth_card *, int);
 int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
 int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
 void qeth_core_free_discipline(struct qeth_card *);
 void qeth_core_free_discipline(struct qeth_card *);
-int qeth_core_create_device_attributes(struct device *);
-void qeth_core_remove_device_attributes(struct device *);
-int qeth_core_create_osn_attributes(struct device *);
-void qeth_core_remove_osn_attributes(struct device *);
 void qeth_buffer_reclaim_work(struct work_struct *);
 void qeth_buffer_reclaim_work(struct work_struct *);
 
 
 /* exports for qeth discipline device drivers */
 /* exports for qeth discipline device drivers */

+ 79 - 99
drivers/s390/net/qeth_core_main.c

@@ -1363,7 +1363,7 @@ static void qeth_start_kernel_thread(struct work_struct *work)
 	    card->write.state != CH_STATE_UP)
 	    card->write.state != CH_STATE_UP)
 		return;
 		return;
 	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) {
 	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) {
-		ts = kthread_run(card->discipline.recover, (void *)card,
+		ts = kthread_run(card->discipline->recover, (void *)card,
 				"qeth_recover");
 				"qeth_recover");
 		if (IS_ERR(ts)) {
 		if (IS_ERR(ts)) {
 			qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
 			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,
 	if (rc) {
 	if (rc) {
 		queue->card->stats.tx_errors += count;
 		queue->card->stats.tx_errors += count;
 		/* ignore temporary SIGA errors without busy condition */
 		/* ignore temporary SIGA errors without busy condition */
-		if (rc == QDIO_ERROR_SIGA_TARGET)
+		if (rc == -ENOBUFS)
 			return;
 			return;
 		QETH_CARD_TEXT(queue->card, 2, "flushbuf");
 		QETH_CARD_TEXT(queue->card, 2, "flushbuf");
 		QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no);
 		QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no);
@@ -3531,7 +3531,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
 	int i;
 	int i;
 
 
 	QETH_CARD_TEXT(card, 6, "qdouhdl");
 	QETH_CARD_TEXT(card, 6, "qdouhdl");
-	if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
+	if (qdio_error & QDIO_ERROR_FATAL) {
 		QETH_CARD_TEXT(card, 2, "achkcond");
 		QETH_CARD_TEXT(card, 2, "achkcond");
 		netif_stop_queue(card->dev);
 		netif_stop_queue(card->dev);
 		qeth_schedule_recovery(card);
 		qeth_schedule_recovery(card);
@@ -4627,7 +4627,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
 		goto out_free_in_sbals;
 		goto out_free_in_sbals;
 	}
 	}
 	for (i = 0; i < card->qdio.no_in_queues; ++i)
 	for (i = 0; i < card->qdio.no_in_queues; ++i)
-		queue_start_poll[i] = card->discipline.start_poll;
+		queue_start_poll[i] = card->discipline->start_poll;
 
 
 	qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
 	qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
 
 
@@ -4651,8 +4651,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
 	init_data.qib_param_field        = qib_param_field;
 	init_data.qib_param_field        = qib_param_field;
 	init_data.no_input_qs            = card->qdio.no_in_queues;
 	init_data.no_input_qs            = card->qdio.no_in_queues;
 	init_data.no_output_qs           = card->qdio.no_out_queues;
 	init_data.no_output_qs           = card->qdio.no_out_queues;
-	init_data.input_handler          = card->discipline.input_handler;
-	init_data.output_handler         = card->discipline.output_handler;
+	init_data.input_handler 	 = card->discipline->input_handler;
+	init_data.output_handler	 = card->discipline->output_handler;
 	init_data.queue_start_poll_array = queue_start_poll;
 	init_data.queue_start_poll_array = queue_start_poll;
 	init_data.int_parm               = (unsigned long) card;
 	init_data.int_parm               = (unsigned long) card;
 	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
 	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
@@ -4737,13 +4737,6 @@ static struct ccw_driver qeth_ccw_driver = {
 	.remove = ccwgroup_remove_ccwdev,
 	.remove = ccwgroup_remove_ccwdev,
 };
 };
 
 
-static int qeth_core_driver_group(const char *buf, struct device *root_dev,
-				unsigned long driver_id)
-{
-	return ccwgroup_create_from_string(root_dev, driver_id,
-					   &qeth_ccw_driver, 3, buf);
-}
-
 int qeth_core_hardsetup_card(struct qeth_card *card)
 int qeth_core_hardsetup_card(struct qeth_card *card)
 {
 {
 	int retries = 0;
 	int retries = 0;
@@ -5040,17 +5033,15 @@ int qeth_core_load_discipline(struct qeth_card *card,
 	mutex_lock(&qeth_mod_mutex);
 	mutex_lock(&qeth_mod_mutex);
 	switch (discipline) {
 	switch (discipline) {
 	case QETH_DISCIPLINE_LAYER3:
 	case QETH_DISCIPLINE_LAYER3:
-		card->discipline.ccwgdriver = try_then_request_module(
-			symbol_get(qeth_l3_ccwgroup_driver),
-			"qeth_l3");
+		card->discipline = try_then_request_module(
+			symbol_get(qeth_l3_discipline), "qeth_l3");
 		break;
 		break;
 	case QETH_DISCIPLINE_LAYER2:
 	case QETH_DISCIPLINE_LAYER2:
-		card->discipline.ccwgdriver = try_then_request_module(
-			symbol_get(qeth_l2_ccwgroup_driver),
-			"qeth_l2");
+		card->discipline = try_then_request_module(
+			symbol_get(qeth_l2_discipline), "qeth_l2");
 		break;
 		break;
 	}
 	}
-	if (!card->discipline.ccwgdriver) {
+	if (!card->discipline) {
 		dev_err(&card->gdev->dev, "There is no kernel module to "
 		dev_err(&card->gdev->dev, "There is no kernel module to "
 			"support discipline %d\n", discipline);
 			"support discipline %d\n", discipline);
 		rc = -EINVAL;
 		rc = -EINVAL;
@@ -5062,12 +5053,21 @@ int qeth_core_load_discipline(struct qeth_card *card,
 void qeth_core_free_discipline(struct qeth_card *card)
 void qeth_core_free_discipline(struct qeth_card *card)
 {
 {
 	if (card->options.layer2)
 	if (card->options.layer2)
-		symbol_put(qeth_l2_ccwgroup_driver);
+		symbol_put(qeth_l2_discipline);
 	else
 	else
-		symbol_put(qeth_l3_ccwgroup_driver);
-	card->discipline.ccwgdriver = NULL;
+		symbol_put(qeth_l3_discipline);
+	card->discipline = NULL;
 }
 }
 
 
+static const struct device_type qeth_generic_devtype = {
+	.name = "qeth_generic",
+	.groups = qeth_generic_attr_groups,
+};
+static const struct device_type qeth_osn_devtype = {
+	.name = "qeth_osn",
+	.groups = qeth_osn_attr_groups,
+};
+
 static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card;
 	struct qeth_card *card;
@@ -5122,18 +5122,17 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 	}
 	}
 
 
 	if (card->info.type == QETH_CARD_TYPE_OSN)
 	if (card->info.type == QETH_CARD_TYPE_OSN)
-		rc = qeth_core_create_osn_attributes(dev);
+		gdev->dev.type = &qeth_osn_devtype;
 	else
 	else
-		rc = qeth_core_create_device_attributes(dev);
-	if (rc)
-		goto err_dbf;
+		gdev->dev.type = &qeth_generic_devtype;
+
 	switch (card->info.type) {
 	switch (card->info.type) {
 	case QETH_CARD_TYPE_OSN:
 	case QETH_CARD_TYPE_OSN:
 	case QETH_CARD_TYPE_OSM:
 	case QETH_CARD_TYPE_OSM:
 		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
 		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
 		if (rc)
 		if (rc)
-			goto err_attr;
-		rc = card->discipline.ccwgdriver->probe(card->gdev);
+			goto err_dbf;
+		rc = card->discipline->setup(card->gdev);
 		if (rc)
 		if (rc)
 			goto err_disc;
 			goto err_disc;
 	case QETH_CARD_TYPE_OSD:
 	case QETH_CARD_TYPE_OSD:
@@ -5151,11 +5150,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 
 
 err_disc:
 err_disc:
 	qeth_core_free_discipline(card);
 	qeth_core_free_discipline(card);
-err_attr:
-	if (card->info.type == QETH_CARD_TYPE_OSN)
-		qeth_core_remove_osn_attributes(dev);
-	else
-		qeth_core_remove_device_attributes(dev);
 err_dbf:
 err_dbf:
 	debug_unregister(card->debug);
 	debug_unregister(card->debug);
 err_card:
 err_card:
@@ -5172,14 +5166,8 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
 
 
 	QETH_DBF_TEXT(SETUP, 2, "removedv");
 	QETH_DBF_TEXT(SETUP, 2, "removedv");
 
 
-	if (card->info.type == QETH_CARD_TYPE_OSN) {
-		qeth_core_remove_osn_attributes(&gdev->dev);
-	} else {
-		qeth_core_remove_device_attributes(&gdev->dev);
-	}
-
-	if (card->discipline.ccwgdriver) {
-		card->discipline.ccwgdriver->remove(gdev);
+	if (card->discipline) {
+		card->discipline->remove(gdev);
 		qeth_core_free_discipline(card);
 		qeth_core_free_discipline(card);
 	}
 	}
 
 
@@ -5199,7 +5187,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
 	int rc = 0;
 	int rc = 0;
 	int def_discipline;
 	int def_discipline;
 
 
-	if (!card->discipline.ccwgdriver) {
+	if (!card->discipline) {
 		if (card->info.type == QETH_CARD_TYPE_IQD)
 		if (card->info.type == QETH_CARD_TYPE_IQD)
 			def_discipline = QETH_DISCIPLINE_LAYER3;
 			def_discipline = QETH_DISCIPLINE_LAYER3;
 		else
 		else
@@ -5207,11 +5195,11 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
 		rc = qeth_core_load_discipline(card, def_discipline);
 		rc = qeth_core_load_discipline(card, def_discipline);
 		if (rc)
 		if (rc)
 			goto err;
 			goto err;
-		rc = card->discipline.ccwgdriver->probe(card->gdev);
+		rc = card->discipline->setup(card->gdev);
 		if (rc)
 		if (rc)
 			goto err;
 			goto err;
 	}
 	}
-	rc = card->discipline.ccwgdriver->set_online(gdev);
+	rc = card->discipline->set_online(gdev);
 err:
 err:
 	return rc;
 	return rc;
 }
 }
@@ -5219,58 +5207,52 @@ err:
 static int qeth_core_set_offline(struct ccwgroup_device *gdev)
 static int qeth_core_set_offline(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	return card->discipline.ccwgdriver->set_offline(gdev);
+	return card->discipline->set_offline(gdev);
 }
 }
 
 
 static void qeth_core_shutdown(struct ccwgroup_device *gdev)
 static void qeth_core_shutdown(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	if (card->discipline.ccwgdriver &&
-	    card->discipline.ccwgdriver->shutdown)
-		card->discipline.ccwgdriver->shutdown(gdev);
+	if (card->discipline && card->discipline->shutdown)
+		card->discipline->shutdown(gdev);
 }
 }
 
 
 static int qeth_core_prepare(struct ccwgroup_device *gdev)
 static int qeth_core_prepare(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	if (card->discipline.ccwgdriver &&
-	    card->discipline.ccwgdriver->prepare)
-		return card->discipline.ccwgdriver->prepare(gdev);
+	if (card->discipline && card->discipline->prepare)
+		return card->discipline->prepare(gdev);
 	return 0;
 	return 0;
 }
 }
 
 
 static void qeth_core_complete(struct ccwgroup_device *gdev)
 static void qeth_core_complete(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	if (card->discipline.ccwgdriver &&
-	    card->discipline.ccwgdriver->complete)
-		card->discipline.ccwgdriver->complete(gdev);
+	if (card->discipline && card->discipline->complete)
+		card->discipline->complete(gdev);
 }
 }
 
 
 static int qeth_core_freeze(struct ccwgroup_device *gdev)
 static int qeth_core_freeze(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	if (card->discipline.ccwgdriver &&
-	    card->discipline.ccwgdriver->freeze)
-		return card->discipline.ccwgdriver->freeze(gdev);
+	if (card->discipline && card->discipline->freeze)
+		return card->discipline->freeze(gdev);
 	return 0;
 	return 0;
 }
 }
 
 
 static int qeth_core_thaw(struct ccwgroup_device *gdev)
 static int qeth_core_thaw(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	if (card->discipline.ccwgdriver &&
-	    card->discipline.ccwgdriver->thaw)
-		return card->discipline.ccwgdriver->thaw(gdev);
+	if (card->discipline && card->discipline->thaw)
+		return card->discipline->thaw(gdev);
 	return 0;
 	return 0;
 }
 }
 
 
 static int qeth_core_restore(struct ccwgroup_device *gdev)
 static int qeth_core_restore(struct ccwgroup_device *gdev)
 {
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	if (card->discipline.ccwgdriver &&
-	    card->discipline.ccwgdriver->restore)
-		return card->discipline.ccwgdriver->restore(gdev);
+	if (card->discipline && card->discipline->restore)
+		return card->discipline->restore(gdev);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -5279,8 +5261,7 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
 		.owner = THIS_MODULE,
 		.owner = THIS_MODULE,
 		.name = "qeth",
 		.name = "qeth",
 	},
 	},
-	.driver_id = 0xD8C5E3C8,
-	.probe = qeth_core_probe_device,
+	.setup = qeth_core_probe_device,
 	.remove = qeth_core_remove_device,
 	.remove = qeth_core_remove_device,
 	.set_online = qeth_core_set_online,
 	.set_online = qeth_core_set_online,
 	.set_offline = qeth_core_set_offline,
 	.set_offline = qeth_core_set_offline,
@@ -5292,21 +5273,30 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
 	.restore = qeth_core_restore,
 	.restore = qeth_core_restore,
 };
 };
 
 
-static ssize_t
-qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf,
-			   size_t count)
+static ssize_t qeth_core_driver_group_store(struct device_driver *ddrv,
+					    const char *buf, size_t count)
 {
 {
 	int err;
 	int err;
-	err = qeth_core_driver_group(buf, qeth_core_root_dev,
-					qeth_core_ccwgroup_driver.driver_id);
-	if (err)
-		return err;
-	else
-		return count;
-}
 
 
+	err = ccwgroup_create_dev(qeth_core_root_dev,
+				  &qeth_core_ccwgroup_driver, 3, buf);
+
+	return err ? err : count;
+}
 static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store);
 static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store);
 
 
+static struct attribute *qeth_drv_attrs[] = {
+	&driver_attr_group.attr,
+	NULL,
+};
+static struct attribute_group qeth_drv_attr_group = {
+	.attrs = qeth_drv_attrs,
+};
+static const struct attribute_group *qeth_drv_attr_groups[] = {
+	&qeth_drv_attr_group,
+	NULL,
+};
+
 static struct {
 static struct {
 	const char str[ETH_GSTRING_LEN];
 	const char str[ETH_GSTRING_LEN];
 } qeth_ethtool_stats_keys[] = {
 } qeth_ethtool_stats_keys[] = {
@@ -5544,49 +5534,41 @@ static int __init qeth_core_init(void)
 	rc = qeth_register_dbf_views();
 	rc = qeth_register_dbf_views();
 	if (rc)
 	if (rc)
 		goto out_err;
 		goto out_err;
-	rc = ccw_driver_register(&qeth_ccw_driver);
-	if (rc)
-		goto ccw_err;
-	rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
-	if (rc)
-		goto ccwgroup_err;
-	rc = driver_create_file(&qeth_core_ccwgroup_driver.driver,
-				&driver_attr_group);
-	if (rc)
-		goto driver_err;
 	qeth_core_root_dev = root_device_register("qeth");
 	qeth_core_root_dev = root_device_register("qeth");
 	rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
 	rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
 	if (rc)
 	if (rc)
 		goto register_err;
 		goto register_err;
-
 	qeth_core_header_cache = kmem_cache_create("qeth_hdr",
 	qeth_core_header_cache = kmem_cache_create("qeth_hdr",
 			sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL);
 			sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL);
 	if (!qeth_core_header_cache) {
 	if (!qeth_core_header_cache) {
 		rc = -ENOMEM;
 		rc = -ENOMEM;
 		goto slab_err;
 		goto slab_err;
 	}
 	}
-
 	qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf",
 	qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf",
 			sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL);
 			sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL);
 	if (!qeth_qdio_outbuf_cache) {
 	if (!qeth_qdio_outbuf_cache) {
 		rc = -ENOMEM;
 		rc = -ENOMEM;
 		goto cqslab_err;
 		goto cqslab_err;
 	}
 	}
+	rc = ccw_driver_register(&qeth_ccw_driver);
+	if (rc)
+		goto ccw_err;
+	qeth_core_ccwgroup_driver.driver.groups = qeth_drv_attr_groups;
+	rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
+	if (rc)
+		goto ccwgroup_err;
 
 
 	return 0;
 	return 0;
+
+ccwgroup_err:
+	ccw_driver_unregister(&qeth_ccw_driver);
+ccw_err:
+	kmem_cache_destroy(qeth_qdio_outbuf_cache);
 cqslab_err:
 cqslab_err:
 	kmem_cache_destroy(qeth_core_header_cache);
 	kmem_cache_destroy(qeth_core_header_cache);
 slab_err:
 slab_err:
 	root_device_unregister(qeth_core_root_dev);
 	root_device_unregister(qeth_core_root_dev);
 register_err:
 register_err:
-	driver_remove_file(&qeth_core_ccwgroup_driver.driver,
-			   &driver_attr_group);
-driver_err:
-	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
-ccwgroup_err:
-	ccw_driver_unregister(&qeth_ccw_driver);
-ccw_err:
-	QETH_DBF_MESSAGE(2, "Initialization failed with code %d\n", rc);
 	qeth_unregister_dbf_views();
 	qeth_unregister_dbf_views();
 out_err:
 out_err:
 	pr_err("Initializing the qeth device driver failed\n");
 	pr_err("Initializing the qeth device driver failed\n");
@@ -5595,13 +5577,11 @@ out_err:
 
 
 static void __exit qeth_core_exit(void)
 static void __exit qeth_core_exit(void)
 {
 {
-	root_device_unregister(qeth_core_root_dev);
-	driver_remove_file(&qeth_core_ccwgroup_driver.driver,
-			   &driver_attr_group);
 	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
 	ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
 	ccw_driver_unregister(&qeth_ccw_driver);
 	ccw_driver_unregister(&qeth_ccw_driver);
 	kmem_cache_destroy(qeth_qdio_outbuf_cache);
 	kmem_cache_destroy(qeth_qdio_outbuf_cache);
 	kmem_cache_destroy(qeth_core_header_cache);
 	kmem_cache_destroy(qeth_core_header_cache);
+	root_device_unregister(qeth_core_root_dev);
 	qeth_unregister_dbf_views();
 	qeth_unregister_dbf_views();
 	pr_info("core functions removed\n");
 	pr_info("core functions removed\n");
 }
 }

+ 13 - 36
drivers/s390/net/qeth_core_sys.c

@@ -434,8 +434,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 		goto out;
 		goto out;
 	else {
 	else {
 		card->info.mac_bits  = 0;
 		card->info.mac_bits  = 0;
-		if (card->discipline.ccwgdriver) {
-			card->discipline.ccwgdriver->remove(card->gdev);
+		if (card->discipline) {
+			card->discipline->remove(card->gdev);
 			qeth_core_free_discipline(card);
 			qeth_core_free_discipline(card);
 		}
 		}
 	}
 	}
@@ -444,7 +444,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 	if (rc)
 	if (rc)
 		goto out;
 		goto out;
 
 
-	rc = card->discipline.ccwgdriver->probe(card->gdev);
+	rc = card->discipline->setup(card->gdev);
 out:
 out:
 	mutex_unlock(&card->discipline_mutex);
 	mutex_unlock(&card->discipline_mutex);
 	return rc ? rc : count;
 	return rc ? rc : count;
@@ -693,7 +693,6 @@ static struct attribute *qeth_blkt_device_attrs[] = {
 	&dev_attr_inter_jumbo.attr,
 	&dev_attr_inter_jumbo.attr,
 	NULL,
 	NULL,
 };
 };
-
 static struct attribute_group qeth_device_blkt_group = {
 static struct attribute_group qeth_device_blkt_group = {
 	.name = "blkt",
 	.name = "blkt",
 	.attrs = qeth_blkt_device_attrs,
 	.attrs = qeth_blkt_device_attrs,
@@ -716,11 +715,16 @@ static struct attribute *qeth_device_attrs[] = {
 	&dev_attr_hw_trap.attr,
 	&dev_attr_hw_trap.attr,
 	NULL,
 	NULL,
 };
 };
-
 static struct attribute_group qeth_device_attr_group = {
 static struct attribute_group qeth_device_attr_group = {
 	.attrs = qeth_device_attrs,
 	.attrs = qeth_device_attrs,
 };
 };
 
 
+const struct attribute_group *qeth_generic_attr_groups[] = {
+	&qeth_device_attr_group,
+	&qeth_device_blkt_group,
+	NULL,
+};
+
 static struct attribute *qeth_osn_device_attrs[] = {
 static struct attribute *qeth_osn_device_attrs[] = {
 	&dev_attr_state.attr,
 	&dev_attr_state.attr,
 	&dev_attr_chpid.attr,
 	&dev_attr_chpid.attr,
@@ -730,37 +734,10 @@ static struct attribute *qeth_osn_device_attrs[] = {
 	&dev_attr_recover.attr,
 	&dev_attr_recover.attr,
 	NULL,
 	NULL,
 };
 };
-
 static struct attribute_group qeth_osn_device_attr_group = {
 static struct attribute_group qeth_osn_device_attr_group = {
 	.attrs = qeth_osn_device_attrs,
 	.attrs = qeth_osn_device_attrs,
 };
 };
-
-int qeth_core_create_device_attributes(struct device *dev)
-{
-	int ret;
-	ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
-	if (ret)
-		return ret;
-	ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
-	if (ret)
-		sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-
-	return 0;
-}
-
-void qeth_core_remove_device_attributes(struct device *dev)
-{
-	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
-	sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
-}
-
-int qeth_core_create_osn_attributes(struct device *dev)
-{
-	return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
-}
-
-void qeth_core_remove_osn_attributes(struct device *dev)
-{
-	sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
-	return;
-}
+const struct attribute_group *qeth_osn_attr_groups[] = {
+	&qeth_osn_device_attr_group,
+	NULL,
+};

+ 7 - 9
drivers/s390/net/qeth_l2_main.c

@@ -882,12 +882,6 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
 	INIT_LIST_HEAD(&card->mc_list);
 	INIT_LIST_HEAD(&card->mc_list);
 	card->options.layer2 = 1;
 	card->options.layer2 = 1;
 	card->info.hwtrap = 0;
 	card->info.hwtrap = 0;
-	card->discipline.start_poll = qeth_qdio_start_poll;
-	card->discipline.input_handler = (qdio_handler_t *)
-		qeth_qdio_input_handler;
-	card->discipline.output_handler = (qdio_handler_t *)
-		qeth_qdio_output_handler;
-	card->discipline.recover = qeth_l2_recover;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1227,8 +1221,12 @@ out:
 	return rc;
 	return rc;
 }
 }
 
 
-struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
-	.probe = qeth_l2_probe_device,
+struct qeth_discipline qeth_l2_discipline = {
+	.start_poll = qeth_qdio_start_poll,
+	.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
+	.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
+	.recover = qeth_l2_recover,
+	.setup = qeth_l2_probe_device,
 	.remove = qeth_l2_remove_device,
 	.remove = qeth_l2_remove_device,
 	.set_online = qeth_l2_set_online,
 	.set_online = qeth_l2_set_online,
 	.set_offline = qeth_l2_set_offline,
 	.set_offline = qeth_l2_set_offline,
@@ -1237,7 +1235,7 @@ struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
 	.thaw = qeth_l2_pm_resume,
 	.thaw = qeth_l2_pm_resume,
 	.restore = qeth_l2_pm_resume,
 	.restore = qeth_l2_pm_resume,
 };
 };
-EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver);
+EXPORT_SYMBOL_GPL(qeth_l2_discipline);
 
 
 static int qeth_osn_send_control_data(struct qeth_card *card, int len,
 static int qeth_osn_send_control_data(struct qeth_card *card, int len,
 			   struct qeth_cmd_buffer *iob)
 			   struct qeth_cmd_buffer *iob)

+ 7 - 9
drivers/s390/net/qeth_l3_main.c

@@ -3298,12 +3298,6 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 	qeth_l3_create_device_attributes(&gdev->dev);
 	qeth_l3_create_device_attributes(&gdev->dev);
 	card->options.layer2 = 0;
 	card->options.layer2 = 0;
 	card->info.hwtrap = 0;
 	card->info.hwtrap = 0;
-	card->discipline.start_poll = qeth_qdio_start_poll;
-	card->discipline.input_handler = (qdio_handler_t *)
-		qeth_qdio_input_handler;
-	card->discipline.output_handler = (qdio_handler_t *)
-		qeth_qdio_output_handler;
-	card->discipline.recover = qeth_l3_recover;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3578,8 +3572,12 @@ out:
 	return rc;
 	return rc;
 }
 }
 
 
-struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
-	.probe = qeth_l3_probe_device,
+struct qeth_discipline qeth_l3_discipline = {
+	.start_poll = qeth_qdio_start_poll,
+	.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
+	.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
+	.recover = qeth_l3_recover,
+	.setup = qeth_l3_probe_device,
 	.remove = qeth_l3_remove_device,
 	.remove = qeth_l3_remove_device,
 	.set_online = qeth_l3_set_online,
 	.set_online = qeth_l3_set_online,
 	.set_offline = qeth_l3_set_offline,
 	.set_offline = qeth_l3_set_offline,
@@ -3588,7 +3586,7 @@ struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
 	.thaw = qeth_l3_pm_resume,
 	.thaw = qeth_l3_pm_resume,
 	.restore = qeth_l3_pm_resume,
 	.restore = qeth_l3_pm_resume,
 };
 };
-EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver);
+EXPORT_SYMBOL_GPL(qeth_l3_discipline);
 
 
 static int qeth_l3_ip_event(struct notifier_block *this,
 static int qeth_l3_ip_event(struct notifier_block *this,
 			    unsigned long event, void *ptr)
 			    unsigned long event, void *ptr)