]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Mar 2009 23:04:22 +0000 (16:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Mar 2009 23:04:22 +0000 (16:04 -0700)
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (81 commits)
  [S390] remove duplicated #includes
  [S390] cpumask: use mm_cpumask() wrapper
  [S390] cpumask: Use accessors code.
  [S390] cpumask: prepare for iterators to only go to nr_cpu_ids/nr_cpumask_bits.
  [S390] cpumask: remove cpu_coregroup_map
  [S390] fix clock comparator save area usage
  [S390] Add hwcap flag for the etf3 enhancement facility
  [S390] Ensure that ipl panic notifier is called late.
  [S390] fix dfp elf hwcap/facility bit detection
  [S390] smp: perform initial cpu reset before starting a cpu
  [S390] smp: fix memory leak on __cpu_up
  [S390] ipl: Improve checking logic and remove switch defaults.
  [S390] s390dbf: Remove needless check for NULL pointer.
  [S390] s390dbf: Remove redundant initilizations.
  [S390] use kzfree()
  [S390] BUG to BUG_ON changes
  [S390] zfcpdump: Prevent zcore from beeing built as a kernel module.
  [S390] Use csum_partial in checksum.h
  [S390] cleanup lowcore.h
  [S390] eliminate ipl_device from lowcore
  ...

99 files changed:
Documentation/kernel-parameters.txt
MAINTAINERS
arch/s390/Kconfig
arch/s390/crypto/prng.c
arch/s390/include/asm/bitops.h
arch/s390/include/asm/crw.h [new file with mode: 0644]
arch/s390/include/asm/dasd.h
arch/s390/include/asm/idals.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/nmi.h [new file with mode: 0644]
arch/s390/include/asm/processor.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/smp.h
arch/s390/include/asm/string.h
arch/s390/include/asm/sysinfo.h
arch/s390/include/asm/tlbflush.h
arch/s390/include/asm/topology.h
arch/s390/include/asm/vtoc.h
arch/s390/kernel/Makefile
arch/s390/kernel/bitmap.S [deleted file]
arch/s390/kernel/bitmap.c [new file with mode: 0644]
arch/s390/kernel/compat_ptrace.h
arch/s390/kernel/debug.c
arch/s390/kernel/early.c
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/module.c
arch/s390/kernel/nmi.c [moved from drivers/s390/s390mach.c with 62% similarity]
arch/s390/kernel/process.c
arch/s390/kernel/processor.c
arch/s390/kernel/reipl64.S
arch/s390/kernel/s390_ksyms.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/sysinfo.c [moved from drivers/s390/sysinfo.c with 88% similarity]
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/traps.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/kvm-s390.c
arch/s390/lib/delay.c
arch/s390/lib/string.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/pgtable.c
drivers/char/hvc_iucv.c
drivers/s390/Makefile
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_eer.c
drivers/s390/block/dasd_erp.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/tape.h
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_block.c
drivers/s390/char/tape_char.c
drivers/s390/char/tape_core.c
drivers/s390/char/tape_proc.c
drivers/s390/char/tape_std.c
drivers/s390/char/zcore.c
drivers/s390/cio/Makefile
drivers/s390/cio/airq.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/chp.c
drivers/s390/cio/chsc.c
drivers/s390/cio/cio.c
drivers/s390/cio/crw.c [new file with mode: 0644]
drivers/s390/cio/css.c
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_debug.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/ebcdic.c [deleted file]
drivers/s390/net/qeth_core_main.c
drivers/s390/s390mach.h [deleted file]
fs/partitions/ibm.c

index 1a29ff3df3c58231a3c8a639758a9f9e7557ea6b..954b23cecfd19bc98f996c26ecfbd7bf8f0f44e9 100644 (file)
@@ -830,6 +830,9 @@ and is between 256 and 4096 characters. It is defined in the file
 
        hvc_iucv=       [S390] Number of z/VM IUCV hypervisor console (HVC)
                               terminal devices. Valid values: 0..8
+       hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs.
+                              If specified, z/VM IUCV HVC accepts connections
+                              from listed z/VM user IDs only.
 
        i8042.debug     [HW] Toggle i8042 debug mode
        i8042.direct    [HW] Put keyboard port into non-translated mode
index bc919b645f379cf52cc688dcbde4ef7aa4c9a5c2..4dacdfcdbe6e6ed34a689cf35851503606255942 100644 (file)
@@ -3745,6 +3745,15 @@ L:       linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 
+S390 ZCRYPT DRIVER
+P:     Felix Beck
+M:     felix.beck@de.ibm.com
+P:     Ralph Wuerthner
+M:     ralph.wuerthner@de.ibm.com
+M:     linux390@de.ibm.com
+L:     linux-s390@vger.kernel.org
+S:     Supported
+
 S390 ZFCP DRIVER
 P:     Christof Schmitt
 M:     christof.schmitt@de.ibm.com
index 6b0a3538dc63b9ab8ff62344904f186b01876702..2a8af5e16345d45f778e657a2f4c24363946edf3 100644 (file)
@@ -343,13 +343,6 @@ source "mm/Kconfig"
 
 comment "I/O subsystem configuration"
 
-config MACHCHK_WARNING
-       bool "Process warning machine checks"
-       help
-         Select this option if you want the machine check handler on IBM S/390 or
-         zSeries to process warning machine checks (e.g. on power failures).
-         If unsure, say "Y".
-
 config QDIO
        tristate "QDIO support"
        ---help---
@@ -521,7 +514,7 @@ config APPLDATA_OS
 
 config APPLDATA_NET_SUM
        tristate "Monitor overall network statistics"
-       depends on APPLDATA_BASE
+       depends on APPLDATA_BASE && NET
        help
          This provides network related data to the Linux - VM Monitor Stream,
          currently there is only a total sum of network I/O statistics, no
@@ -552,7 +545,7 @@ config KEXEC
          but is independent of hardware/microcode support.
 
 config ZFCPDUMP
-       tristate "zfcpdump support"
+       bool "zfcpdump support"
        select SMP
        default n
        help
index eca724d229ecd26d7102dfd7c7d4be37af98d19f..b49c00ce65e92f4e0e9b584ce0c61e3aaaf37da1 100644 (file)
@@ -201,8 +201,7 @@ out_free:
 static void __exit prng_exit(void)
 {
        /* wipe me */
-       memset(p->buf, 0, prng_chunk_size);
-       kfree(p->buf);
+       kzfree(p->buf);
        kfree(p);
 
        misc_deregister(&prng_dev);
index 8e9243ae0c19d13524a700c3ffea8aa4961665c8..b30606f6d5230e45b4eb8f4e3f009eb929d02a84 100644 (file)
@@ -57,7 +57,7 @@
  * with operation of the form "set_bit(bitnr, flags)".
  */
 
-/* bitmap tables from arch/S390/kernel/bitmap.S */
+/* bitmap tables from arch/s390/kernel/bitmap.c */
 extern const char _oi_bitmap[];
 extern const char _ni_bitmap[];
 extern const char _zb_findmap[];
@@ -525,16 +525,16 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr,
 static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
 {
 #ifdef __s390x__
-       if (likely((word & 0xffffffff) == 0xffffffff)) {
+       if ((word & 0xffffffff) == 0xffffffff) {
                word >>= 32;
                nr += 32;
        }
 #endif
-       if (likely((word & 0xffff) == 0xffff)) {
+       if ((word & 0xffff) == 0xffff) {
                word >>= 16;
                nr += 16;
        }
-       if (likely((word & 0xff) == 0xff)) {
+       if ((word & 0xff) == 0xff) {
                word >>= 8;
                nr += 8;
        }
@@ -549,16 +549,16 @@ static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
 static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
 {
 #ifdef __s390x__
-       if (likely((word & 0xffffffff) == 0)) {
+       if ((word & 0xffffffff) == 0) {
                word >>= 32;
                nr += 32;
        }
 #endif
-       if (likely((word & 0xffff) == 0)) {
+       if ((word & 0xffff) == 0) {
                word >>= 16;
                nr += 16;
        }
-       if (likely((word & 0xff) == 0)) {
+       if ((word & 0xff) == 0) {
                word >>= 8;
                nr += 8;
        }
diff --git a/arch/s390/include/asm/crw.h b/arch/s390/include/asm/crw.h
new file mode 100644 (file)
index 0000000..2185a6d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *   Data definitions for channel report processing
+ *    Copyright IBM Corp. 2000,2009
+ *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *              Cornelia Huck <cornelia.huck@de.ibm.com>,
+ *              Heiko Carstens <heiko.carstens@de.ibm.com>,
+ */
+
+#ifndef _ASM_S390_CRW_H
+#define _ASM_S390_CRW_H
+
+#include <linux/types.h>
+
+/*
+ * Channel Report Word
+ */
+struct crw {
+       __u32 res1 :  1;   /* reserved zero */
+       __u32 slct :  1;   /* solicited */
+       __u32 oflw :  1;   /* overflow */
+       __u32 chn  :  1;   /* chained */
+       __u32 rsc  :  4;   /* reporting source code */
+       __u32 anc  :  1;   /* ancillary report */
+       __u32 res2 :  1;   /* reserved zero */
+       __u32 erc  :  6;   /* error-recovery code */
+       __u32 rsid : 16;   /* reporting-source ID */
+} __attribute__ ((packed));
+
+typedef void (*crw_handler_t)(struct crw *, struct crw *, int);
+
+extern int crw_register_handler(int rsc, crw_handler_t handler);
+extern void crw_unregister_handler(int rsc);
+extern void crw_handle_channel_report(void);
+
+#define NR_RSCS 16
+
+#define CRW_RSC_MONITOR  0x2  /* monitoring facility */
+#define CRW_RSC_SCH     0x3  /* subchannel */
+#define CRW_RSC_CPATH   0x4  /* channel path */
+#define CRW_RSC_CONFIG  0x9  /* configuration-alert facility */
+#define CRW_RSC_CSS     0xB  /* channel subsystem */
+
+#define CRW_ERC_EVENT   0x00 /* event information pending */
+#define CRW_ERC_AVAIL   0x01 /* available */
+#define CRW_ERC_INIT    0x02 /* initialized */
+#define CRW_ERC_TERROR  0x03 /* temporary error */
+#define CRW_ERC_IPARM   0x04 /* installed parm initialized */
+#define CRW_ERC_TERM    0x05 /* terminal */
+#define CRW_ERC_PERRN   0x06 /* perm. error, fac. not init */
+#define CRW_ERC_PERRI   0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD    0x08 /* installed parameters modified */
+
+static inline int stcrw(struct crw *pcrw)
+{
+       int ccode;
+
+       asm volatile(
+               "       stcrw   0(%2)\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
+               : "=d" (ccode), "=m" (*pcrw)
+               : "a" (pcrw)
+               : "cc" );
+       return ccode;
+}
+
+#endif /* _ASM_S390_CRW_H */
index e2db6f16d9c8bd6273ba0b26e56d9f2efe8c62e4..218bce81ec70f05db21fde6b512ac7e6fe83447c 100644 (file)
@@ -162,15 +162,15 @@ typedef struct dasd_profile_info_t {
         unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */
 } dasd_profile_info_t;
 
-/* 
+/*
  * struct format_data_t
  * represents all data necessary to format a dasd
  */
 typedef struct format_data_t {
-       int start_unit; /* from track */
-       int stop_unit;  /* to track */
-       int blksize;    /* sectorsize */
-        int intensity;  
+       unsigned int start_unit; /* from track */
+       unsigned int stop_unit;  /* to track */
+       unsigned int blksize;    /* sectorsize */
+       unsigned int intensity;
 } format_data_t;
 
 /*
index e82c10efe65aee289c94fe59f761ce8c4c49acbb..aae276d00383cc90660f1e1771d0aee11ae36949 100644 (file)
@@ -44,24 +44,18 @@ idal_is_needed(void *vaddr, unsigned int length)
 /*
  * Return the number of idal words needed for an address/length pair.
  */
-static inline unsigned int
-idal_nr_words(void *vaddr, unsigned int length)
+static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
 {
-#ifdef __s390x__
-       if (idal_is_needed(vaddr, length))
-               return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length + 
-                       (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
-#endif
-       return 0;
+       return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
+               (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
 }
 
 /*
  * Create the list of idal words for an address/length pair.
  */
-static inline unsigned long *
-idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length)
+static inline unsigned long *idal_create_words(unsigned long *idaws,
+                                              void *vaddr, unsigned int length)
 {
-#ifdef __s390x__
        unsigned long paddr;
        unsigned int cidaw;
 
@@ -74,7 +68,6 @@ idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length)
                paddr += IDA_BLOCK_SIZE;
                *idaws++ = paddr;
        }
-#endif
        return idaws;
 }
 
index f3720defdd164de6e47cc5524cc9f5f67564f3b9..b349f1c7fdfab9dc73d91bcb9e177e38c74dc538 100644 (file)
 #ifndef _ASM_S390_LOWCORE_H
 #define _ASM_S390_LOWCORE_H
 
-#ifndef __s390x__
-#define __LC_EXT_OLD_PSW                0x018
-#define __LC_SVC_OLD_PSW                0x020
-#define __LC_PGM_OLD_PSW                0x028
-#define __LC_MCK_OLD_PSW                0x030
-#define __LC_IO_OLD_PSW                 0x038
-#define __LC_EXT_NEW_PSW                0x058
-#define __LC_SVC_NEW_PSW                0x060
-#define __LC_PGM_NEW_PSW                0x068
-#define __LC_MCK_NEW_PSW                0x070
-#define __LC_IO_NEW_PSW                 0x078
-#else /* !__s390x__ */
-#define __LC_EXT_OLD_PSW                0x0130
-#define __LC_SVC_OLD_PSW                0x0140
-#define __LC_PGM_OLD_PSW                0x0150
-#define __LC_MCK_OLD_PSW                0x0160
-#define __LC_IO_OLD_PSW                 0x0170
-#define __LC_EXT_NEW_PSW                0x01b0
-#define __LC_SVC_NEW_PSW                0x01c0
-#define __LC_PGM_NEW_PSW                0x01d0
-#define __LC_MCK_NEW_PSW                0x01e0
-#define __LC_IO_NEW_PSW                 0x01f0
-#endif /* !__s390x__ */
-
-#define __LC_IPL_PARMBLOCK_PTR         0x014
-#define __LC_EXT_PARAMS                 0x080
-#define __LC_CPU_ADDRESS                0x084
-#define __LC_EXT_INT_CODE               0x086
-
-#define __LC_SVC_ILC                    0x088
-#define __LC_SVC_INT_CODE               0x08A
-#define __LC_PGM_ILC                    0x08C
-#define __LC_PGM_INT_CODE               0x08E
+#define __LC_IPL_PARMBLOCK_PTR         0x0014
+#define __LC_EXT_PARAMS                        0x0080
+#define __LC_CPU_ADDRESS               0x0084
+#define __LC_EXT_INT_CODE              0x0086
 
-#define __LC_PER_ATMID                 0x096
-#define __LC_PER_ADDRESS               0x098
-#define __LC_PER_ACCESS_ID             0x0A1
-#define __LC_AR_MODE_ID                        0x0A3
+#define __LC_SVC_ILC                   0x0088
+#define __LC_SVC_INT_CODE              0x008a
+#define __LC_PGM_ILC                   0x008c
+#define __LC_PGM_INT_CODE              0x008e
 
-#define __LC_SUBCHANNEL_ID              0x0B8
-#define __LC_SUBCHANNEL_NR              0x0BA
-#define __LC_IO_INT_PARM                0x0BC
-#define __LC_IO_INT_WORD                0x0C0
-#define __LC_MCCK_CODE                  0x0E8
+#define __LC_PER_ATMID                 0x0096
+#define __LC_PER_ADDRESS               0x0098
+#define __LC_PER_ACCESS_ID             0x00a1
+#define __LC_AR_MODE_ID                        0x00a3
 
-#define __LC_LAST_BREAK                0x110
-
-#define __LC_RETURN_PSW                 0x200
-
-#define __LC_SAVE_AREA                  0xC00
-
-#ifndef __s390x__
-#define __LC_IRB                       0x208
-#define __LC_SYNC_ENTER_TIMER          0x248
-#define __LC_ASYNC_ENTER_TIMER         0x250
-#define __LC_EXIT_TIMER                        0x258
-#define __LC_USER_TIMER                        0x260
-#define __LC_SYSTEM_TIMER              0x268
-#define __LC_STEAL_TIMER               0x270
-#define __LC_LAST_UPDATE_TIMER         0x278
-#define __LC_LAST_UPDATE_CLOCK         0x280
-#define __LC_RETURN_MCCK_PSW            0x288
-#define __LC_KERNEL_STACK               0xC40
-#define __LC_THREAD_INFO               0xC44
-#define __LC_ASYNC_STACK                0xC48
-#define __LC_KERNEL_ASCE               0xC4C
-#define __LC_USER_ASCE                 0xC50
-#define __LC_PANIC_STACK                0xC54
-#define __LC_CPUID                      0xC60
-#define __LC_CPUADDR                    0xC68
-#define __LC_IPLDEV                     0xC7C
-#define __LC_CURRENT                   0xC90
-#define __LC_INT_CLOCK                 0xC98
-#else /* __s390x__ */
-#define __LC_IRB                       0x210
-#define __LC_SYNC_ENTER_TIMER          0x250
-#define __LC_ASYNC_ENTER_TIMER         0x258
-#define __LC_EXIT_TIMER                        0x260
-#define __LC_USER_TIMER                        0x268
-#define __LC_SYSTEM_TIMER              0x270
-#define __LC_STEAL_TIMER               0x278
-#define __LC_LAST_UPDATE_TIMER         0x280
-#define __LC_LAST_UPDATE_CLOCK         0x288
-#define __LC_RETURN_MCCK_PSW            0x290
-#define __LC_KERNEL_STACK               0xD40
-#define __LC_THREAD_INFO               0xD48
-#define __LC_ASYNC_STACK                0xD50
-#define __LC_KERNEL_ASCE               0xD58
-#define __LC_USER_ASCE                 0xD60
-#define __LC_PANIC_STACK                0xD68
-#define __LC_CPUID                     0xD80
-#define __LC_CPUADDR                   0xD88
-#define __LC_IPLDEV                     0xDB8
-#define __LC_CURRENT                   0xDD8
-#define __LC_INT_CLOCK                 0xDE8
-#define __LC_VDSO_PER_CPU              0xE38
-#endif /* __s390x__ */
+#define __LC_SUBCHANNEL_ID             0x00b8
+#define __LC_SUBCHANNEL_NR             0x00ba
+#define __LC_IO_INT_PARM               0x00bc
+#define __LC_IO_INT_WORD               0x00c0
+#define __LC_MCCK_CODE                 0x00e8
 
-#define __LC_PASTE                     0xE40
+#define __LC_DUMP_REIPL                        0x0e00
 
-#define __LC_PANIC_MAGIC               0xE00
 #ifndef __s390x__
-#define __LC_PFAULT_INTPARM             0x080
-#define __LC_CPU_TIMER_SAVE_AREA        0x0D8
-#define __LC_CLOCK_COMP_SAVE_AREA      0x0E0
-#define __LC_PSW_SAVE_AREA             0x100
-#define __LC_PREFIX_SAVE_AREA          0x108
-#define __LC_AREGS_SAVE_AREA            0x120
-#define __LC_FPREGS_SAVE_AREA          0x160
-#define __LC_GPREGS_SAVE_AREA           0x180
-#define __LC_CREGS_SAVE_AREA            0x1C0
+#define __LC_EXT_OLD_PSW               0x0018
+#define __LC_SVC_OLD_PSW               0x0020
+#define __LC_PGM_OLD_PSW               0x0028
+#define __LC_MCK_OLD_PSW               0x0030
+#define __LC_IO_OLD_PSW                        0x0038
+#define __LC_EXT_NEW_PSW               0x0058
+#define __LC_SVC_NEW_PSW               0x0060
+#define __LC_PGM_NEW_PSW               0x0068
+#define __LC_MCK_NEW_PSW               0x0070
+#define __LC_IO_NEW_PSW                        0x0078
+#define __LC_SAVE_AREA                 0x0200
+#define __LC_RETURN_PSW                        0x0240
+#define __LC_RETURN_MCCK_PSW           0x0248
+#define __LC_SYNC_ENTER_TIMER          0x0250
+#define __LC_ASYNC_ENTER_TIMER         0x0258
+#define __LC_EXIT_TIMER                        0x0260
+#define __LC_USER_TIMER                        0x0268
+#define __LC_SYSTEM_TIMER              0x0270
+#define __LC_STEAL_TIMER               0x0278
+#define __LC_LAST_UPDATE_TIMER         0x0280
+#define __LC_LAST_UPDATE_CLOCK         0x0288
+#define __LC_CURRENT                   0x0290
+#define __LC_THREAD_INFO               0x0294
+#define __LC_KERNEL_STACK              0x0298
+#define __LC_ASYNC_STACK               0x029c
+#define __LC_PANIC_STACK               0x02a0
+#define __LC_KERNEL_ASCE               0x02a4
+#define __LC_USER_ASCE                 0x02a8
+#define __LC_USER_EXEC_ASCE            0x02ac
+#define __LC_CPUID                     0x02b0
+#define __LC_INT_CLOCK                 0x02c8
+#define __LC_IRB                       0x0300
+#define __LC_PFAULT_INTPARM            0x0080
+#define __LC_CPU_TIMER_SAVE_AREA       0x00d8
+#define __LC_CLOCK_COMP_SAVE_AREA      0x00e0
+#define __LC_PSW_SAVE_AREA             0x0100
+#define __LC_PREFIX_SAVE_AREA          0x0108
+#define __LC_AREGS_SAVE_AREA           0x0120
+#define __LC_FPREGS_SAVE_AREA          0x0160
+#define __LC_GPREGS_SAVE_AREA          0x0180
+#define __LC_CREGS_SAVE_AREA           0x01c0
 #else /* __s390x__ */
-#define __LC_PFAULT_INTPARM             0x11B8
+#define __LC_LAST_BREAK                        0x0110
+#define __LC_EXT_OLD_PSW               0x0130
+#define __LC_SVC_OLD_PSW               0x0140
+#define __LC_PGM_OLD_PSW               0x0150
+#define __LC_MCK_OLD_PSW               0x0160
+#define __LC_IO_OLD_PSW                        0x0170
+#define __LC_EXT_NEW_PSW               0x01b0
+#define __LC_SVC_NEW_PSW               0x01c0
+#define __LC_PGM_NEW_PSW               0x01d0
+#define __LC_MCK_NEW_PSW               0x01e0
+#define __LC_IO_NEW_PSW                        0x01f0
+#define __LC_SAVE_AREA                 0x0200
+#define __LC_RETURN_PSW                        0x0280
+#define __LC_RETURN_MCCK_PSW           0x0290
+#define __LC_SYNC_ENTER_TIMER          0x02a0
+#define __LC_ASYNC_ENTER_TIMER         0x02a8
+#define __LC_EXIT_TIMER                        0x02b0
+#define __LC_USER_TIMER                        0x02b8
+#define __LC_SYSTEM_TIMER              0x02c0
+#define __LC_STEAL_TIMER               0x02c8
+#define __LC_LAST_UPDATE_TIMER         0x02d0
+#define __LC_LAST_UPDATE_CLOCK         0x02d8
+#define __LC_CURRENT                   0x02e0
+#define __LC_THREAD_INFO               0x02e8
+#define __LC_KERNEL_STACK              0x02f0
+#define __LC_ASYNC_STACK               0x02f8
+#define __LC_PANIC_STACK               0x0300
+#define __LC_KERNEL_ASCE               0x0308
+#define __LC_USER_ASCE                 0x0310
+#define __LC_USER_EXEC_ASCE            0x0318
+#define __LC_CPUID                     0x0320
+#define __LC_INT_CLOCK                 0x0340
+#define __LC_VDSO_PER_CPU              0x0350
+#define __LC_IRB                       0x0380
+#define __LC_PASTE                     0x03c0
+#define __LC_PFAULT_INTPARM            0x11b8
 #define __LC_FPREGS_SAVE_AREA          0x1200
-#define __LC_GPREGS_SAVE_AREA           0x1280
+#define __LC_GPREGS_SAVE_AREA          0x1280
 #define __LC_PSW_SAVE_AREA             0x1300
 #define __LC_PREFIX_SAVE_AREA          0x1318
-#define __LC_FP_CREG_SAVE_AREA         0x131C
+#define __LC_FP_CREG_SAVE_AREA         0x131c
 #define __LC_TODREG_SAVE_AREA          0x1324
-#define __LC_CPU_TIMER_SAVE_AREA        0x1328
+#define __LC_CPU_TIMER_SAVE_AREA       0x1328
 #define __LC_CLOCK_COMP_SAVE_AREA      0x1331
-#define __LC_AREGS_SAVE_AREA            0x1340
-#define __LC_CREGS_SAVE_AREA            0x1380
+#define __LC_AREGS_SAVE_AREA           0x1340
+#define __LC_CREGS_SAVE_AREA           0x1380
 #endif /* __s390x__ */
 
 #ifndef __ASSEMBLY__
@@ -198,222 +187,240 @@ union save_area {
 struct _lowcore
 {
 #ifndef __s390x__
-        /* prefix area: defined by architecture */
-       psw_t        restart_psw;              /* 0x000 */
-       __u32        ccw2[4];                  /* 0x008 */
-       psw_t        external_old_psw;         /* 0x018 */
-       psw_t        svc_old_psw;              /* 0x020 */
-       psw_t        program_old_psw;          /* 0x028 */
-       psw_t        mcck_old_psw;             /* 0x030 */
-       psw_t        io_old_psw;               /* 0x038 */
-       __u8         pad1[0x58-0x40];          /* 0x040 */
-       psw_t        external_new_psw;         /* 0x058 */
-       psw_t        svc_new_psw;              /* 0x060 */
-       psw_t        program_new_psw;          /* 0x068 */
-       psw_t        mcck_new_psw;             /* 0x070 */
-       psw_t        io_new_psw;               /* 0x078 */
-       __u32        ext_params;               /* 0x080 */
-       __u16        cpu_addr;                 /* 0x084 */
-       __u16        ext_int_code;             /* 0x086 */
-        __u16        svc_ilc;                  /* 0x088 */
-        __u16        svc_code;                 /* 0x08a */
-        __u16        pgm_ilc;                  /* 0x08c */
-        __u16        pgm_code;                 /* 0x08e */
-       __u32        trans_exc_code;           /* 0x090 */
-       __u16        mon_class_num;            /* 0x094 */
-       __u16        per_perc_atmid;           /* 0x096 */
-       __u32        per_address;              /* 0x098 */
-       __u32        monitor_code;             /* 0x09c */
-       __u8         exc_access_id;            /* 0x0a0 */
-       __u8         per_access_id;            /* 0x0a1 */
-       __u8         pad2[0xB8-0xA2];          /* 0x0a2 */
-       __u16        subchannel_id;            /* 0x0b8 */
-       __u16        subchannel_nr;            /* 0x0ba */
-       __u32        io_int_parm;              /* 0x0bc */
-       __u32        io_int_word;              /* 0x0c0 */
-       __u8         pad3[0xc8-0xc4];          /* 0x0c4 */
-       __u32        stfl_fac_list;            /* 0x0c8 */
-       __u8         pad4[0xd4-0xcc];          /* 0x0cc */
-       __u32        extended_save_area_addr;  /* 0x0d4 */
-       __u32        cpu_timer_save_area[2];   /* 0x0d8 */
-       __u32        clock_comp_save_area[2];  /* 0x0e0 */
-       __u32        mcck_interruption_code[2]; /* 0x0e8 */
-       __u8         pad5[0xf4-0xf0];          /* 0x0f0 */
-       __u32        external_damage_code;     /* 0x0f4 */
-       __u32        failing_storage_address;  /* 0x0f8 */
-       __u8         pad6[0x100-0xfc];         /* 0x0fc */
-       __u32        st_status_fixed_logout[4];/* 0x100 */
-       __u8         pad7[0x120-0x110];        /* 0x110 */
-       __u32        access_regs_save_area[16];/* 0x120 */
-       __u32        floating_pt_save_area[8]; /* 0x160 */
-       __u32        gpregs_save_area[16];     /* 0x180 */
-       __u32        cregs_save_area[16];      /* 0x1c0 */      
-
-        psw_t        return_psw;               /* 0x200 */
-       __u8         irb[64];                  /* 0x208 */
-       __u64        sync_enter_timer;         /* 0x248 */
-       __u64        async_enter_timer;        /* 0x250 */
-       __u64        exit_timer;               /* 0x258 */
-       __u64        user_timer;               /* 0x260 */
-       __u64        system_timer;             /* 0x268 */
-       __u64        steal_timer;              /* 0x270 */
-       __u64        last_update_timer;        /* 0x278 */
-       __u64        last_update_clock;        /* 0x280 */
-        psw_t        return_mcck_psw;          /* 0x288 */
-       __u8         pad8[0xc00-0x290];        /* 0x290 */
-
-        /* System info area */
-       __u32        save_area[16];            /* 0xc00 */
-       __u32        kernel_stack;             /* 0xc40 */
-       __u32        thread_info;              /* 0xc44 */
-       __u32        async_stack;              /* 0xc48 */
-       __u32        kernel_asce;              /* 0xc4c */
-       __u32        user_asce;                /* 0xc50 */
-       __u32        panic_stack;              /* 0xc54 */
-       __u32        user_exec_asce;           /* 0xc58 */
-       __u8         pad10[0xc60-0xc5c];       /* 0xc5c */
-       /* entry.S sensitive area start */
-       struct       cpuinfo_S390 cpu_data;    /* 0xc60 */
-       __u32        ipl_device;               /* 0xc7c */
-       /* entry.S sensitive area end */
-
-        /* SMP info area: defined by DJB */
-       __u64        clock_comparator;         /* 0xc80 */
-       __u32        ext_call_fast;            /* 0xc88 */
-       __u32        percpu_offset;            /* 0xc8c */
-       __u32        current_task;             /* 0xc90 */
-       __u32        softirq_pending;          /* 0xc94 */
-       __u64        int_clock;                /* 0xc98 */
-        __u8         pad11[0xe00-0xca0];       /* 0xca0 */
-
-        /* 0xe00 is used as indicator for dump tools */
-        /* whether the kernel died with panic() or not */
-        __u32        panic_magic;              /* 0xe00 */
-
-        /* Align to the top 1k of prefix area */
-       __u8         pad12[0x1000-0xe04];      /* 0xe04 */
+       /* 0x0000 - 0x01ff: defined by architecture */
+       psw_t   restart_psw;                    /* 0x0000 */
+       __u32   ccw2[4];                        /* 0x0008 */
+       psw_t   external_old_psw;               /* 0x0018 */
+       psw_t   svc_old_psw;                    /* 0x0020 */
+       psw_t   program_old_psw;                /* 0x0028 */
+       psw_t   mcck_old_psw;                   /* 0x0030 */
+       psw_t   io_old_psw;                     /* 0x0038 */
+       __u8    pad_0x0040[0x0058-0x0040];      /* 0x0040 */
+       psw_t   external_new_psw;               /* 0x0058 */
+       psw_t   svc_new_psw;                    /* 0x0060 */
+       psw_t   program_new_psw;                /* 0x0068 */
+       psw_t   mcck_new_psw;                   /* 0x0070 */
+       psw_t   io_new_psw;                     /* 0x0078 */
+       __u32   ext_params;                     /* 0x0080 */
+       __u16   cpu_addr;                       /* 0x0084 */
+       __u16   ext_int_code;                   /* 0x0086 */
+       __u16   svc_ilc;                        /* 0x0088 */
+       __u16   svc_code;                       /* 0x008a */
+       __u16   pgm_ilc;                        /* 0x008c */
+       __u16   pgm_code;                       /* 0x008e */
+       __u32   trans_exc_code;                 /* 0x0090 */
+       __u16   mon_class_num;                  /* 0x0094 */
+       __u16   per_perc_atmid;                 /* 0x0096 */
+       __u32   per_address;                    /* 0x0098 */
+       __u32   monitor_code;                   /* 0x009c */
+       __u8    exc_access_id;                  /* 0x00a0 */
+       __u8    per_access_id;                  /* 0x00a1 */
+       __u8    pad_0x00a2[0x00b8-0x00a2];      /* 0x00a2 */
+       __u16   subchannel_id;                  /* 0x00b8 */
+       __u16   subchannel_nr;                  /* 0x00ba */
+       __u32   io_int_parm;                    /* 0x00bc */
+       __u32   io_int_word;                    /* 0x00c0 */
+       __u8    pad_0x00c4[0x00c8-0x00c4];      /* 0x00c4 */
+       __u32   stfl_fac_list;                  /* 0x00c8 */
+       __u8    pad_0x00cc[0x00d4-0x00cc];      /* 0x00cc */
+       __u32   extended_save_area_addr;        /* 0x00d4 */
+       __u32   cpu_timer_save_area[2];         /* 0x00d8 */
+       __u32   clock_comp_save_area[2];        /* 0x00e0 */
+       __u32   mcck_interruption_code[2];      /* 0x00e8 */
+       __u8    pad_0x00f0[0x00f4-0x00f0];      /* 0x00f0 */
+       __u32   external_damage_code;           /* 0x00f4 */
+       __u32   failing_storage_address;        /* 0x00f8 */
+       __u8    pad_0x00fc[0x0100-0x00fc];      /* 0x00fc */
+       __u32   st_status_fixed_logout[4];      /* 0x0100 */
+       __u8    pad_0x0110[0x0120-0x0110];      /* 0x0110 */
+
+       /* CPU register save area: defined by architecture */
+       __u32   access_regs_save_area[16];      /* 0x0120 */
+       __u32   floating_pt_save_area[8];       /* 0x0160 */
+       __u32   gpregs_save_area[16];           /* 0x0180 */
+       __u32   cregs_save_area[16];            /* 0x01c0 */
+
+       /* Return psws. */
+       __u32   save_area[16];                  /* 0x0200 */
+       psw_t   return_psw;                     /* 0x0240 */
+       psw_t   return_mcck_psw;                /* 0x0248 */
+
+       /* CPU time accounting values */
+       __u64   sync_enter_timer;               /* 0x0250 */
+       __u64   async_enter_timer;              /* 0x0258 */
+       __u64   exit_timer;                     /* 0x0260 */
+       __u64   user_timer;                     /* 0x0268 */
+       __u64   system_timer;                   /* 0x0270 */
+       __u64   steal_timer;                    /* 0x0278 */
+       __u64   last_update_timer;              /* 0x0280 */
+       __u64   last_update_clock;              /* 0x0288 */
+
+       /* Current process. */
+       __u32   current_task;                   /* 0x0290 */
+       __u32   thread_info;                    /* 0x0294 */
+       __u32   kernel_stack;                   /* 0x0298 */
+
+       /* Interrupt and panic stack. */
+       __u32   async_stack;                    /* 0x029c */
+       __u32   panic_stack;                    /* 0x02a0 */
+
+       /* Address space pointer. */
+       __u32   kernel_asce;                    /* 0x02a4 */
+       __u32   user_asce;                      /* 0x02a8 */
+       __u32   user_exec_asce;                 /* 0x02ac */
+
+       /* SMP info area */
+       cpuid_t cpu_id;                         /* 0x02b0 */
+       __u32   cpu_nr;                         /* 0x02b8 */
+       __u32   softirq_pending;                /* 0x02bc */
+       __u32   percpu_offset;                  /* 0x02c0 */
+       __u32   ext_call_fast;                  /* 0x02c4 */
+       __u64   int_clock;                      /* 0x02c8 */
+       __u64   clock_comparator;               /* 0x02d0 */
+       __u8    pad_0x02d8[0x0300-0x02d8];      /* 0x02d8 */
+
+       /* Interrupt response block */
+       __u8    irb[64];                        /* 0x0300 */
+
+       __u8    pad_0x0400[0x0e00-0x0400];      /* 0x0400 */
+
+       /*
+        * 0xe00 contains the address of the IPL Parameter Information
+        * block. Dump tools need IPIB for IPL after dump.
+        * Note: do not change the position of any fields in 0x0e00-0x0f00
+        */
+       __u32   ipib;                           /* 0x0e00 */
+       __u32   ipib_checksum;                  /* 0x0e04 */
+
+       /* Align to the top 1k of prefix area */
+       __u8    pad_0x0e08[0x1000-0x0e08];      /* 0x0e08 */
 #else /* !__s390x__ */
-        /* prefix area: defined by architecture */
-       __u32        ccw1[2];                  /* 0x000 */
-       __u32        ccw2[4];                  /* 0x008 */
-       __u8         pad1[0x80-0x18];          /* 0x018 */
-       __u32        ext_params;               /* 0x080 */
-       __u16        cpu_addr;                 /* 0x084 */
-       __u16        ext_int_code;             /* 0x086 */
-        __u16        svc_ilc;                  /* 0x088 */
-        __u16        svc_code;                 /* 0x08a */
-        __u16        pgm_ilc;                  /* 0x08c */
-        __u16        pgm_code;                 /* 0x08e */
-       __u32        data_exc_code;            /* 0x090 */
-       __u16        mon_class_num;            /* 0x094 */
-       __u16        per_perc_atmid;           /* 0x096 */
-       addr_t       per_address;              /* 0x098 */
-       __u8         exc_access_id;            /* 0x0a0 */
-       __u8         per_access_id;            /* 0x0a1 */
-       __u8         op_access_id;             /* 0x0a2 */
-       __u8         ar_access_id;             /* 0x0a3 */
-       __u8         pad2[0xA8-0xA4];          /* 0x0a4 */
-       addr_t       trans_exc_code;           /* 0x0A0 */
-       addr_t       monitor_code;             /* 0x09c */
-       __u16        subchannel_id;            /* 0x0b8 */
-       __u16        subchannel_nr;            /* 0x0ba */
-       __u32        io_int_parm;              /* 0x0bc */
-       __u32        io_int_word;              /* 0x0c0 */
-       __u8         pad3[0xc8-0xc4];          /* 0x0c4 */
-       __u32        stfl_fac_list;            /* 0x0c8 */
-       __u8         pad4[0xe8-0xcc];          /* 0x0cc */
-       __u32        mcck_interruption_code[2]; /* 0x0e8 */
-       __u8         pad5[0xf4-0xf0];          /* 0x0f0 */
-       __u32        external_damage_code;     /* 0x0f4 */
-       addr_t       failing_storage_address;  /* 0x0f8 */
-       __u8         pad6[0x120-0x100];        /* 0x100 */
-       psw_t        restart_old_psw;          /* 0x120 */
-       psw_t        external_old_psw;         /* 0x130 */
-       psw_t        svc_old_psw;              /* 0x140 */
-       psw_t        program_old_psw;          /* 0x150 */
-       psw_t        mcck_old_psw;             /* 0x160 */
-       psw_t        io_old_psw;               /* 0x170 */
-       __u8         pad7[0x1a0-0x180];        /* 0x180 */
-       psw_t        restart_psw;              /* 0x1a0 */
-       psw_t        external_new_psw;         /* 0x1b0 */
-       psw_t        svc_new_psw;              /* 0x1c0 */
-       psw_t        program_new_psw;          /* 0x1d0 */
-       psw_t        mcck_new_psw;             /* 0x1e0 */
-       psw_t        io_new_psw;               /* 0x1f0 */
-        psw_t        return_psw;               /* 0x200 */
-       __u8         irb[64];                  /* 0x210 */
-       __u64        sync_enter_timer;         /* 0x250 */
-       __u64        async_enter_timer;        /* 0x258 */
-       __u64        exit_timer;               /* 0x260 */
-       __u64        user_timer;               /* 0x268 */
-       __u64        system_timer;             /* 0x270 */
-       __u64        steal_timer;              /* 0x278 */
-       __u64        last_update_timer;        /* 0x280 */
-       __u64        last_update_clock;        /* 0x288 */
-        psw_t        return_mcck_psw;          /* 0x290 */
-        __u8         pad8[0xc00-0x2a0];        /* 0x2a0 */
-        /* System info area */
-       __u64        save_area[16];            /* 0xc00 */
-        __u8         pad9[0xd40-0xc80];        /* 0xc80 */
-       __u64        kernel_stack;             /* 0xd40 */
-       __u64        thread_info;              /* 0xd48 */
-       __u64        async_stack;              /* 0xd50 */
-       __u64        kernel_asce;              /* 0xd58 */
-       __u64        user_asce;                /* 0xd60 */
-       __u64        panic_stack;              /* 0xd68 */
-       __u64        user_exec_asce;           /* 0xd70 */
-       __u8         pad10[0xd80-0xd78];       /* 0xd78 */
-       /* entry.S sensitive area start */
-       struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
-       __u32        ipl_device;               /* 0xdb8 */
-       __u32        pad11;                    /* 0xdbc */
-       /* entry.S sensitive area end */
-
-        /* SMP info area: defined by DJB */
-       __u64        clock_comparator;         /* 0xdc0 */
-       __u64        ext_call_fast;            /* 0xdc8 */
-       __u64        percpu_offset;            /* 0xdd0 */
-       __u64        current_task;             /* 0xdd8 */
-       __u32        softirq_pending;          /* 0xde0 */
-       __u32        pad_0x0de4;               /* 0xde4 */
-       __u64        int_clock;                /* 0xde8 */
-        __u8         pad12[0xe00-0xdf0];       /* 0xdf0 */
-
-        /* 0xe00 is used as indicator for dump tools */
-        /* whether the kernel died with panic() or not */
-        __u32        panic_magic;              /* 0xe00 */
+       /* 0x0000 - 0x01ff: defined by architecture */
+       __u32   ccw1[2];                        /* 0x0000 */
+       __u32   ccw2[4];                        /* 0x0008 */
+       __u8    pad_0x0018[0x0080-0x0018];      /* 0x0018 */
+       __u32   ext_params;                     /* 0x0080 */
+       __u16   cpu_addr;                       /* 0x0084 */
+       __u16   ext_int_code;                   /* 0x0086 */
+       __u16   svc_ilc;                        /* 0x0088 */
+       __u16   svc_code;                       /* 0x008a */
+       __u16   pgm_ilc;                        /* 0x008c */
+       __u16   pgm_code;                       /* 0x008e */
+       __u32   data_exc_code;                  /* 0x0090 */
+       __u16   mon_class_num;                  /* 0x0094 */
+       __u16   per_perc_atmid;                 /* 0x0096 */
+       addr_t  per_address;                    /* 0x0098 */
+       __u8    exc_access_id;                  /* 0x00a0 */
+       __u8    per_access_id;                  /* 0x00a1 */
+       __u8    op_access_id;                   /* 0x00a2 */
+       __u8    ar_access_id;                   /* 0x00a3 */
+       __u8    pad_0x00a4[0x00a8-0x00a4];      /* 0x00a4 */
+       addr_t  trans_exc_code;                 /* 0x00a8 */
+       addr_t  monitor_code;                   /* 0x00b0 */
+       __u16   subchannel_id;                  /* 0x00b8 */
+       __u16   subchannel_nr;                  /* 0x00ba */
+       __u32   io_int_parm;                    /* 0x00bc */
+       __u32   io_int_word;                    /* 0x00c0 */
+       __u8    pad_0x00c4[0x00c8-0x00c4];      /* 0x00c4 */
+       __u32   stfl_fac_list;                  /* 0x00c8 */
+       __u8    pad_0x00cc[0x00e8-0x00cc];      /* 0x00cc */
+       __u32   mcck_interruption_code[2];      /* 0x00e8 */
+       __u8    pad_0x00f0[0x00f4-0x00f0];      /* 0x00f0 */
+       __u32   external_damage_code;           /* 0x00f4 */
+       addr_t  failing_storage_address;        /* 0x00f8 */
+       __u8    pad_0x0100[0x0120-0x0100];      /* 0x0100 */
+       psw_t   restart_old_psw;                /* 0x0120 */
+       psw_t   external_old_psw;               /* 0x0130 */
+       psw_t   svc_old_psw;                    /* 0x0140 */
+       psw_t   program_old_psw;                /* 0x0150 */
+       psw_t   mcck_old_psw;                   /* 0x0160 */
+       psw_t   io_old_psw;                     /* 0x0170 */
+       __u8    pad_0x0180[0x01a0-0x0180];      /* 0x0180 */
+       psw_t   restart_psw;                    /* 0x01a0 */
+       psw_t   external_new_psw;               /* 0x01b0 */
+       psw_t   svc_new_psw;                    /* 0x01c0 */
+       psw_t   program_new_psw;                /* 0x01d0 */
+       psw_t   mcck_new_psw;                   /* 0x01e0 */
+       psw_t   io_new_psw;                     /* 0x01f0 */
+
+       /* Entry/exit save area & return psws. */
+       __u64   save_area[16];                  /* 0x0200 */
+       psw_t   return_psw;                     /* 0x0280 */
+       psw_t   return_mcck_psw;                /* 0x0290 */
+
+       /* CPU accounting and timing values. */
+       __u64   sync_enter_timer;               /* 0x02a0 */
+       __u64   async_enter_timer;              /* 0x02a8 */
+       __u64   exit_timer;                     /* 0x02b0 */
+       __u64   user_timer;                     /* 0x02b8 */
+       __u64   system_timer;                   /* 0x02c0 */
+       __u64   steal_timer;                    /* 0x02c8 */
+       __u64   last_update_timer;              /* 0x02d0 */
+       __u64   last_update_clock;              /* 0x02d8 */
+
+       /* Current process. */
+       __u64   current_task;                   /* 0x02e0 */
+       __u64   thread_info;                    /* 0x02e8 */
+       __u64   kernel_stack;                   /* 0x02f0 */
+
+       /* Interrupt and panic stack. */
+       __u64   async_stack;                    /* 0x02f8 */
+       __u64   panic_stack;                    /* 0x0300 */
+
+       /* Address space pointer. */
+       __u64   kernel_asce;                    /* 0x0308 */
+       __u64   user_asce;                      /* 0x0310 */
+       __u64   user_exec_asce;                 /* 0x0318 */
+
+       /* SMP info area */
+       cpuid_t cpu_id;                         /* 0x0320 */
+       __u32   cpu_nr;                         /* 0x0328 */
+       __u32   softirq_pending;                /* 0x032c */
+       __u64   percpu_offset;                  /* 0x0330 */
+       __u64   ext_call_fast;                  /* 0x0338 */
+       __u64   int_clock;                      /* 0x0340 */
+       __u64   clock_comparator;               /* 0x0348 */
+       __u64   vdso_per_cpu_data;              /* 0x0350 */
+       __u8    pad_0x0358[0x0380-0x0358];      /* 0x0358 */
+
+       /* Interrupt response block. */
+       __u8    irb[64];                        /* 0x0380 */
 
        /* Per cpu primary space access list */
-       __u8         pad_0xe04[0xe38-0xe04];   /* 0xe04 */
-       __u64        vdso_per_cpu_data;        /* 0xe38 */
-       __u32        paste[16];                /* 0xe40 */
-
-       __u8         pad13[0x11b8-0xe80];      /* 0xe80 */
-
-       /* 64 bit extparam used for pfault, diag 250 etc  */
-       __u64        ext_params2;               /* 0x11B8 */
-
-       __u8         pad14[0x1200-0x11C0];      /* 0x11C0 */
-
-        /* System info area */ 
-
-       __u64        floating_pt_save_area[16]; /* 0x1200 */
-       __u64        gpregs_save_area[16];      /* 0x1280 */
-       __u32        st_status_fixed_logout[4]; /* 0x1300 */
-       __u8         pad15[0x1318-0x1310];      /* 0x1310 */
-       __u32        prefixreg_save_area;       /* 0x1318 */
-       __u32        fpt_creg_save_area;        /* 0x131c */
-       __u8         pad16[0x1324-0x1320];      /* 0x1320 */
-       __u32        tod_progreg_save_area;     /* 0x1324 */
-       __u32        cpu_timer_save_area[2];    /* 0x1328 */
-       __u32        clock_comp_save_area[2];   /* 0x1330 */
-       __u8         pad17[0x1340-0x1338];      /* 0x1338 */
-       __u32        access_regs_save_area[16]; /* 0x1340 */ 
-       __u64        cregs_save_area[16];       /* 0x1380 */
+       __u32   paste[16];                      /* 0x03c0 */
+
+       __u8    pad_0x0400[0x0e00-0x0400];      /* 0x0400 */
+
+       /*
+        * 0xe00 contains the address of the IPL Parameter Information
+        * block. Dump tools need IPIB for IPL after dump.
+        * Note: do not change the position of any fields in 0x0e00-0x0f00
+        */
+       __u64   ipib;                           /* 0x0e00 */
+       __u32   ipib_checksum;                  /* 0x0e08 */
+       __u8    pad_0x0e0c[0x11b8-0x0e0c];      /* 0x0e0c */
+
+       /* 64 bit extparam used for pfault/diag 250: defined by architecture */
+       __u64   ext_params2;                    /* 0x11B8 */
+       __u8    pad_0x11c0[0x1200-0x11C0];      /* 0x11C0 */
+
+       /* CPU register save area: defined by architecture */
+       __u64   floating_pt_save_area[16];      /* 0x1200 */
+       __u64   gpregs_save_area[16];           /* 0x1280 */
+       __u32   st_status_fixed_logout[4];      /* 0x1300 */
+       __u8    pad_0x1310[0x1318-0x1310];      /* 0x1310 */
+       __u32   prefixreg_save_area;            /* 0x1318 */
+       __u32   fpt_creg_save_area;             /* 0x131c */
+       __u8    pad_0x1320[0x1324-0x1320];      /* 0x1320 */
+       __u32   tod_progreg_save_area;          /* 0x1324 */
+       __u32   cpu_timer_save_area[2];         /* 0x1328 */
+       __u32   clock_comp_save_area[2];        /* 0x1330 */
+       __u8    pad_0x1338[0x1340-0x1338];      /* 0x1338 */
+       __u32   access_regs_save_area[16];      /* 0x1340 */
+       __u64   cregs_save_area[16];            /* 0x1380 */
 
        /* align to the top of the prefix area */
-
-       __u8         pad18[0x2000-0x1400];      /* 0x1400 */
+       __u8    pad_0x1400[0x2000-0x1400];      /* 0x1400 */
 #endif /* !__s390x__ */
 } __attribute__((packed)); /* End structure*/
 
@@ -433,8 +440,6 @@ static inline __u32 store_prefix(void)
        return address;
 }
 
-#define __PANIC_MAGIC           0xDEADC0DE
-
 #endif
 
 #endif
index 28ec870655af01fba9750fbc1d9e3105f41579fc..fc7edd6f41b6c736382df3339434caeb4b6da5d7 100644 (file)
@@ -74,7 +74,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                             struct task_struct *tsk)
 {
-       cpu_set(smp_processor_id(), next->cpu_vm_mask);
+       cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
        update_mm(next, tsk);
 }
 
diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h
new file mode 100644 (file)
index 0000000..f4b6044
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *   Machine check handler definitions
+ *
+ *    Copyright IBM Corp. 2000,2009
+ *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *              Cornelia Huck <cornelia.huck@de.ibm.com>,
+ *              Heiko Carstens <heiko.carstens@de.ibm.com>,
+ */
+
+#ifndef _ASM_S390_NMI_H
+#define _ASM_S390_NMI_H
+
+#include <linux/types.h>
+
+struct mci {
+       __u32 sd :  1; /* 00 system damage */
+       __u32 pd :  1; /* 01 instruction-processing damage */
+       __u32 sr :  1; /* 02 system recovery */
+       __u32    :  1; /* 03 */
+       __u32 cd :  1; /* 04 timing-facility damage */
+       __u32 ed :  1; /* 05 external damage */
+       __u32    :  1; /* 06 */
+       __u32 dg :  1; /* 07 degradation */
+       __u32 w  :  1; /* 08 warning pending */
+       __u32 cp :  1; /* 09 channel-report pending */
+       __u32 sp :  1; /* 10 service-processor damage */
+       __u32 ck :  1; /* 11 channel-subsystem damage */
+       __u32    :  2; /* 12-13 */
+       __u32 b  :  1; /* 14 backed up */
+       __u32    :  1; /* 15 */
+       __u32 se :  1; /* 16 storage error uncorrected */
+       __u32 sc :  1; /* 17 storage error corrected */
+       __u32 ke :  1; /* 18 storage-key error uncorrected */
+       __u32 ds :  1; /* 19 storage degradation */
+       __u32 wp :  1; /* 20 psw mwp validity */
+       __u32 ms :  1; /* 21 psw mask and key validity */
+       __u32 pm :  1; /* 22 psw program mask and cc validity */
+       __u32 ia :  1; /* 23 psw instruction address validity */
+       __u32 fa :  1; /* 24 failing storage address validity */
+       __u32    :  1; /* 25 */
+       __u32 ec :  1; /* 26 external damage code validity */
+       __u32 fp :  1; /* 27 floating point register validity */
+       __u32 gr :  1; /* 28 general register validity */
+       __u32 cr :  1; /* 29 control register validity */
+       __u32    :  1; /* 30 */
+       __u32 st :  1; /* 31 storage logical validity */
+       __u32 ie :  1; /* 32 indirect storage error */
+       __u32 ar :  1; /* 33 access register validity */
+       __u32 da :  1; /* 34 delayed access exception */
+       __u32    :  7; /* 35-41 */
+       __u32 pr :  1; /* 42 tod programmable register validity */
+       __u32 fc :  1; /* 43 fp control register validity */
+       __u32 ap :  1; /* 44 ancillary report */
+       __u32    :  1; /* 45 */
+       __u32 ct :  1; /* 46 cpu timer validity */
+       __u32 cc :  1; /* 47 clock comparator validity */
+       __u32    : 16; /* 47-63 */
+};
+
+struct pt_regs;
+
+extern void s390_handle_mcck(void);
+extern void s390_do_machine_check(struct pt_regs *regs);
+
+#endif /* _ASM_S390_NMI_H */
index db4523fe38ac918d6ce29f1698f6f489ca6e5af2..61862b3ac7941132db66c23d04ca33122b33b7b6 100644 (file)
@@ -42,22 +42,8 @@ static inline void get_cpu_id(cpuid_t *ptr)
        asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
 }
 
-struct cpuinfo_S390
-{
-        cpuid_t  cpu_id;
-        __u16    cpu_addr;
-        __u16    cpu_nr;
-        unsigned long loops_per_jiffy;
-        unsigned long *pgd_quick;
-#ifdef __s390x__
-        unsigned long *pmd_quick;
-#endif /* __s390x__ */
-        unsigned long *pte_quick;
-        unsigned long pgtable_cache_sz;
-};
-
 extern void s390_adjust_jiffies(void);
-extern void print_cpu_info(struct cpuinfo_S390 *);
+extern void print_cpu_info(void);
 extern int get_cpu_capability(unsigned int *);
 
 /*
index 8920025c3c02ed3bb95919861bf4b16b823a731f..f1b051630c50c50fbf83ee82e42a16ecbae3a184 100644 (file)
 #define NUM_CRS                16
 #define NUM_ACRS       16
 
+#define NUM_CR_WORDS   3
+
 #define FPR_SIZE       8
 #define FPC_SIZE       4
 #define FPC_PAD_SIZE   4 /* gcc insists on aligning the fpregs */
@@ -334,7 +336,7 @@ struct pt_regs
  */
 typedef struct
 {
-       unsigned long cr[3];
+       unsigned long cr[NUM_CR_WORDS];
 } per_cr_words;
 
 #define PER_EM_MASK 0xE8000000UL
index 27fc1746de1578a7611f97ce92e252d2227ed3c4..402d6dcf0d26dbff39470e728432b4bbd0896911 100644 (file)
@@ -314,6 +314,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
                            int, int, unsigned long);
 
 /* 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
index 024b91e06239293b38be4f6598a81631eebd4702..2009158a4502cf859e242ab5068efd74eb75949f 100644 (file)
@@ -50,12 +50,7 @@ extern void machine_power_off_smp(void);
  
 #define PROC_CHANGE_PENALTY    20              /* Schedule penalty */
 
-#define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
-
-static inline __u16 hard_smp_processor_id(void)
-{
-       return stap();
-}
+#define raw_smp_processor_id() (S390_lowcore.cpu_nr)
 
 /*
  * returns 1 if cpu is in stopped/check stopped state or not operational
index d074673a6d9b500010e3c7f4ad25cfbaea5b2d68..cd0241db5a4688b754d6838497cfc06768b4025e 100644 (file)
@@ -100,6 +100,7 @@ static inline char *strcat(char *dst, const char *src)
 
 static inline char *strcpy(char *dst, const char *src)
 {
+#if __GNUC__ < 4
        register int r0 asm("0") = 0;
        char *ret = dst;
 
@@ -109,10 +110,14 @@ static inline char *strcpy(char *dst, const char *src)
                : "+&a" (dst), "+&a" (src) : "d" (r0)
                : "cc", "memory");
        return ret;
+#else
+       return __builtin_strcpy(dst, src);
+#endif
 }
 
 static inline size_t strlen(const char *s)
 {
+#if __GNUC__ < 4
        register unsigned long r0 asm("0") = 0;
        const char *tmp = s;
 
@@ -121,6 +126,9 @@ static inline size_t strlen(const char *s)
                "       jo      0b"
                : "+d" (r0), "+a" (tmp) :  : "cc");
        return r0 - (unsigned long) s;
+#else
+       return __builtin_strlen(s);
+#endif
 }
 
 static inline size_t strnlen(const char * s, size_t n)
@@ -135,7 +143,13 @@ static inline size_t strnlen(const char * s, size_t n)
                : "+a" (end), "+a" (tmp) : "d" (r0)  : "cc");
        return end - s;
 }
-
+#else /* IN_ARCH_STRING_C */
+void *memchr(const void * s, int c, size_t n);
+void *memscan(void *s, int c, size_t n);
+char *strcat(char *dst, const char *src);
+char *strcpy(char *dst, const char *src);
+size_t strlen(const char *s);
+size_t strnlen(const char * s, size_t n);
 #endif /* !IN_ARCH_STRING_C */
 
 #endif /* __KERNEL__ */
index ad93212d9e16a3099087f846edb942612de0694c..9d70057d828c604796082b21d61535eebcd19f87 100644 (file)
@@ -100,6 +100,7 @@ struct sysinfo_3_2_2 {
                char reserved_1[24];
 
        } vm[8];
+       char reserved_544[3552];
 };
 
 static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
index d60394b9745ef60387ad385013f18f23d622980c..304cffa623e158041e128c738999abbed1d3aa5b 100644 (file)
@@ -51,7 +51,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm)
         * If the process only ran on the local cpu, do a local flush.
         */
        local_cpumask = cpumask_of_cpu(smp_processor_id());
-       if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
+       if (cpumask_equal(mm_cpumask(mm), &local_cpumask))
                __tlb_flush_local();
        else
                __tlb_flush_global();
@@ -73,7 +73,7 @@ static inline void __tlb_flush_idte(unsigned long asce)
 
 static inline void __tlb_flush_mm(struct mm_struct * mm)
 {
-       if (unlikely(cpus_empty(mm->cpu_vm_mask)))
+       if (unlikely(cpumask_empty(mm_cpumask(mm))))
                return;
        /*
         * If the machine has IDTE we prefer to do a per mm flush
index c979c3b56ab062f1c4ddc7515b21ca464c38f40b..5e0ad618dc45d2b3ea111f8f494c95e6fa8b99e9 100644 (file)
@@ -5,7 +5,6 @@
 
 #define mc_capable()   (1)
 
-cpumask_t cpu_coregroup_map(unsigned int cpu);
 const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
 
 extern cpumask_t cpu_core_map[NR_CPUS];
index 3a5267d90d29921e9b3e6b60999ab928fa1c087a..8406a2b3157a2d98f16bc4485d83d452a58e9cc5 100644 (file)
@@ -39,7 +39,7 @@ struct vtoc_labeldate
        __u16 day;
 } __attribute__ ((packed));
 
-struct vtoc_volume_label
+struct vtoc_volume_label_cdl
 {
        char volkey[4];         /* volume key = volume label */
        char vollbl[4];         /* volume label */
@@ -56,6 +56,14 @@ struct vtoc_volume_label
        char res3[29];          /* reserved */
 } __attribute__ ((packed));
 
+struct vtoc_volume_label_ldl {
+       char vollbl[4];         /* volume label */
+       char volid[6];          /* volume identifier */
+       char res3[69];          /* reserved */
+       char ldl_version;       /* version number, valid for ldl format */
+       __u64 formatted_blocks; /* valid when ldl_version >= f2  */
+} __attribute__ ((packed));
+
 struct vtoc_extent
 {
        __u8 typeind;                   /* extent type indicator */
@@ -140,7 +148,11 @@ struct vtoc_format4_label
        char res2[10];          /* reserved */
        __u8 DS4EFLVL;          /* extended free-space management level */
        struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */
-       char res3[9];           /* reserved */
+       char res3;              /* reserved */
+       __u32 DS4DCYL;          /* number of logical cyls */
+       char res4[2];           /* reserved */
+       __u8 DS4DEVF2;          /* device flags */
+       char res5;              /* reserved */
 } __attribute__ ((packed));
 
 struct vtoc_ds5ext
index 3edc6c6f258b2a06b9f7bb09591964ebbce7ebd3..228e3105ded772da7d975faf6afaddb73a4e1e9e 100644 (file)
@@ -17,10 +17,12 @@ CFLAGS_smp.o        := -Wno-nonnull
 #
 CFLAGS_ptrace.o                += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
+CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
+
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o setup.o \
            processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
            s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
-           vdso.o vtime.o
+           vdso.o vtime.o sysinfo.o nmi.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/bitmap.S b/arch/s390/kernel/bitmap.S
deleted file mode 100644 (file)
index dfb41f9..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  arch/s390/kernel/bitmap.S
- *    Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
- *    See include/asm-s390/{bitops.h|posix_types.h} for details
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- */
-
-         .globl _oi_bitmap
-_oi_bitmap:
-         .byte  0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
-
-         .globl _ni_bitmap
-_ni_bitmap:
-         .byte  0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F
-
-         .globl _zb_findmap
-_zb_findmap:
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
-         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8
-
-         .globl _sb_findmap
-_sb_findmap:
-         .byte  8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-         .byte  4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-
diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c
new file mode 100644 (file)
index 0000000..3ae4757
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *    Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
+ *    See include/asm/{bitops.h|posix_types.h} for details
+ *
+ *    Copyright IBM Corp. 1999,2009
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ */
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+
+const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+EXPORT_SYMBOL(_oi_bitmap);
+
+const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
+EXPORT_SYMBOL(_ni_bitmap);
+
+const char _zb_findmap[] = {
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+       0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 };
+EXPORT_SYMBOL(_zb_findmap);
+
+const char _sb_findmap[] = {
+       8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+EXPORT_SYMBOL(_sb_findmap);
index a2be3a978d5c43281e3cf3115e2dfb19d473307f..123dd660d7fbed3793ed34a6dee6add2bc25c05a 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef _PTRACE32_H
 #define _PTRACE32_H
 
+#include <asm/ptrace.h>    /* needed for NUM_CR_WORDS */
 #include "compat_linux.h"  /* needed for psw_compat_t */
 
 typedef struct {
-       __u32 cr[3];
+       __u32 cr[NUM_CR_WORDS];
 } per_cr_words32;
 
 typedef struct {
index ba03fc0a3a569777fc3b1936cbe6f54d254d6e34..be8bceaf37d96660e9b5e3ecd56d689fd86bc3e6 100644 (file)
@@ -603,7 +603,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
 static int
 debug_open(struct inode *inode, struct file *file)
 {
-       int i = 0, rc = 0;
+       int i, rc = 0;
        file_private_info_t *p_info;
        debug_info_t *debug_info, *debug_info_snapshot;
 
@@ -642,8 +642,7 @@ found:
        p_info = kmalloc(sizeof(file_private_info_t),
                                                GFP_KERNEL);
        if(!p_info){
-               if(debug_info_snapshot)
-                       debug_info_free(debug_info_snapshot);
+               debug_info_free(debug_info_snapshot);
                rc = -ENOMEM;
                goto out;
        }
@@ -698,8 +697,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area,
        if ((uid != 0) || (gid != 0))
                pr_warning("Root becomes the owner of all s390dbf files "
                           "in sysfs\n");
-       if (!initialized)
-               BUG();
+       BUG_ON(!initialized);
        mutex_lock(&debug_mutex);
 
         /* create new debug_info */
@@ -1156,7 +1154,6 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
        else {
                debugfs_remove(id->debugfs_entries[i]);
                id->views[i] = NULL;
-               rc = 0;
        }
        spin_unlock_irqrestore(&id->lock, flags);
 out:
index 2a2ca268b1dd6e6bc38115496674ee965f8ef29a..4d221c81c84941a13f3350a4f539b231d05cc8d2 100644 (file)
@@ -6,6 +6,7 @@
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
+#include <linux/compiler.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -20,6 +21,7 @@
 #include <asm/processor.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
+#include <asm/sysinfo.h>
 #include <asm/cpcmd.h>
 #include <asm/sclp.h>
 #include "entry.h"
@@ -173,19 +175,21 @@ static noinline __init void init_kernel_storage_key(void)
                page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
 }
 
+static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
+
 static noinline __init void detect_machine_type(void)
 {
-       struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
-
-       get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
-
-       /* Running under z/VM ? */
-       if (cpuinfo->cpu_id.version == 0xff)
-               machine_flags |= MACHINE_FLAG_VM;
+       /* No VM information? Looks like LPAR */
+       if (stsi(&vmms, 3, 2, 2) == -ENOSYS)
+               return;
+       if (!vmms.count)
+               return;
 
-       /* Running under KVM ? */
-       if (cpuinfo->cpu_id.version == 0xfe)
+       /* Running under KVM? If not we assume z/VM */
+       if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3))
                machine_flags |= MACHINE_FLAG_KVM;
+       else
+               machine_flags |= MACHINE_FLAG_VM;
 }
 
 static __init void early_pgm_check_handler(void)
@@ -348,7 +352,6 @@ static void __init setup_boot_command_line(void)
 
        /* copy arch command line */
        strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
-       boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
 
        /* append IPL PARM data to the boot command line */
        if (MACHINE_IS_VM) {
index ec7e35f6055b238dc3c18eaeff09054ec7ecfb3f..1046c2c9f8d139b723ce32fbeded0b71fc1f388b 100644 (file)
@@ -469,6 +469,8 @@ start:
        .org    0x10000
 startup:basr   %r13,0                  # get base
 .LPG0:
+       xc      0x200(256),0x200        # partially clear lowcore
+       xc      0x300(256),0x300
 
 #ifndef CONFIG_MARCH_G5
        # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
index db476d114caabd5c79b016110f503d507de2f312..2ced846065b7a61e340fc88d9b390a4416ead542 100644 (file)
@@ -20,7 +20,6 @@ startup_continue:
        lctl    %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
        l       %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
                                        # move IPL device to lowcore
-       mvc     __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
 #
 # Setup stack
 #
index f9f70aa15244152423cd3ff0182224e6158197ab..65667b2e65cee6fdd3ed71f104ee326d4ec13d86 100644 (file)
@@ -86,7 +86,6 @@ startup_continue:
        lctlg   %c0,%c15,.Lctl-.LPG1(%r13)      # load control registers
        lg      %r12,.Lparmaddr-.LPG1(%r13)     # pointer to parameter area
                                        # move IPL device to lowcore
-       mvc     __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
        lghi    %r0,__LC_PASTE
        stg     %r0,__LC_VDSO_PER_CPU
 #
index 2dcf590faba69cca7b36f3d2731611c1ed4acc00..6f3711a0eaaa108bd2e9b1b1796096cedd906963 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/ebcdic.h>
 #include <asm/reset.h>
 #include <asm/sclp.h>
-#include <asm/setup.h>
+#include <asm/checksum.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
 
@@ -56,13 +56,14 @@ struct shutdown_trigger {
 };
 
 /*
- * Five shutdown action types are supported:
+ * The following shutdown action types are supported:
  */
 #define SHUTDOWN_ACTION_IPL_STR                "ipl"
 #define SHUTDOWN_ACTION_REIPL_STR      "reipl"
 #define SHUTDOWN_ACTION_DUMP_STR       "dump"
 #define SHUTDOWN_ACTION_VMCMD_STR      "vmcmd"
 #define SHUTDOWN_ACTION_STOP_STR       "stop"
+#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
 
 struct shutdown_action {
        char *name;
@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
 static struct ipl_parameter_block *reipl_block_fcp;
 static struct ipl_parameter_block *reipl_block_ccw;
 static struct ipl_parameter_block *reipl_block_nss;
+static struct ipl_parameter_block *reipl_block_actual;
 
 static int dump_capabilities = DUMP_TYPE_NONE;
 static enum dump_type dump_type = DUMP_TYPE_NONE;
@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type)
                        reipl_method = REIPL_METHOD_CCW_VM;
                else
                        reipl_method = REIPL_METHOD_CCW_CIO;
+               reipl_block_actual = reipl_block_ccw;
                break;
        case IPL_TYPE_FCP:
                if (diag308_set_works)
@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type)
                        reipl_method = REIPL_METHOD_FCP_RO_VM;
                else
                        reipl_method = REIPL_METHOD_FCP_RO_DIAG;
+               reipl_block_actual = reipl_block_fcp;
                break;
        case IPL_TYPE_FCP_DUMP:
                reipl_method = REIPL_METHOD_FCP_DUMP;
@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type)
                        reipl_method = REIPL_METHOD_NSS_DIAG;
                else
                        reipl_method = REIPL_METHOD_NSS;
+               reipl_block_actual = reipl_block_nss;
                break;
        case IPL_TYPE_UNKNOWN:
                reipl_method = REIPL_METHOD_DEFAULT;
@@ -960,7 +965,6 @@ static void reipl_run(struct shutdown_trigger *trigger)
                diag308(DIAG308_IPL, NULL);
                break;
        case REIPL_METHOD_FCP_DUMP:
-       default:
                break;
        }
        disabled_wait((unsigned long) __builtin_return_address(0));
@@ -1069,10 +1073,12 @@ static int __init reipl_fcp_init(void)
 {
        int rc;
 
-       if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
-               return 0;
-       if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
-               make_attrs_ro(reipl_fcp_attrs);
+       if (!diag308_set_works) {
+               if (ipl_info.type == IPL_TYPE_FCP)
+                       make_attrs_ro(reipl_fcp_attrs);
+               else
+                       return 0;
+       }
 
        reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
        if (!reipl_block_fcp)
@@ -1253,7 +1259,6 @@ static void dump_run(struct shutdown_trigger *trigger)
                diag308(DIAG308_DUMP, NULL);
                break;
        case DUMP_METHOD_NONE:
-       default:
                return;
        }
        printk(KERN_EMERG "Dump failed!\n");
@@ -1332,6 +1337,49 @@ static struct shutdown_action __refdata dump_action = {
        .init   = dump_init,
 };
 
+static void dump_reipl_run(struct shutdown_trigger *trigger)
+{
+       preempt_disable();
+       /*
+        * Bypass dynamic address translation (DAT) when storing IPL parameter
+        * information block address and checksum into the prefix area
+        * (corresponding to absolute addresses 0-8191).
+        * When enhanced DAT applies and the STE format control in one,
+        * the absolute address is formed without prefixing. In this case a
+        * normal store (stg/st) into the prefix area would no more match to
+        * absolute addresses 0-8191.
+        */
+#ifdef CONFIG_64BIT
+       asm volatile("sturg %0,%1"
+               :: "a" ((unsigned long) reipl_block_actual),
+               "a" (&lowcore_ptr[smp_processor_id()]->ipib));
+#else
+       asm volatile("stura %0,%1"
+               :: "a" ((unsigned long) reipl_block_actual),
+               "a" (&lowcore_ptr[smp_processor_id()]->ipib));
+#endif
+       asm volatile("stura %0,%1"
+               :: "a" (csum_partial(reipl_block_actual,
+                                    reipl_block_actual->hdr.len, 0)),
+               "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
+       preempt_enable();
+       dump_run(trigger);
+}
+
+static int __init dump_reipl_init(void)
+{
+       if (!diag308_set_works)
+               return -EOPNOTSUPP;
+       else
+               return 0;
+}
+
+static struct shutdown_action __refdata dump_reipl_action = {
+       .name   = SHUTDOWN_ACTION_DUMP_REIPL_STR,
+       .fn     = dump_reipl_run,
+       .init   = dump_reipl_init,
+};
+
 /*
  * vmcmd shutdown action: Trigger vm command on shutdown.
  */
@@ -1421,7 +1469,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
 /* action list */
 
 static struct shutdown_action *shutdown_actions_list[] = {
-       &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action};
+       &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
+       &vmcmd_action, &stop_action};
 #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
 
 /*
@@ -1434,11 +1483,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
                       size_t len)
 {
        int i;
+
        for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
                if (!shutdown_actions_list[i])
                        continue;
-               if (strncmp(buf, shutdown_actions_list[i]->name,
-                           strlen(shutdown_actions_list[i]->name)) == 0) {
+               if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
                        trigger->action = shutdown_actions_list[i];
                        return len;
                }
@@ -1672,7 +1721,7 @@ static int on_panic_notify(struct notifier_block *self,
 
 static struct notifier_block on_panic_nb = {
        .notifier_call = on_panic_notify,
-       .priority = 0,
+       .priority = INT_MIN,
 };
 
 void __init setup_ipl(void)
@@ -1696,7 +1745,6 @@ void __init setup_ipl(void)
                        sizeof(ipl_info.data.nss.name));
                break;
        case IPL_TYPE_UNKNOWN:
-       default:
                /* We have no info to copy */
                break;
        }
index 59b4e796680af3e3f376285b7fbaa5500092d602..eed4a00cb676238f7fdbc3b1ccc9dbde7ecb0b98 100644 (file)
@@ -310,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
                        info->plt_initialized = 1;
                }
                if (r_type == R_390_PLTOFF16 ||
-                   r_type == R_390_PLTOFF32
-                   || r_type == R_390_PLTOFF64
-                       )
+                   r_type == R_390_PLTOFF32 ||
+                   r_type == R_390_PLTOFF64)
                        val = me->arch.plt_offset - me->arch.got_offset +
                                info->plt_offset + rela->r_addend;
-               else
-                       val =  (Elf_Addr) me->module_core +
-                               me->arch.plt_offset + info->plt_offset + 
-                               rela->r_addend - loc;
+               else {
+                       if (!((r_type == R_390_PLT16DBL &&
+                              val - loc + 0xffffUL < 0x1ffffeUL) ||
+                             (r_type == R_390_PLT32DBL &&
+                              val - loc + 0xffffffffULL < 0x1fffffffeULL)))
+                               val = (Elf_Addr) me->module_core +
+                                       me->arch.plt_offset +
+                                       info->plt_offset;
+                       val += rela->r_addend - loc;
+               }
                if (r_type == R_390_PLT16DBL)
                        *(unsigned short *) loc = val >> 1;
                else if (r_type == R_390_PLTOFF16)
similarity index 62%
rename from drivers/s390/s390mach.c
rename to arch/s390/kernel/nmi.c
index 92b0417f8e12069403f1d50bbfb5653913b5a8f9..4bfdc421d7e92c65868d4a4b7c9783175aed9920 100644 (file)
 /*
- *  drivers/s390/s390mach.c
- *   S/390 machine check handler
+ *   Machine check handler
  *
- *    Copyright IBM Corp. 2000,2008
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- *              Martin Schwidefsky (schwidefsky@de.ibm.com)
- *              Cornelia Huck <cornelia.huck@de.ibm.com>
+ *    Copyright IBM Corp. 2000,2009
+ *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *              Cornelia Huck <cornelia.huck@de.ibm.com>,
+ *              Heiko Carstens <heiko.carstens@de.ibm.com>,
  */
 
 #include <linux/init.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/workqueue.h>
 #include <linux/time.h>
-#include <linux/device.h>
-#include <linux/kthread.h>
-#include <asm/etr.h>
+#include <linux/module.h>
 #include <asm/lowcore.h>
-#include <asm/cio.h>
+#include <asm/smp.h>
+#include <asm/etr.h>
 #include <asm/cpu.h>
-#include "s390mach.h"
-
-static struct semaphore m_sem;
-
-static NORET_TYPE void
-s390_handle_damage(char *msg)
-{
-#ifdef CONFIG_SMP
-       smp_send_stop();
-#endif
-       disabled_wait((unsigned long) __builtin_return_address(0));
-       for(;;);
-}
-
-static crw_handler_t crw_handlers[NR_RSCS];
-
-/**
- * s390_register_crw_handler() - register a channel report word handler
- * @rsc: reporting source code to handle
- * @handler: handler to be registered
- *
- * Returns %0 on success and a negative error value otherwise.
- */
-int s390_register_crw_handler(int rsc, crw_handler_t handler)
-{
-       if ((rsc < 0) || (rsc >= NR_RSCS))
-               return -EINVAL;
-       if (!cmpxchg(&crw_handlers[rsc], NULL, handler))
-               return 0;
-       return -EBUSY;
-}
-
-/**
- * s390_unregister_crw_handler() - unregister a channel report word handler
- * @rsc: reporting source code to handle
- */
-void s390_unregister_crw_handler(int rsc)
-{
-       if ((rsc < 0) || (rsc >= NR_RSCS))
-               return;
-       xchg(&crw_handlers[rsc], NULL);
-       synchronize_sched();
-}
-
-/*
- * Retrieve CRWs and call function to handle event.
- */
-static int s390_collect_crw_info(void *param)
-{
-       struct crw crw[2];
-       int ccode;
-       struct semaphore *sem;
-       unsigned int chain;
-       int ignore;
-
-       sem = (struct semaphore *)param;
-repeat:
-       ignore = down_interruptible(sem);
-       chain = 0;
-       while (1) {
-               if (unlikely(chain > 1)) {
-                       struct crw tmp_crw;
-
-                       printk(KERN_WARNING"%s: Code does not support more "
-                              "than two chained crws; please report to "
-                              "linux390@de.ibm.com!\n", __func__);
-                       ccode = stcrw(&tmp_crw);
-                       printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
-                              "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
-                              __func__, tmp_crw.slct, tmp_crw.oflw,
-                              tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
-                              tmp_crw.erc, tmp_crw.rsid);
-                       printk(KERN_WARNING"%s: This was crw number %x in the "
-                              "chain\n", __func__, chain);
-                       if (ccode != 0)
-                               break;
-                       chain = tmp_crw.chn ? chain + 1 : 0;
-                       continue;
-               }
-               ccode = stcrw(&crw[chain]);
-               if (ccode != 0)
-                       break;
-               printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
-                      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
-                      crw[chain].slct, crw[chain].oflw, crw[chain].chn,
-                      crw[chain].rsc, crw[chain].anc, crw[chain].erc,
-                      crw[chain].rsid);
-               /* Check for overflows. */
-               if (crw[chain].oflw) {
-                       int i;
-
-                       pr_debug("%s: crw overflow detected!\n", __func__);
-                       for (i = 0; i < NR_RSCS; i++) {
-                               if (crw_handlers[i])
-                                       crw_handlers[i](NULL, NULL, 1);
-                       }
-                       chain = 0;
-                       continue;
-               }
-               if (crw[0].chn && !chain) {
-                       chain++;
-                       continue;
-               }
-               if (crw_handlers[crw[chain].rsc])
-                       crw_handlers[crw[chain].rsc](&crw[0],
-                                                    chain ? &crw[1] : NULL,
-                                                    0);
-               /* chain is always 0 or 1 here. */
-               chain = crw[chain].chn ? chain + 1 : 0;
-       }
-       goto repeat;
-       return 0;
-}
+#include <asm/nmi.h>
+#include <asm/crw.h>
 
 struct mcck_struct {
        int kill_task;
@@ -142,12 +28,18 @@ struct mcck_struct {
 
 static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
 
+static NORET_TYPE void s390_handle_damage(char *msg)
+{
+       smp_send_stop();
+       disabled_wait((unsigned long) __builtin_return_address(0));
+       while (1);
+}
+
 /*
  * Main machine check handler function. Will be called with interrupts enabled
  * or disabled and machine checks enabled or disabled.
  */
-void
-s390_handle_mcck(void)
+void s390_handle_mcck(void)
 {
        unsigned long flags;
        struct mcck_struct mcck;
@@ -166,29 +58,24 @@ s390_handle_mcck(void)
        local_irq_restore(flags);
 
        if (mcck.channel_report)
-               up(&m_sem);
-
-#ifdef CONFIG_MACHCHK_WARNING
-/*
- * The warning may remain for a prolonged period on the bare iron.
- * (actually till the machine is powered off, or until the problem is gone)
- * So we just stop listening for the WARNING MCH and prevent continuously
- * being interrupted.  One caveat is however, that we must do this per
- * processor and cannot use the smp version of ctl_clear_bit().
- * On VM we only get one interrupt per virtally presented machinecheck.
- * Though one suffices, we may get one interrupt per (virtual) processor.
- */
+               crw_handle_channel_report();
+       /*
+        * A warning may remain for a prolonged period on the bare iron.
+        * (actually until the machine is powered off, or the problem is gone)
+        * So we just stop listening for the WARNING MCH and avoid continuously
+        * being interrupted.  One caveat is however, that we must do this per
+        * processor and cannot use the smp version of ctl_clear_bit().
+        * On VM we only get one interrupt per virtally presented machinecheck.
+        * Though one suffices, we may get one interrupt per (virtual) cpu.
+        */
        if (mcck.warning) {     /* WARNING pending ? */
                static int mchchk_wng_posted = 0;
-               /*
-                * Use single machine clear, as we cannot handle smp right now
-                */
+
+               /* Use single cpu clear, as we cannot handle smp here. */
                __ctl_clear_bit(14, 24);        /* Disable WARNING MCH */
                if (xchg(&mchchk_wng_posted, 1) == 0)
                        kill_cad_pid(SIGPWR, 1);
        }
-#endif
-
        if (mcck.kill_task) {
                local_irq_enable();
                printk(KERN_EMERG "mcck: Terminating task because of machine "
@@ -204,8 +91,7 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck);
  * returns 0 if all registers could be validated
  * returns 1 otherwise
  */
-static int
-s390_revalidate_registers(struct mci *mci)
+static int notrace s390_revalidate_registers(struct mci *mci)
 {
        int kill_task;
        u64 tmpclock;
@@ -214,22 +100,21 @@ s390_revalidate_registers(struct mci *mci)
 
        kill_task = 0;
        zero = 0;
-       /* General purpose registers */
-       if (!mci->gr)
+
+       if (!mci->gr) {
                /*
                 * General purpose registers couldn't be restored and have
                 * unknown contents. Process needs to be terminated.
                 */
                kill_task = 1;
-
-       /* Revalidate floating point registers */
-       if (!mci->fp)
+       }
+       if (!mci->fp) {
                /*
                 * Floating point registers can't be restored and
                 * therefore the process needs to be terminated.
                 */
                kill_task = 1;
-
+       }
 #ifndef CONFIG_64BIT
        asm volatile(
                "       ld      0,0(%0)\n"
@@ -245,9 +130,8 @@ s390_revalidate_registers(struct mci *mci)
                fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
 #else
                fpt_save_area = (void *) S390_lowcore.extended_save_area_addr;
-               fpt_creg_save_area = fpt_save_area+128;
+               fpt_creg_save_area = fpt_save_area + 128;
 #endif
-               /* Floating point control register */
                if (!mci->fc) {
                        /*
                         * Floating point control register can't be restored.
@@ -278,26 +162,25 @@ s390_revalidate_registers(struct mci *mci)
                        "       ld      15,120(%0)\n"
                        : : "a" (fpt_save_area));
        }
-
        /* Revalidate access registers */
        asm volatile(
                "       lam     0,15,0(%0)"
                : : "a" (&S390_lowcore.access_regs_save_area));
-       if (!mci->ar)
+       if (!mci->ar) {
                /*
                 * Access registers have unknown contents.
                 * Terminating task.
                 */
                kill_task = 1;
-
+       }
        /* Revalidate control registers */
-       if (!mci->cr)
+       if (!mci->cr) {
                /*
                 * Control registers have unknown contents.
                 * Can't recover and therefore stopping machine.
                 */
                s390_handle_damage("invalid control registers.");
-       else
+       } else {
 #ifdef CONFIG_64BIT
                asm volatile(
                        "       lctlg   0,15,0(%0)"
@@ -307,12 +190,11 @@ s390_revalidate_registers(struct mci *mci)
                        "       lctl    0,15,0(%0)"
                        : : "a" (&S390_lowcore.cregs_save_area));
 #endif
-
+       }
        /*
         * We don't even try to revalidate the TOD register, since we simply
         * can't write something sensible into that register.
         */
-
 #ifdef CONFIG_64BIT
        /*
         * See if we can revalidate the TOD programmable register with its
@@ -330,7 +212,6 @@ s390_revalidate_registers(struct mci *mci)
                        : : "a" (&S390_lowcore.tod_progreg_save_area)
                        : "0", "cc");
 #endif
-
        /* Revalidate clock comparator register */
        asm volatile(
                "       stck    0(%1)\n"
@@ -354,32 +235,35 @@ s390_revalidate_registers(struct mci *mci)
 #define MAX_IPD_COUNT  29
 #define MAX_IPD_TIME   (5 * 60 * USEC_PER_SEC) /* 5 minutes */
 
+#define ED_STP_ISLAND  6       /* External damage STP island check */
+#define ED_STP_SYNC    7       /* External damage STP sync check */
+#define ED_ETR_SYNC    12      /* External damage ETR sync check */
+#define ED_ETR_SWITCH  13      /* External damage ETR switch to local */
+
 /*
  * machine check handler.
  */
-void
-s390_do_machine_check(struct pt_regs *regs)
+void notrace s390_do_machine_check(struct pt_regs *regs)
 {
+       static int ipd_count;
        static DEFINE_SPINLOCK(ipd_lock);
        static unsigned long long last_ipd;
-       static int ipd_count;
+       struct mcck_struct *mcck;
        unsigned long long tmp;
        struct mci *mci;
-       struct mcck_struct *mcck;
        int umode;
 
        lockdep_off();
-
        s390_idle_check();
 
        mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
        mcck = &__get_cpu_var(cpu_mcck);
        umode = user_mode(regs);
 
-       if (mci->sd)
+       if (mci->sd) {
                /* System damage -> stopping machine */
                s390_handle_damage("received system damage machine check.");
-
+       }
        if (mci->pd) {
                if (mci->b) {
                        /* Processing backup -> verify if we can survive this */
@@ -409,24 +293,17 @@ s390_do_machine_check(struct pt_regs *regs)
                         * Nullifying exigent condition, therefore we might
                         * retry this instruction.
                         */
-
                        spin_lock(&ipd_lock);
-
                        tmp = get_clock();
-
                        if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
                                ipd_count++;
                        else
                                ipd_count = 1;
-
                        last_ipd = tmp;
-
                        if (ipd_count == MAX_IPD_COUNT)
                                s390_handle_damage("too many ipd retries.");
-
                        spin_unlock(&ipd_lock);
-               }
-               else {
+               } else {
                        /* Processing damage -> stopping machine */
                        s390_handle_damage("received instruction processing "
                                           "damage machine check.");
@@ -441,20 +318,18 @@ s390_do_machine_check(struct pt_regs *regs)
                        mcck->kill_task = 1;
                        mcck->mcck_code = *(unsigned long long *) mci;
                        set_thread_flag(TIF_MCCK_PENDING);
-               }
-               else
+               } else {
                        /*
                         * Couldn't restore all register contents while in
                         * kernel mode -> stopping machine.
                         */
                        s390_handle_damage("unable to revalidate registers.");
+               }
        }
-
        if (mci->cd) {
                /* Timing facility damage */
                s390_handle_damage("TOD clock damaged");
        }
-
        if (mci->ed && mci->ec) {
                /* External damage */
                if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC))
@@ -466,28 +341,23 @@ s390_do_machine_check(struct pt_regs *regs)
                if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND))
                        stp_island_check();
        }
-
        if (mci->se)
                /* Storage error uncorrected */
                s390_handle_damage("received storage error uncorrected "
                                   "machine check.");
-
        if (mci->ke)
                /* Storage key-error uncorrected */
                s390_handle_damage("received storage key-error uncorrected "
                                   "machine check.");
-
        if (mci->ds && mci->fa)
                /* Storage degradation */
                s390_handle_damage("received storage degradation machine "
                                   "check.");
-
        if (mci->cp) {
                /* Channel report word pending */
                mcck->channel_report = 1;
                set_thread_flag(TIF_MCCK_PENDING);
        }
-
        if (mci->w) {
                /* Warning pending */
                mcck->warning = 1;
@@ -496,43 +366,11 @@ s390_do_machine_check(struct pt_regs *regs)
        lockdep_on();
 }
 
-/*
- * s390_init_machine_check
- *
- * initialize machine check handling
- */
-static int
-machine_check_init(void)
+static int __init machine_check_init(void)
 {
-       init_MUTEX_LOCKED(&m_sem);
        ctl_set_bit(14, 25);    /* enable external damage MCH */
-       ctl_set_bit(14, 27);    /* enable system recovery MCH */
-#ifdef CONFIG_MACHCHK_WARNING
+       ctl_set_bit(14, 27);    /* enable system recovery MCH */
        ctl_set_bit(14, 24);    /* enable warning MCH */
-#endif
        return 0;
 }
-
-/*
- * Initialize the machine check handler really early to be able to
- * catch all machine checks that happen during boot
- */
 arch_initcall(machine_check_init);
-
-/*
- * Machine checks for the channel subsystem must be enabled
- * after the channel subsystem is initialized
- */
-static int __init
-machine_check_crw_init (void)
-{
-       struct task_struct *task;
-
-       task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
-       if (IS_ERR(task))
-               return PTR_ERR(task);
-       ctl_set_bit(14, 28);    /* enable channel report MCH */
-       return 0;
-}
-
-device_initcall (machine_check_crw_init);
index 5cd38a90e64d743443baa2bc1cb95e26070d0d9e..b48e961a38f6ee08f0a12b5e7ffc1348fd7c4dcb 100644 (file)
@@ -1,18 +1,10 @@
 /*
- *  arch/s390/kernel/process.c
+ * This file handles the architecture dependent parts of process handling.
  *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *               Hartmut Penner (hp@de.ibm.com),
- *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
- *
- *  Derived from "arch/i386/kernel/process.c"
- *    Copyright (C) 1995, Linus Torvalds
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
+ *    Copyright IBM Corp. 1999,2009
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *              Hartmut Penner <hp@de.ibm.com>,
+ *              Denis Joseph Barrow,
  */
 
 #include <linux/compiler.h>
@@ -47,6 +39,7 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/timer.h>
+#include <asm/nmi.h>
 #include "entry.h"
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -76,7 +69,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sf->gprs[8];
 }
 
-extern void s390_handle_mcck(void);
 /*
  * The idle loop on a S390...
  */
@@ -149,6 +141,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
                       0, &regs, 0, NULL, NULL);
 }
+EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Free current thread data structures etc..
@@ -168,34 +161,35 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
-       unsigned long unused,
-        struct task_struct * p, struct pt_regs * regs)
+               unsigned long unused,
+               struct task_struct *p, struct pt_regs *regs)
 {
-        struct fake_frame
-          {
-           struct stack_frame sf;
-            struct pt_regs childregs;
-          } *frame;
-
-        frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
-        p->thread.ksp = (unsigned long) frame;
+       struct thread_info *ti;
+       struct fake_frame
+       {
+               struct stack_frame sf;
+               struct pt_regs childregs;
+       } *frame;
+
+       frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
+       p->thread.ksp = (unsigned long) frame;
        /* Store access registers to kernel stack of new process. */
-        frame->childregs = *regs;
+       frame->childregs = *regs;
        frame->childregs.gprs[2] = 0;   /* child returns 0 on fork. */
-        frame->childregs.gprs[15] = new_stackp;
-        frame->sf.back_chain = 0;
+       frame->childregs.gprs[15] = new_stackp;
+       frame->sf.back_chain = 0;
 
-        /* new return point is ret_from_fork */
-        frame->sf.gprs[8] = (unsigned long) ret_from_fork;
+       /* new return point is ret_from_fork */
+       frame->sf.gprs[8] = (unsigned long) ret_from_fork;
 
-        /* fake return stack for resume(), don't go back to schedule */
-        frame->sf.gprs[9] = (unsigned long) frame;
+       /* fake return stack for resume(), don't go back to schedule */
+       frame->sf.gprs[9] = (unsigned long) frame;
 
        /* Save access registers to new thread structure. */
        save_access_regs(&p->thread.acrs[0]);
 
 #ifndef CONFIG_64BIT
-        /*
+       /*
         * save fprs to current->thread.fp_regs to merge them with
         * the emulated registers and then copy the result to the child.
         */
@@ -220,10 +214,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
 #endif /* CONFIG_64BIT */
        /* start new process with ar4 pointing to the correct address space */
        p->thread.mm_segment = get_fs();
-        /* Don't copy debug registers */
-        memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
-
-        return 0;
+       /* Don't copy debug registers */
+       memset(&p->thread.per_info, 0, sizeof(p->thread.per_info));
+       /* Initialize per thread user and system timer values */
+       ti = task_thread_info(p);
+       ti->user_timer = 0;
+       ti->system_timer = 0;
+       return 0;
 }
 
 SYSCALL_DEFINE0(fork)
@@ -311,7 +308,7 @@ out:
 int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
 {
 #ifndef CONFIG_64BIT
-        /*
+       /*
         * save fprs to current->thread.fp_regs to merge them with
         * the emulated registers and then copy the result to the dump.
         */
@@ -322,6 +319,7 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
 #endif /* CONFIG_64BIT */
        return 1;
 }
+EXPORT_SYMBOL(dump_fpu);
 
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -346,4 +344,3 @@ unsigned long get_wchan(struct task_struct *p)
        }
        return 0;
 }
-
index 82c1872cfe804c03d838b5625c54add169b7cce9..802c8ab247f30cc25bda2e67569991a2919f0ad1 100644 (file)
 #include <asm/lowcore.h>
 #include <asm/param.h>
 
-void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+void __cpuinit print_cpu_info(void)
 {
        pr_info("Processor %d started, address %d, identification %06X\n",
-               cpuinfo->cpu_nr, cpuinfo->cpu_addr, cpuinfo->cpu_id.ident);
+               S390_lowcore.cpu_nr, S390_lowcore.cpu_addr,
+               S390_lowcore.cpu_id.ident);
 }
 
 /*
@@ -30,48 +31,46 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-       static const char *hwcap_str[8] = {
+       static const char *hwcap_str[9] = {
                "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
-               "edat"
+               "edat", "etf3eh"
        };
-       struct cpuinfo_S390 *cpuinfo;
-       unsigned long n = (unsigned long) v - 1;
-       int i;
+       struct _lowcore *lc;
+       unsigned long n = (unsigned long) v - 1;
+       int i;
 
-       s390_adjust_jiffies();
-       preempt_disable();
-       if (!n) {
-              seq_printf(m, "vendor_id       : IBM/S390\n"
-                         "# processors    : %i\n"
-                         "bogomips per cpu: %lu.%02lu\n",
-                         num_online_cpus(), loops_per_jiffy/(500000/HZ),
-                         (loops_per_jiffy/(5000/HZ))%100);
-              seq_puts(m, "features\t: ");
-              for (i = 0; i < 8; i++)
-                      if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
-                              seq_printf(m, "%s ", hwcap_str[i]);
-              seq_puts(m, "\n");
-       }
+       s390_adjust_jiffies();
+       preempt_disable();
+       if (!n) {
+               seq_printf(m, "vendor_id       : IBM/S390\n"
+                          "# processors    : %i\n"
+                          "bogomips per cpu: %lu.%02lu\n",
+                          num_online_cpus(), loops_per_jiffy/(500000/HZ),
+                          (loops_per_jiffy/(5000/HZ))%100);
+               seq_puts(m, "features\t: ");
+               for (i = 0; i < 9; i++)
+                       if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+                               seq_printf(m, "%s ", hwcap_str[i]);
+               seq_puts(m, "\n");
+       }
 
-       if (cpu_online(n)) {
+       if (cpu_online(n)) {
 #ifdef CONFIG_SMP
-              if (smp_processor_id() == n)
-                      cpuinfo = &S390_lowcore.cpu_data;
-              else
-                      cpuinfo = &lowcore_ptr[n]->cpu_data;
+               lc = (smp_processor_id() == n) ?
+                       &S390_lowcore : lowcore_ptr[n];
 #else
-              cpuinfo = &S390_lowcore.cpu_data;
+               lc = &S390_lowcore;
 #endif
-              seq_printf(m, "processor %li: "
-                         "version = %02X,  "
-                         "identification = %06X,  "
-                         "machine = %04X\n",
-                         n, cpuinfo->cpu_id.version,
-                         cpuinfo->cpu_id.ident,
-                         cpuinfo->cpu_id.machine);
-       }
-       preempt_enable();
-       return 0;
+               seq_printf(m, "processor %li: "
+                          "version = %02X,  "
+                          "identification = %06X,  "
+                          "machine = %04X\n",
+                          n, lc->cpu_id.version,
+                          lc->cpu_id.ident,
+                          lc->cpu_id.machine);
+       }
+       preempt_enable();
+       return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
index c41930499a5f1d0ca921e69e820c3810dcf4a216..774147824c3dc8a6643ad3d786a8e2207f7ca478 100644 (file)
@@ -1,10 +1,7 @@
 /*
- *  arch/s390/kernel/reipl.S
- *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
-                Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *    Copyright IBM Corp 2000,2009
+ *    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
+ *              Denis Joseph Barrow,
  */
 
 #include <asm/lowcore.h>
@@ -30,7 +27,7 @@ do_reipl_asm: basr    %r13,0
                mvc     __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10)
                stfpc   __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
                stckc   .Lclkcmp-.Lpg0(%r13)
-               mvc     __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
+               mvc     __LC_CLOCK_COMP_SAVE_AREA-0x1000(7,%r1),.Lclkcmp-.Lpg0(%r13)
                stpt    __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
                stg     %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
 
index 46b90cb03707305bdc4713653479a2f8376d0b3f..656fcbb9bd83267c3c6a8a509997d8839462914e 100644 (file)
@@ -1,49 +1,5 @@
-/*
- *  arch/s390/kernel/s390_ksyms.c
- *
- *  S390 version
- */
-#include <linux/highuid.h>
 #include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/syscalls.h>
-#include <linux/interrupt.h>
-#include <asm/checksum.h>
-#include <asm/cpcmd.h>
-#include <asm/delay.h>
-#include <asm/pgalloc.h>
-#include <asm/setup.h>
 #include <asm/ftrace.h>
-#ifdef CONFIG_IP_MULTICAST
-#include <net/arp.h>
-#endif
-
-/*
- * memory management
- */
-EXPORT_SYMBOL(_oi_bitmap);
-EXPORT_SYMBOL(_ni_bitmap);
-EXPORT_SYMBOL(_zb_findmap);
-EXPORT_SYMBOL(_sb_findmap);
-
-/*
- * binfmt_elf loader 
- */
-extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(empty_zero_page);
-
-/*
- * misc.
- */
-EXPORT_SYMBOL(machine_flags);
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(csum_fold);
-EXPORT_SYMBOL(console_mode);
-EXPORT_SYMBOL(console_devno);
-EXPORT_SYMBOL(console_irq);
 
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
index c5cfb6185eaca51eb5e9ee3667d1c4d06ee22a52..06201b93cbbf5623fa6247b25ee39edaab3f0da1 100644 (file)
@@ -74,9 +74,17 @@ EXPORT_SYMBOL(uaccess);
  * Machine setup..
  */
 unsigned int console_mode = 0;
+EXPORT_SYMBOL(console_mode);
+
 unsigned int console_devno = -1;
+EXPORT_SYMBOL(console_devno);
+
 unsigned int console_irq = -1;
+EXPORT_SYMBOL(console_irq);
+
 unsigned long machine_flags;
+EXPORT_SYMBOL(machine_flags);
+
 unsigned long elf_hwcap = 0;
 char elf_platform[ELF_PLATFORM_SIZE];
 
@@ -86,6 +94,10 @@ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
 int __initdata memory_end_set;
 unsigned long __initdata memory_end;
 
+/* An array with a pointer to the lowcore of every CPU. */
+struct _lowcore *lowcore_ptr[NR_CPUS];
+EXPORT_SYMBOL(lowcore_ptr);
+
 /*
  * This is set up by the setup-routine at boot-time
  * for S390 need to find out, what we have to setup
@@ -109,13 +121,10 @@ static struct resource data_resource = {
  */
 void __cpuinit cpu_init(void)
 {
-        int addr = hard_smp_processor_id();
-
         /*
          * Store processor id in lowcore (used e.g. in timer_interrupt)
          */
-       get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
-        S390_lowcore.cpu_data.cpu_addr = addr;
+       get_cpu_id(&S390_lowcore.cpu_id);
 
         /*
          * Force FPU initialization:
@@ -125,8 +134,7 @@ void __cpuinit cpu_init(void)
 
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
-        if (current->mm)
-                BUG();
+       BUG_ON(current->mm);
         enter_lazy_tlb(&init_mm, current);
 }
 
@@ -217,7 +225,7 @@ static void __init conmode_default(void)
        }
 }
 
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
 static void __init setup_zfcpdump(unsigned int console_devno)
 {
        static char str[41];
@@ -289,11 +297,7 @@ static int __init early_parse_mem(char *p)
 early_param("mem", early_parse_mem);
 
 #ifdef CONFIG_S390_SWITCH_AMODE
-#ifdef CONFIG_PGSTE
-unsigned int switch_amode = 1;
-#else
 unsigned int switch_amode = 0;
-#endif
 EXPORT_SYMBOL_GPL(switch_amode);
 
 static int set_amode_and_uaccess(unsigned long user_amode,
@@ -414,7 +418,6 @@ setup_lowcore(void)
                PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
        lc->io_new_psw.mask = psw_kernel_bits;
        lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
-       lc->ipl_device = S390_lowcore.ipl_device;
        lc->clock_comparator = -1ULL;
        lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
        lc->async_stack = (unsigned long)
@@ -434,6 +437,7 @@ setup_lowcore(void)
        lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
 #endif
        set_prefix((u32)(unsigned long) lc);
+       lowcore_ptr[0] = lc;
 }
 
 static void __init
@@ -510,7 +514,7 @@ static void __init setup_memory_end(void)
        unsigned long max_mem;
        int i;
 
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
        if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
                memory_end = ZFCPDUMP_HSA_SIZE;
                memory_end_set = 1;
@@ -677,7 +681,6 @@ setup_memory(void)
 static void __init setup_hwcaps(void)
 {
        static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
-       struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
        unsigned long long facility_list_extended;
        unsigned int facility_list;
        int i;
@@ -693,15 +696,22 @@ static void __init setup_hwcaps(void)
         *   Bit 17: the message-security assist is installed
         *   Bit 19: the long-displacement facility is installed
         *   Bit 21: the extended-immediate facility is installed
+        *   Bit 22: extended-translation facility 3 is installed
+        *   Bit 30: extended-translation facility 3 enhancement facility
         * These get translated to:
         *   HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
         *   HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
-        *   HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+        *   HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and
+        *   HWCAP_S390_ETF3EH bit 8 (22 && 30).
         */
        for (i = 0; i < 6; i++)
                if (facility_list & (1UL << (31 - stfl_bits[i])))
                        elf_hwcap |= 1UL << i;
 
+       if ((facility_list & (1UL << (31 - 22)))
+           && (facility_list & (1UL << (31 - 30))))
+               elf_hwcap |= 1UL << 8;
+
        /*
         * Check for additional facilities with store-facility-list-extended.
         * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
@@ -710,20 +720,22 @@ static void __init setup_hwcaps(void)
         * How many facility words are stored depends on the number of
         * doublewords passed to the instruction. The additional facilites
         * are:
-        *   Bit 43: decimal floating point facility is installed
+        *   Bit 42: decimal floating point facility is installed
+        *   Bit 44: perform floating point operation facility is installed
         * translated to:
-        *   HWCAP_S390_DFP bit 6.
+        *   HWCAP_S390_DFP bit 6 (42 && 44).
         */
        if ((elf_hwcap & (1UL << 2)) &&
            __stfle(&facility_list_extended, 1) > 0) {
-               if (facility_list_extended & (1ULL << (64 - 43)))
+               if ((facility_list_extended & (1ULL << (63 - 42)))
+                   && (facility_list_extended & (1ULL << (63 - 44))))
                        elf_hwcap |= 1UL << 6;
        }
 
        if (MACHINE_HAS_HPAGE)
                elf_hwcap |= 1UL << 7;
 
-       switch (cpuinfo->cpu_id.machine) {
+       switch (S390_lowcore.cpu_id.machine) {
        case 0x9672:
 #if !defined(CONFIG_64BIT)
        default:        /* Use "g5" as default for 31 bit kernels. */
@@ -816,7 +828,7 @@ setup_arch(char **cmdline_p)
        setup_lowcore();
 
         cpu_init();
-        __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
+       __cpu_logical_map[0] = stap();
        s390_init_cpu_topology();
 
        /*
index 2d337cbb9329c33e07f9dfccb2f51daa94269e30..006ed5016eb416d8dab512bd2a7e2625e0d498ed 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
+#include <linux/irqflags.h>
 #include <linux/cpu.h>
 #include <linux/timex.h>
 #include <linux/bootmem.h>
 #include <asm/vdso.h>
 #include "entry.h"
 
-/*
- * An array with a pointer the lowcore of every CPU.
- */
-struct _lowcore *lowcore_ptr[NR_CPUS];
-EXPORT_SYMBOL(lowcore_ptr);
-
 static struct task_struct *current_set[NR_CPUS];
 
 static u8 smp_cpu_type;
@@ -81,9 +76,7 @@ void smp_send_stop(void)
 
        /* Disable all interrupts/machine checks */
        __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
-
-       /* write magic number to zero page (absolute 0) */
-       lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
+       trace_hardirqs_off();
 
        /* stop all processors */
        for_each_online_cpu(cpu) {
@@ -233,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
  */
 #define CPU_INIT_NO    1
 
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
 
 /*
  * zfcpdump_prefix_array holds prefix registers for the following scenario:
@@ -274,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
 
 static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
 
-#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
+#endif /* CONFIG_ZFCPDUMP */
 
 static int cpu_stopped(int cpu)
 {
@@ -304,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
 {
        int cpu_id, logical_cpu;
 
-       logical_cpu = first_cpu(avail);
-       if (logical_cpu == NR_CPUS)
+       logical_cpu = cpumask_first(&avail);
+       if (logical_cpu >= nr_cpu_ids)
                return 0;
        for (cpu_id = 0; cpu_id <= 65535; cpu_id++) {
                if (cpu_known(cpu_id))
@@ -316,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
                        continue;
                cpu_set(logical_cpu, cpu_present_map);
                smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
-               logical_cpu = next_cpu(logical_cpu, avail);
-               if (logical_cpu == NR_CPUS)
+               logical_cpu = cpumask_next(logical_cpu, &avail);
+               if (logical_cpu >= nr_cpu_ids)
                        break;
        }
        return 0;
@@ -329,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
        int cpu_id, logical_cpu, cpu;
        int rc;
 
-       logical_cpu = first_cpu(avail);
-       if (logical_cpu == NR_CPUS)
+       logical_cpu = cpumask_first(&avail);
+       if (logical_cpu >= nr_cpu_ids)
                return 0;
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
@@ -351,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
                        smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
                else
                        smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
-               logical_cpu = next_cpu(logical_cpu, avail);
-               if (logical_cpu == NR_CPUS)
+               logical_cpu = cpumask_next(logical_cpu, &avail);
+               if (logical_cpu >= nr_cpu_ids)
                        break;
        }
 out:
@@ -379,7 +372,7 @@ static void __init smp_detect_cpus(void)
 
        c_cpus = 1;
        s_cpus = 0;
-       boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+       boot_cpu_addr = __cpu_logical_map[0];
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                panic("smp_detect_cpus failed to allocate memory\n");
@@ -453,7 +446,7 @@ int __cpuinit start_secondary(void *cpuvoid)
        /* Switch on interrupts */
        local_irq_enable();
        /* Print info about this processor */
-       print_cpu_info(&S390_lowcore.cpu_data);
+       print_cpu_info();
        /* cpu_idle will call schedule for us */
        cpu_idle();
        return 0;
@@ -515,7 +508,6 @@ out:
        return -ENOMEM;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static void smp_free_lowcore(int cpu)
 {
        struct _lowcore *lowcore;
@@ -534,7 +526,6 @@ static void smp_free_lowcore(int cpu)
        free_pages((unsigned long) lowcore, lc_order);
        lowcore_ptr[cpu] = NULL;
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 /* Upping and downing of CPUs */
 int __cpuinit __cpu_up(unsigned int cpu)
@@ -543,16 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu)
        struct _lowcore *cpu_lowcore;
        struct stack_frame *sf;
        sigp_ccode ccode;
+       u32 lowcore;
 
        if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
                return -EIO;
        if (smp_alloc_lowcore(cpu))
                return -ENOMEM;
-
-       ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]),
-                                  cpu, sigp_set_prefix);
-       if (ccode)
-               return -EIO;
+       do {
+               ccode = signal_processor(cpu, sigp_initial_cpu_reset);
+               if (ccode == sigp_busy)
+                       udelay(10);
+               if (ccode == sigp_not_operational)
+                       goto err_out;
+       } while (ccode == sigp_busy);
+
+       lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
+       while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
+               udelay(10);
 
        idle = current_set[cpu];
        cpu_lowcore = lowcore_ptr[cpu];
@@ -571,9 +569,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
                : : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
        cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
        cpu_lowcore->current_task = (unsigned long) idle;
-       cpu_lowcore->cpu_data.cpu_nr = cpu;
+       cpu_lowcore->cpu_nr = cpu;
        cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
-       cpu_lowcore->ipl_device = S390_lowcore.ipl_device;
        eieio();
 
        while (signal_processor(cpu, sigp_restart) == sigp_busy)
@@ -582,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
        while (!cpu_online(cpu))
                cpu_relax();
        return 0;
+
+err_out:
+       smp_free_lowcore(cpu);
+       return -EIO;
 }
 
 static int __init setup_possible_cpus(char *s)
@@ -589,9 +590,8 @@ static int __init setup_possible_cpus(char *s)
        int pcpus, cpu;
 
        pcpus = simple_strtoul(s, NULL, 0);
-       cpu_possible_map = cpumask_of_cpu(0);
-       for (cpu = 1; cpu < pcpus && cpu < NR_CPUS; cpu++)
-               cpu_set(cpu, cpu_possible_map);
+       for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++)
+               set_cpu_possible(cpu, true);
        return 0;
 }
 early_param("possible_cpus", setup_possible_cpus);
@@ -663,7 +663,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        /* request the 0x1201 emergency signal external interrupt */
        if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
                panic("Couldn't request external interrupt 0x1201");
-       print_cpu_info(&S390_lowcore.cpu_data);
+       print_cpu_info();
 
        /* Reallocate current lowcore, but keep its contents. */
        lc_order = sizeof(long) == 8 ? 1 : 0;
similarity index 88%
rename from drivers/s390/sysinfo.c
rename to arch/s390/kernel/sysinfo.c
index 0eea90781385784ae4ab838dce905dcaf4942a89..b5e75e1061c82d35b40b63594f1889ce07d0453b 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  drivers/s390/sysinfo.c
- *
- *  Copyright IBM Corp. 2001, 2008
- *  Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com)
- *            Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *  Copyright IBM Corp. 2001, 2009
+ *  Author(s): Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
+ *            Martin Schwidefsky <schwidefsky@de.ibm.com>,
  */
 
 #include <linux/kernel.h>
@@ -24,7 +22,7 @@
 
 static inline int stsi_0(void)
 {
-       int rc = stsi (NULL, 0, 0, 0);
+       int rc = stsi(NULL, 0, 0, 0);
        return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
 }
 
@@ -78,23 +76,6 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
        return len;
 }
 
-#if 0 /* Currently unused */
-static int stsi_1_2_1(struct sysinfo_1_2_1 *info, char *page, int len)
-{
-       if (stsi(info, 1, 2, 1) == -ENOSYS)
-               return len;
-
-       len += sprintf(page + len, "\n");
-       EBCASC(info->sequence, sizeof(info->sequence));
-       EBCASC(info->plant, sizeof(info->plant));
-       len += sprintf(page + len, "Sequence Code of CPU: %-16.16s\n",
-                      info->sequence);
-       len += sprintf(page + len, "Plant of CPU:         %-16.16s\n",
-                      info->plant);
-       return len;
-}
-#endif
-
 static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
 {
        struct sysinfo_1_2_2_extension *ext;
@@ -145,33 +126,15 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
        if (info->secondary_capability != 0)
                len += sprintf(page + len, "Secondary Capability: %d\n",
                               info->secondary_capability);
-
        return len;
 }
 
-#if 0 /* Currently unused */
-static int stsi_2_2_1(struct sysinfo_2_2_1 *info, char *page, int len)
-{
-       if (stsi(info, 2, 2, 1) == -ENOSYS)
-               return len;
-
-       len += sprintf(page + len, "\n");
-       EBCASC (info->sequence, sizeof(info->sequence));
-       EBCASC (info->plant, sizeof(info->plant));
-       len += sprintf(page + len, "Sequence Code of logical CPU: %-16.16s\n",
-                      info->sequence);
-       len += sprintf(page + len, "Plant of logical CPU: %-16.16s\n",
-                      info->plant);
-       return len;
-}
-#endif
-
 static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len)
 {
        if (stsi(info, 2, 2, 2) == -ENOSYS)
                return len;
 
-       EBCASC (info->name, sizeof(info->name));
+       EBCASC(info->name, sizeof(info->name));
 
        len += sprintf(page + len, "\n");
        len += sprintf(page + len, "LPAR Number:          %d\n",
@@ -214,8 +177,8 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
        if (stsi(info, 3, 2, 2) == -ENOSYS)
                return len;
        for (i = 0; i < info->count; i++) {
-               EBCASC (info->vm[i].name, sizeof(info->vm[i].name));
-               EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi));
+               EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
+               EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
                len += sprintf(page + len, "\n");
                len += sprintf(page + len, "VM%02d Name:            %-8.8s\n",
                               i, info->vm[i].name);
@@ -237,14 +200,13 @@ static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
        return len;
 }
 
-
 static int proc_read_sysinfo(char *page, char **start,
-                             off_t off, int count,
-                             int *eof, void *data)
+                            off_t off, int count,
+                            int *eof, void *data)
 {
-       unsigned long info = get_zeroed_page (GFP_KERNEL);
+       unsigned long info = get_zeroed_page(GFP_KERNEL);
        int level, len;
-       
+
        if (!info)
                return 0;
 
@@ -262,8 +224,8 @@ static int proc_read_sysinfo(char *page, char **start,
        if (level >= 3)
                len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len);
 
-       free_page (info);
-        return len;
+       free_page(info);
+       return len;
 }
 
 static __init int create_proc_sysinfo(void)
@@ -272,8 +234,7 @@ static __init int create_proc_sysinfo(void)
                               proc_read_sysinfo, NULL);
        return 0;
 }
-
-__initcall(create_proc_sysinfo);
+device_initcall(create_proc_sysinfo);
 
 /*
  * Service levels interface.
@@ -387,13 +348,11 @@ static __init int create_proc_service_level(void)
                register_service_level(&service_level_vm);
        return 0;
 }
-
 subsys_initcall(create_proc_service_level);
 
 /*
  * Bogomips calculation based on cpu capability.
  */
-
 int get_cpu_capability(unsigned int *capability)
 {
        struct sysinfo_1_2_2 *info;
index fc468cae4460ace449d92250f777f70490a25380..f72d41068dc2d7177c0e5c7f70aebb75754a5edd 100644 (file)
@@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old,
 }
 
 static DEFINE_PER_CPU(atomic_t, clock_sync_word);
+static DEFINE_MUTEX(clock_sync_mutex);
 static unsigned long clock_sync_flags;
 
 #define CLOCK_SYNC_HAS_ETR     0
@@ -394,6 +395,20 @@ static void enable_sync_clock(void)
        atomic_set_mask(0x80000000, sw_ptr);
 }
 
+/*
+ * Function to check if the clock is in sync.
+ */
+static inline int check_sync_clock(void)
+{
+       atomic_t *sw_ptr;
+       int rc;
+
+       sw_ptr = &get_cpu_var(clock_sync_word);
+       rc = (atomic_read(sw_ptr) & 0x80000000U) != 0;
+       put_cpu_var(clock_sync_sync);
+       return rc;
+}
+
 /* Single threaded workqueue used for etr and stp sync events */
 static struct workqueue_struct *time_sync_wq;
 
@@ -485,6 +500,8 @@ static void etr_reset(void)
        if (etr_setr(&etr_eacr) == 0) {
                etr_tolec = get_clock();
                set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags);
+               if (etr_port0_online && etr_port1_online)
+                       set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
        } else if (etr_port0_online || etr_port1_online) {
                pr_warning("The real or virtual hardware system does "
                           "not provide an ETR interface\n");
@@ -533,8 +550,7 @@ void etr_switch_to_local(void)
 {
        if (!etr_eacr.sl)
                return;
-       if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
-               disable_sync_clock(NULL);
+       disable_sync_clock(NULL);
        set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
        queue_work(time_sync_wq, &etr_work);
 }
@@ -549,8 +565,7 @@ void etr_sync_check(void)
 {
        if (!etr_eacr.es)
                return;
-       if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
-               disable_sync_clock(NULL);
+       disable_sync_clock(NULL);
        set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
        queue_work(time_sync_wq, &etr_work);
 }
@@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
         * Do not try to get the alternate port aib if the clock
         * is not in sync yet.
         */
-       if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es)
+       if (!check_sync_clock())
                return eacr;
 
        /*
@@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work)
                on_each_cpu(disable_sync_clock, NULL, 1);
                del_timer_sync(&etr_timer);
                etr_update_eacr(eacr);
-               clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
                goto out_unlock;
        }
 
@@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work)
                /* Both ports not usable. */
                eacr.es = eacr.sl = 0;
                sync_port = -1;
-               clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
        }
 
-       if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
-               eacr.es = 0;
-
        /*
         * If the clock is in sync just update the eacr and return.
         * If there is no valid sync port wait for a port update.
         */
-       if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) ||
-           eacr.es || sync_port < 0) {
+       if (check_sync_clock() || sync_port < 0) {
                etr_update_eacr(eacr);
                etr_set_tolec_timeout(now);
                goto out_unlock;
@@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work)
         * and set up a timer to try again after 0.5 seconds
         */
        etr_update_eacr(eacr);
-       set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
        if (now < etr_tolec + (1600000 << 12) ||
            etr_sync_clock_stop(&aib, sync_port) != 0) {
                /* Sync failed. Try again in 1/2 second. */
                eacr.es = 0;
                etr_update_eacr(eacr);
-               clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
                etr_set_sync_timeout();
        } else
                etr_set_tolec_timeout(now);
@@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev,
                return -EINVAL;
        if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
                return -EOPNOTSUPP;
+       mutex_lock(&clock_sync_mutex);
        if (dev == &etr_port0_dev) {
                if (etr_port0_online == value)
-                       return count;   /* Nothing to do. */
+                       goto out;       /* Nothing to do. */
                etr_port0_online = value;
+               if (etr_port0_online && etr_port1_online)
+                       set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
+               else
+                       clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
                set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
                queue_work(time_sync_wq, &etr_work);
        } else {
                if (etr_port1_online == value)
-                       return count;   /* Nothing to do. */
+                       goto out;       /* Nothing to do. */
                etr_port1_online = value;
+               if (etr_port0_online && etr_port1_online)
+                       set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
+               else
+                       clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
                set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
                queue_work(time_sync_wq, &etr_work);
        }
+out:
+       mutex_unlock(&clock_sync_mutex);
        return count;
 }
 
@@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm)
  */
 void stp_sync_check(void)
 {
-       if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
-               return;
        disable_sync_clock(NULL);
        queue_work(time_sync_wq, &stp_work);
 }
@@ -1485,8 +1501,6 @@ void stp_sync_check(void)
  */
 void stp_island_check(void)
 {
-       if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
-               return;
        disable_sync_clock(NULL);
        queue_work(time_sync_wq, &stp_work);
 }
@@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data)
 
        enable_sync_clock();
 
-       set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
-       if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
-               queue_work(time_sync_wq, &etr_work);
-
        rc = 0;
        if (stp_info.todoff[0] || stp_info.todoff[1] ||
            stp_info.todoff[2] || stp_info.todoff[3] ||
@@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data)
        if (rc) {
                disable_sync_clock(NULL);
                stp_sync->in_sync = -EAGAIN;
-               clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
-               if (etr_port0_online || etr_port1_online)
-                       queue_work(time_sync_wq, &etr_work);
        } else
                stp_sync->in_sync = 1;
        xchg(&first, 0);
@@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work)
        if (rc || stp_info.c == 0)
                goto out_unlock;
 
+       /* Skip synchronization if the clock is already in sync. */
+       if (check_sync_clock())
+               goto out_unlock;
+
        memset(&stp_sync, 0, sizeof(stp_sync));
        get_online_cpus();
        atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
@@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class,
                return -EINVAL;
        if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
                return -EOPNOTSUPP;
+       mutex_lock(&clock_sync_mutex);
        stp_online = value;
+       if (stp_online)
+               set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
+       else
+               clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
        queue_work(time_sync_wq, &stp_work);
+       mutex_unlock(&clock_sync_mutex);
        return count;
 }
 
index cc362c9ea8f1acc42d001d957a35e881868b4e0b..3c72c9cf22b68f8f40a6b68d0da1972b9c112bf1 100644 (file)
@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(topology_lock);
 
 cpumask_t cpu_core_map[NR_CPUS];
 
-cpumask_t cpu_coregroup_map(unsigned int cpu)
+static cpumask_t cpu_coregroup_map(unsigned int cpu)
 {
        struct core_info *core = &core_info;
        unsigned long flags;
index 4584d81984c0f25dabb4bffc17371866081ed6a5..c2e42cc65ce7cb7798618e35ededbe685001d825 100644 (file)
@@ -61,9 +61,11 @@ extern pgm_check_handler_t do_asce_exception;
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
 #ifndef CONFIG_64BIT
+#define LONG "%08lx "
 #define FOURLONG "%08lx %08lx %08lx %08lx\n"
 static int kstack_depth_to_print = 12;
 #else /* CONFIG_64BIT */
+#define LONG "%016lx "
 #define FOURLONG "%016lx %016lx %016lx %016lx\n"
 static int kstack_depth_to_print = 20;
 #endif /* CONFIG_64BIT */
@@ -155,7 +157,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
                        break;
                if (i && ((i * sizeof (long) % 32) == 0))
                        printk("\n       ");
-               printk("%p ", (void *)*stack++);
+               printk(LONG, *stack++);
        }
        printk("\n");
        show_trace(task, sp);
index 690e17819686534c9061b03e5408354bdb00f5d8..89b2e7f1b7a9ca85c207880b54f7c220ac428728 100644 (file)
@@ -144,7 +144,6 @@ out:
        return -ENOMEM;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
 {
        unsigned long segment_table, page_table, page_frame;
@@ -163,7 +162,6 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
        free_page(page_table);
        free_pages(segment_table, SEGMENT_ORDER);
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 static void __vdso_init_cr5(void *dummy)
 {
index d796d05c9c01ac1be6779682a730485d73502bd2..7a2063eb88f0ffac77a573d24d2653dc7aaf3c24 100644 (file)
@@ -108,6 +108,8 @@ SECTIONS
                EXIT_TEXT
        }
 
+       /* early.c uses stsi, which requires page aligned data. */
+       . = ALIGN(PAGE_SIZE);
        .init.data : {
                INIT_DATA
        }
index cbfe91e101208273d789585595f146a5878b0081..f4d56e9939c90949c1e886eaabf6cc7d35cab858 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/timer.h>
 #include <asm/lowcore.h>
 #include <asm/pgtable.h>
-
+#include <asm/nmi.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -286,7 +286,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
                 (unsigned long) vcpu);
        get_cpu_id(&vcpu->arch.cpu_id);
-       vcpu->arch.cpu_id.version = 0xfe;
+       vcpu->arch.cpu_id.version = 0xff;
        return 0;
 }
 
@@ -440,8 +440,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
        return -EINVAL; /* not implemented yet */
 }
 
-extern void s390_handle_mcck(void);
-
 static void __vcpu_run(struct kvm_vcpu *vcpu)
 {
        memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
index 6ccb9fab055a5b08abb129bbd8752d11f1a0dd8c..3f5f680726ed1e03bc74cc40a4217a93ab89e837 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/timex.h>
+#include <linux/module.h>
 #include <linux/irqflags.h>
 #include <linux/interrupt.h>
 
@@ -92,6 +93,7 @@ out:
        local_irq_restore(flags);
        preempt_enable();
 }
+EXPORT_SYMBOL(__udelay);
 
 /*
  * Simple udelay variant. To be used on startup and reboot
index ae5cf5d03d4165b7c98134830a8138b1b1ffe61b..4143b7c1909628fd7e8284b97acfc9392e158910 100644 (file)
@@ -44,7 +44,11 @@ static inline char *__strnend(const char *s, size_t n)
  */
 size_t strlen(const char *s)
 {
+#if __GNUC__ < 4
        return __strend(s) - s;
+#else
+       return __builtin_strlen(s);
+#endif
 }
 EXPORT_SYMBOL(strlen);
 
@@ -70,6 +74,7 @@ EXPORT_SYMBOL(strnlen);
  */
 char *strcpy(char *dest, const char *src)
 {
+#if __GNUC__ < 4
        register int r0 asm("0") = 0;
        char *ret = dest;
 
@@ -78,6 +83,9 @@ char *strcpy(char *dest, const char *src)
                      : "+&a" (dest), "+&a" (src) : "d" (r0)
                      : "cc", "memory" );
        return ret;
+#else
+       return __builtin_strcpy(dest, src);
+#endif
 }
 EXPORT_SYMBOL(strcpy);
 
index 4d537205e83c0013d159a9cd8fc5145e0dd80813..833e8366c351d08238466e21f660c66dc47e0845 100644 (file)
@@ -200,29 +200,6 @@ static void do_low_address(struct pt_regs *regs, unsigned long error_code)
        do_no_context(regs, error_code, 0);
 }
 
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code,
-                           unsigned long address)
-{
-       struct task_struct *tsk = current;
-       struct mm_struct *mm = tsk->mm;
-
-       up_read(&mm->mmap_sem);
-       if (is_global_init(tsk)) {
-               yield();
-               down_read(&mm->mmap_sem);
-               return 1;
-       }
-       printk("VM: killing process %s\n", tsk->comm);
-       if (regs->psw.mask & PSW_MASK_PSTATE)
-               do_group_exit(SIGKILL);
-       do_no_context(regs, error_code, address);
-       return 0;
-}
-
 static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
                      unsigned long address)
 {
@@ -367,7 +344,6 @@ good_area:
                        goto bad_area;
        }
 
-survive:
        if (is_vm_hugetlb_page(vma))
                address &= HPAGE_MASK;
        /*
@@ -378,8 +354,8 @@ survive:
        fault = handle_mm_fault(mm, vma, address, write);
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM) {
-                       if (do_out_of_memory(regs, error_code, address))
-                               goto survive;
+                       up_read(&mm->mmap_sem);
+                       pagefault_out_of_memory();
                        return;
                } else if (fault & VM_FAULT_SIGBUS) {
                        do_sigbus(regs, error_code, address);
index f0258ca3b17ed0905bd8a80a42f15e4355a6fd87..c634dfbe92e9ad680f245617db440be322fcad27 100644 (file)
@@ -40,7 +40,9 @@
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
+
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+EXPORT_SYMBOL(empty_zero_page);
 
 /*
  * paging_init() sets up the page tables
index 6b6ddc4ea02be082bf340c8ee662da7fe25d47a7..be6c1cf4ad5ae8922f039ab2100b2e50183553f2 100644 (file)
@@ -258,6 +258,10 @@ int s390_enable_sie(void)
        struct task_struct *tsk = current;
        struct mm_struct *mm, *old_mm;
 
+       /* Do we have switched amode? If no, we cannot do sie */
+       if (!switch_amode)
+               return -EINVAL;
+
        /* Do we have pgstes? if yes, we are done */
        if (tsk->mm->context.has_pgste)
                return 0;
@@ -292,7 +296,7 @@ int s390_enable_sie(void)
        tsk->mm = tsk->active_mm = mm;
        preempt_disable();
        update_mm(mm, tsk);
-       cpu_set(smp_processor_id(), mm->cpu_vm_mask);
+       cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
        preempt_enable();
        task_unlock(tsk);
        mmput(old_mm);
index a53496828b76949a3e0b50c82fa4372d8c6f21dd..54481a8877699d40d22d3afceded64d70365cbe0 100644 (file)
 
 #include <linux/types.h>
 #include <asm/ebcdic.h>
+#include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/mempool.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/tty.h>
 #include <linux/wait.h>
 #include <net/iucv/iucv.h>
@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1;
 /* Array of allocated hvc iucv tty lines... */
 static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
 #define IUCV_HVC_CON_IDX       (0)
+/* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
+#define MAX_VMID_FILTER                (500)
+static size_t hvc_iucv_filter_size;
+static void *hvc_iucv_filter;
+static const char *hvc_iucv_filter_string;
+static DEFINE_RWLOCK(hvc_iucv_filter_lock);
 
 /* Kmem cache and mempool for iucv_tty_buffer elements */
 static struct kmem_cache *hvc_iucv_buffer_cache;
@@ -617,6 +624,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
        }
 }
 
+/**
+ * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
+ * @ipvmid:    Originating z/VM user ID (right padded with blanks)
+ *
+ * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise
+ * non-zero.
+ */
+static int hvc_iucv_filter_connreq(u8 ipvmid[8])
+{
+       size_t i;
+
+       /* Note: default policy is ACCEPT if no filter is set */
+       if (!hvc_iucv_filter_size)
+               return 0;
+
+       for (i = 0; i < hvc_iucv_filter_size; i++)
+               if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8))
+                       return 0;
+       return 1;
+}
+
 /**
  * hvc_iucv_path_pending() - IUCV handler to process a connection request.
  * @path:      Pending path (struct iucv_path)
@@ -641,6 +669,7 @@ static      int hvc_iucv_path_pending(struct iucv_path *path,
 {
        struct hvc_iucv_private *priv;
        u8 nuser_data[16];
+       u8 vm_user_id[9];
        int i, rc;
 
        priv = NULL;
@@ -653,6 +682,20 @@ static     int hvc_iucv_path_pending(struct iucv_path *path,
        if (!priv)
                return -ENODEV;
 
+       /* Enforce that ipvmid is allowed to connect to us */
+       read_lock(&hvc_iucv_filter_lock);
+       rc = hvc_iucv_filter_connreq(ipvmid);
+       read_unlock(&hvc_iucv_filter_lock);
+       if (rc) {
+               iucv_path_sever(path, ipuser);
+               iucv_path_free(path);
+               memcpy(vm_user_id, ipvmid, 8);
+               vm_user_id[8] = 0;
+               pr_info("A connection request from z/VM user ID %s "
+                       "was refused\n", vm_user_id);
+               return 0;
+       }
+
        spin_lock(&priv->lock);
 
        /* If the terminal is already connected or being severed, then sever
@@ -876,6 +919,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
        return 0;
 }
 
+/**
+ * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
+ * @filter:    String containing a comma-separated list of z/VM user IDs
+ */
+static const char *hvc_iucv_parse_filter(const char *filter, char *dest)
+{
+       const char *nextdelim, *residual;
+       size_t len;
+
+       nextdelim = strchr(filter, ',');
+       if (nextdelim) {
+               len = nextdelim - filter;
+               residual = nextdelim + 1;
+       } else {
+               len = strlen(filter);
+               residual = filter + len;
+       }
+
+       if (len == 0)
+               return ERR_PTR(-EINVAL);
+
+       /* check for '\n' (if called from sysfs) */
+       if (filter[len - 1] == '\n')
+               len--;
+
+       if (len > 8)
+               return ERR_PTR(-EINVAL);
+
+       /* pad with blanks and save upper case version of user ID */
+       memset(dest, ' ', 8);
+       while (len--)
+               dest[len] = toupper(filter[len]);
+       return residual;
+}
+
+/**
+ * hvc_iucv_setup_filter() - Set up z/VM user ID filter
+ * @filter:    String consisting of a comma-separated list of z/VM user IDs
+ *
+ * The function parses the @filter string and creates an array containing
+ * the list of z/VM user ID filter entries.
+ * Return code 0 means success, -EINVAL if the filter is syntactically
+ * incorrect, -ENOMEM if there was not enough memory to allocate the
+ * filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
+ */
+static int hvc_iucv_setup_filter(const char *val)
+{
+       const char *residual;
+       int err;
+       size_t size, count;
+       void *array, *old_filter;
+
+       count = strlen(val);
+       if (count == 0 || (count == 1 && val[0] == '\n')) {
+               size  = 0;
+               array = NULL;
+               goto out_replace_filter;        /* clear filter */
+       }
+
+       /* count user IDs in order to allocate sufficient memory */
+       size = 1;
+       residual = val;
+       while ((residual = strchr(residual, ',')) != NULL) {
+               residual++;
+               size++;
+       }
+
+       /* check if the specified list exceeds the filter limit */
+       if (size > MAX_VMID_FILTER)
+               return -ENOSPC;
+
+       array = kzalloc(size * 8, GFP_KERNEL);
+       if (!array)
+               return -ENOMEM;
+
+       count = size;
+       residual = val;
+       while (*residual && count) {
+               residual = hvc_iucv_parse_filter(residual,
+                                                array + ((size - count) * 8));
+               if (IS_ERR(residual)) {
+                       err = PTR_ERR(residual);
+                       kfree(array);
+                       goto out_err;
+               }
+               count--;
+       }
+
+out_replace_filter:
+       write_lock_bh(&hvc_iucv_filter_lock);
+       old_filter = hvc_iucv_filter;
+       hvc_iucv_filter_size = size;
+       hvc_iucv_filter = array;
+       write_unlock_bh(&hvc_iucv_filter_lock);
+       kfree(old_filter);
+
+       err = 0;
+out_err:
+       return err;
+}
+
+/**
+ * param_set_vmidfilter() - Set z/VM user ID filter parameter
+ * @val:       String consisting of a comma-separated list of z/VM user IDs
+ * @kp:                Kernel parameter pointing to hvc_iucv_filter array
+ *
+ * The function sets up the z/VM user ID filter specified as comma-separated
+ * list of user IDs in @val.
+ * Note: If it is called early in the boot process, @val is stored and
+ *      parsed later in hvc_iucv_init().
+ */
+static int param_set_vmidfilter(const char *val, struct kernel_param *kp)
+{
+       int rc;
+
+       if (!MACHINE_IS_VM || !hvc_iucv_devices)
+               return -ENODEV;
+
+       if (!val)
+               return -EINVAL;
+
+       rc = 0;
+       if (slab_is_available())
+               rc = hvc_iucv_setup_filter(val);
+       else
+               hvc_iucv_filter_string = val;   /* defer... */
+       return rc;
+}
+
+/**
+ * param_get_vmidfilter() - Get z/VM user ID filter
+ * @buffer:    Buffer to store z/VM user ID filter,
+ *             (buffer size assumption PAGE_SIZE)
+ * @kp:                Kernel parameter pointing to the hvc_iucv_filter array
+ *
+ * The function stores the filter as a comma-separated list of z/VM user IDs
+ * in @buffer. Typically, sysfs routines call this function for attr show.
+ */
+static int param_get_vmidfilter(char *buffer, struct kernel_param *kp)
+{
+       int rc;
+       size_t index, len;
+       void *start, *end;
+
+       if (!MACHINE_IS_VM || !hvc_iucv_devices)
+               return -ENODEV;
+
+       rc = 0;
+       read_lock_bh(&hvc_iucv_filter_lock);
+       for (index = 0; index < hvc_iucv_filter_size; index++) {
+               start = hvc_iucv_filter + (8 * index);
+               end   = memchr(start, ' ', 8);
+               len   = (end) ? end - start : 8;
+               memcpy(buffer + rc, start, len);
+               rc += len;
+               buffer[rc++] = ',';
+       }
+       read_unlock_bh(&hvc_iucv_filter_lock);
+       if (rc)
+               buffer[--rc] = '\0';    /* replace last comma and update rc */
+       return rc;
+}
+
+#define param_check_vmidfilter(name, p) __param_check(name, p, void)
+
 /**
  * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
  */
@@ -884,24 +1092,53 @@ static int __init hvc_iucv_init(void)
        int rc;
        unsigned int i;
 
+       if (!hvc_iucv_devices)
+               return -ENODEV;
+
        if (!MACHINE_IS_VM) {
-               pr_info("The z/VM IUCV HVC device driver cannot "
+               pr_notice("The z/VM IUCV HVC device driver cannot "
                           "be used without z/VM\n");
-               return -ENODEV;
+               rc = -ENODEV;
+               goto out_error;
        }
 
-       if (!hvc_iucv_devices)
-               return -ENODEV;
+       if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) {
+               pr_err("%lu is not a valid value for the hvc_iucv= "
+                       "kernel parameter\n", hvc_iucv_devices);
+               rc = -EINVAL;
+               goto out_error;
+       }
 
-       if (hvc_iucv_devices > MAX_HVC_IUCV_LINES)
-               return -EINVAL;
+       /* parse hvc_iucv_allow string and create z/VM user ID filter list */
+       if (hvc_iucv_filter_string) {
+               rc = hvc_iucv_setup_filter(hvc_iucv_filter_string);
+               switch (rc) {
+               case 0:
+                       break;
+               case -ENOMEM:
+                       pr_err("Allocating memory failed with "
+                               "reason code=%d\n", 3);
+                       goto out_error;
+               case -EINVAL:
+                       pr_err("hvc_iucv_allow= does not specify a valid "
+                               "z/VM user ID list\n");
+                       goto out_error;
+               case -ENOSPC:
+                       pr_err("hvc_iucv_allow= specifies too many "
+                               "z/VM user IDs\n");
+                       goto out_error;
+               default:
+                       goto out_error;
+               }
+       }
 
        hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT,
                                           sizeof(struct iucv_tty_buffer),
                                           0, 0, NULL);
        if (!hvc_iucv_buffer_cache) {
                pr_err("Allocating memory failed with reason code=%d\n", 1);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_error;
        }
 
        hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR,
@@ -909,7 +1146,8 @@ static int __init hvc_iucv_init(void)
        if (!hvc_iucv_mempool) {
                pr_err("Allocating memory failed with reason code=%d\n", 2);
                kmem_cache_destroy(hvc_iucv_buffer_cache);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out_error;
        }
 
        /* register the first terminal device as console
@@ -953,6 +1191,8 @@ out_error_hvc:
 out_error_memory:
        mempool_destroy(hvc_iucv_mempool);
        kmem_cache_destroy(hvc_iucv_buffer_cache);
+out_error:
+       hvc_iucv_devices = 0; /* ensure that we do not provide any device */
        return rc;
 }
 
@@ -968,3 +1208,4 @@ static     int __init hvc_iucv_config(char *val)
 
 device_initcall(hvc_iucv_init);
 __setup("hvc_iucv=", hvc_iucv_config);
+core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640);
index d0eae59bc3667ce8d2ee56d484777d7cb5d32ccd..95bccfd3f169a8a3a167368f972cbbd08de7c869 100644 (file)
@@ -2,9 +2,6 @@
 # Makefile for the S/390 specific device drivers
 #
 
-CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
-
-obj-y += s390mach.o sysinfo.o
 obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
 
 drivers-y += drivers/s390/built-in.o
index 08c23a921012d4a771b2171b712fdd1b8f653c0f..2fd64e5a9ab267ae38d6b79454125a41d929ec74 100644 (file)
@@ -9,6 +9,9 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -22,6 +25,7 @@
 #include <asm/ebcdic.h>
 #include <asm/idals.h>
 #include <asm/todclk.h>
+#include <asm/itcw.h>
 
 /* This is ugly... */
 #define PRINTK_HEADER "dasd:"
@@ -221,7 +225,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device)
                        return rc;
        }
        /* register 'device' debug area, used for all DBF_DEV_XXX calls */
-       device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1,
+       device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1,
                                            8 * sizeof(long));
        debug_register_view(device->debug_area, &debug_sprintf_view);
        debug_set_level(device->debug_area, DBF_WARNING);
@@ -762,7 +766,7 @@ static inline int dasd_check_cqr(struct dasd_ccw_req *cqr)
                return -EINVAL;
        device = cqr->startdev;
        if (strncmp((char *) &cqr->magic, device->discipline->ebcname, 4)) {
-               DEV_MESSAGE(KERN_WARNING, device,
+               DBF_DEV_EVENT(DBF_WARNING, device,
                            " dasd_ccw_req 0x%08x magic doesn't match"
                            " discipline 0x%08x",
                            cqr->magic,
@@ -782,6 +786,7 @@ int dasd_term_IO(struct dasd_ccw_req *cqr)
 {
        struct dasd_device *device;
        int retries, rc;
+       char errorstring[ERRORLENGTH];
 
        /* Check the cqr */
        rc = dasd_check_cqr(cqr);
@@ -815,10 +820,10 @@ int dasd_term_IO(struct dasd_ccw_req *cqr)
                                      "device busy, retry later");
                        break;
                default:
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "line %d unknown RC=%d, please "
-                                   "report to linux390@de.ibm.com",
-                                   __LINE__, rc);
+                       /* internal error 10 - unknown rc*/
+                       snprintf(errorstring, ERRORLENGTH, "10 %d", rc);
+                       dev_err(&device->cdev->dev, "An error occurred in the "
+                               "DASD device driver, reason=%s\n", errorstring);
                        BUG();
                        break;
                }
@@ -836,6 +841,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
 {
        struct dasd_device *device;
        int rc;
+       char errorstring[ERRORLENGTH];
 
        /* Check the cqr */
        rc = dasd_check_cqr(cqr);
@@ -843,17 +849,23 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
                return rc;
        device = (struct dasd_device *) cqr->startdev;
        if (cqr->retries < 0) {
-               DEV_MESSAGE(KERN_DEBUG, device,
-                           "start_IO: request %p (%02x/%i) - no retry left.",
-                           cqr, cqr->status, cqr->retries);
+               /* internal error 14 - start_IO run out of retries */
+               sprintf(errorstring, "14 %p", cqr);
+               dev_err(&device->cdev->dev, "An error occurred in the DASD "
+                       "device driver, reason=%s\n", errorstring);
                cqr->status = DASD_CQR_ERROR;
                return -EIO;
        }
        cqr->startclk = get_clock();
        cqr->starttime = jiffies;
        cqr->retries--;
-       rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr,
-                             cqr->lpm, 0);
+       if (cqr->cpmode == 1) {
+               rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
+                                        (long) cqr, cqr->lpm);
+       } else {
+               rc = ccw_device_start(device->cdev, cqr->cpaddr,
+                                     (long) cqr, cqr->lpm, 0);
+       }
        switch (rc) {
        case 0:
                cqr->status = DASD_CQR_IN_IO;
@@ -862,11 +874,11 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
                              cqr);
                break;
        case -EBUSY:
-               DBF_DEV_EVENT(DBF_ERR, device, "%s",
+               DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
                              "start_IO: device busy, retry later");
                break;
        case -ETIMEDOUT:
-               DBF_DEV_EVENT(DBF_ERR, device, "%s",
+               DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
                              "start_IO: request timeout, retry later");
                break;
        case -EACCES:
@@ -876,19 +888,24 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
                 * Do a retry with all available pathes.
                 */
                cqr->lpm = LPM_ANYPATH;
-               DBF_DEV_EVENT(DBF_ERR, device, "%s",
+               DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
                              "start_IO: selected pathes gone,"
                              " retry on all pathes");
                break;
        case -ENODEV:
+               DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+                             "start_IO: -ENODEV device gone, retry");
+               break;
        case -EIO:
-               DBF_DEV_EVENT(DBF_ERR, device, "%s",
-                             "start_IO: device gone, retry");
+               DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
+                             "start_IO: -EIO device gone, retry");
                break;
        default:
-               DEV_MESSAGE(KERN_ERR, device,
-                           "line %d unknown RC=%d, please report"
-                           " to linux390@de.ibm.com", __LINE__, rc);
+               /* internal error 11 - unknown rc */
+               snprintf(errorstring, ERRORLENGTH, "11 %d", rc);
+               dev_err(&device->cdev->dev,
+                       "An error occurred in the DASD device driver, "
+                       "reason=%s\n", errorstring);
                BUG();
                break;
        }
@@ -945,7 +962,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
                return;
        cqr = (struct dasd_ccw_req *) intparm;
        if (cqr->status != DASD_CQR_IN_IO) {
-               MESSAGE(KERN_DEBUG,
+               DBF_EVENT(DBF_DEBUG,
                        "invalid status in handle_killed_request: "
                        "bus_id %s, status %02x",
                        dev_name(&cdev->dev), cqr->status);
@@ -956,8 +973,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
        if (device == NULL ||
            device != dasd_device_from_cdev_locked(cdev) ||
            strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
-               MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
-                       dev_name(&cdev->dev));
+               DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: "
+                             "bus_id %s", dev_name(&cdev->dev));
                return;
        }
 
@@ -996,11 +1013,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                case -EIO:
                        break;
                case -ETIMEDOUT:
-                       printk(KERN_WARNING"%s(%s): request timed out\n",
+                       DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n",
                               __func__, dev_name(&cdev->dev));
                        break;
                default:
-                       printk(KERN_WARNING"%s(%s): unknown error %ld\n",
+                       DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n",
                               __func__, dev_name(&cdev->dev), PTR_ERR(irb));
                }
                dasd_handle_killed_request(cdev, intparm);
@@ -1009,15 +1026,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
 
        now = get_clock();
 
-       DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
-                 dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) |
-                 irb->scsw.cmd.dstat), (unsigned int) intparm);
-
        /* check for unsolicited interrupts */
        cqr = (struct dasd_ccw_req *) intparm;
-       if (!cqr || ((irb->scsw.cmd.cc == 1) &&
-                    (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
-                    (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND))) {
+       if (!cqr || ((scsw_cc(&irb->scsw) == 1) &&
+                    (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
+                    (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) {
                if (cqr && cqr->status == DASD_CQR_IN_IO)
                        cqr->status = DASD_CQR_QUEUED;
                device = dasd_device_from_cdev_locked(cdev);
@@ -1033,14 +1046,14 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
        device = (struct dasd_device *) cqr->startdev;
        if (!device ||
            strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
-               MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s",
-                       dev_name(&cdev->dev));
+               DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: "
+                             "bus_id %s", dev_name(&cdev->dev));
                return;
        }
 
        /* Check for clear pending */
        if (cqr->status == DASD_CQR_CLEAR_PENDING &&
-           irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) {
+           scsw_fctl(&irb->scsw) & SCSW_FCTL_CLEAR_FUNC) {
                cqr->status = DASD_CQR_CLEARED;
                dasd_device_clear_timer(device);
                wake_up(&dasd_flush_wq);
@@ -1048,19 +1061,17 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                return;
        }
 
-       /* check status - the request might have been killed by dyn detach */
+       /* check status - the request might have been killed by dyn detach */
        if (cqr->status != DASD_CQR_IN_IO) {
-               MESSAGE(KERN_DEBUG,
-                       "invalid status: bus_id %s, status %02x",
-                       dev_name(&cdev->dev), cqr->status);
+               DBF_DEV_EVENT(DBF_DEBUG, device, "invalid status: bus_id %s, "
+                             "status %02x", dev_name(&cdev->dev), cqr->status);
                return;
        }
-       DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
-                     ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), cqr);
+
        next = NULL;
        expires = 0;
-       if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
-           irb->scsw.cmd.cstat == 0 && !irb->esw.esw0.erw.cons) {
+       if (scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
+           scsw_cstat(&irb->scsw) == 0) {
                /* request was completed successfully */
                cqr->status = DASD_CQR_SUCCESS;
                cqr->stopclk = now;
@@ -1071,18 +1082,23 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                }
        } else {  /* error */
                memcpy(&cqr->irb, irb, sizeof(struct irb));
+               /* log sense for every failed I/O to s390 debugfeature */
+               dasd_log_sense_dbf(cqr, irb);
                if (device->features & DASD_FEATURE_ERPLOG) {
                        dasd_log_sense(cqr, irb);
                }
+
                /*
                 * If we don't want complex ERP for this request, then just
                 * reset this and retry it in the fastpath
                 */
                if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) &&
                    cqr->retries > 0) {
-                       DEV_MESSAGE(KERN_DEBUG, device,
-                                   "default ERP in fastpath (%i retries left)",
-                                   cqr->retries);
+                       if (cqr->lpm == LPM_ANYPATH)
+                               DBF_DEV_EVENT(DBF_DEBUG, device,
+                                             "default ERP in fastpath "
+                                             "(%i retries left)",
+                                             cqr->retries);
                        cqr->lpm    = LPM_ANYPATH;
                        cqr->status = DASD_CQR_QUEUED;
                        next = cqr;
@@ -1093,10 +1109,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
            (!device->stopped)) {
                if (device->discipline->start_IO(next) == 0)
                        expires = next->expires;
-               else
-                       DEV_MESSAGE(KERN_DEBUG, device, "%s",
-                                   "Interrupt fastpath "
-                                   "failed!");
        }
        if (expires != 0)
                dasd_device_set_timer(device, expires);
@@ -1169,6 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
        struct dasd_block *block;
        void (*callback)(struct dasd_ccw_req *, void *data);
        void *callback_data;
+       char errorstring[ERRORLENGTH];
 
        list_for_each_safe(l, n, final_queue) {
                cqr = list_entry(l, struct dasd_ccw_req, devlist);
@@ -1189,10 +1202,11 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
                        cqr->status = DASD_CQR_TERMINATED;
                        break;
                default:
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "wrong cqr status in __dasd_process_final_queue "
-                                   "for cqr %p, status %x",
-                                   cqr, cqr->status);
+                       /* internal error 12 - wrong cqr status*/
+                       snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status);
+                       dev_err(&device->cdev->dev,
+                               "An error occurred in the DASD device driver, "
+                               "reason=%s\n", errorstring);
                        BUG();
                }
                if (cqr->callback != NULL)
@@ -1217,18 +1231,17 @@ static void __dasd_device_check_expire(struct dasd_device *device)
            (time_after_eq(jiffies, cqr->expires + cqr->starttime))) {
                if (device->discipline->term_IO(cqr) != 0) {
                        /* Hmpf, try again in 5 sec */
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "internal error - timeout (%is) expired "
-                                   "for cqr %p, termination failed, "
-                                   "retrying in 5s",
-                                   (cqr->expires/HZ), cqr);
+                       dev_err(&device->cdev->dev,
+                               "cqr %p timed out (%is) but cannot be "
+                               "ended, retrying in 5 s\n",
+                               cqr, (cqr->expires/HZ));
                        cqr->expires += 5*HZ;
                        dasd_device_set_timer(device, 5*HZ);
                } else {
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "internal error - timeout (%is) expired "
-                                   "for cqr %p (%i retries left)",
-                                   (cqr->expires/HZ), cqr, cqr->retries);
+                       dev_err(&device->cdev->dev,
+                               "cqr %p timed out (%is), %i retries "
+                               "remaining\n", cqr, (cqr->expires/HZ),
+                               cqr->retries);
                }
        }
 }
@@ -1290,10 +1303,9 @@ int dasd_flush_device_queue(struct dasd_device *device)
                        rc = device->discipline->term_IO(cqr);
                        if (rc) {
                                /* unable to terminate requeust */
-                               DEV_MESSAGE(KERN_ERR, device,
-                                           "dasd flush ccw_queue is unable "
-                                           " to terminate request %p",
-                                           cqr);
+                               dev_err(&device->cdev->dev,
+                                       "Flushing the DASD request queue "
+                                       "failed for request %p\n", cqr);
                                /* stop flush processing */
                                goto finished;
                        }
@@ -1537,10 +1549,9 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr)
                /* request in IO - terminate IO and release again */
                rc = device->discipline->term_IO(cqr);
                if (rc) {
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "dasd_cancel_req is unable "
-                                   " to terminate request %p, rc = %d",
-                                   cqr, rc);
+                       dev_err(&device->cdev->dev,
+                               "Cancelling request %p failed with rc=%d\n",
+                               cqr, rc);
                } else {
                        cqr->stopclk = get_clock();
                        rc = 1;
@@ -1617,7 +1628,7 @@ static inline void __dasd_block_process_erp(struct dasd_block *block,
        if (cqr->status == DASD_CQR_DONE)
                DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful");
        else
-               DEV_MESSAGE(KERN_ERR, device, "%s", "ERP unsuccessful");
+               dev_err(&device->cdev->dev, "ERP failed for the DASD\n");
        erp_fn = device->discipline->erp_postaction(cqr);
        erp_fn(cqr);
 }
@@ -1991,8 +2002,11 @@ static void dasd_setup_queue(struct dasd_block *block)
        blk_queue_max_sectors(block->request_queue, max);
        blk_queue_max_phys_segments(block->request_queue, -1L);
        blk_queue_max_hw_segments(block->request_queue, -1L);
-       blk_queue_max_segment_size(block->request_queue, -1L);
-       blk_queue_segment_boundary(block->request_queue, -1L);
+       /* with page sized segments we can translate each segement into
+        * one idaw/tidaw
+        */
+       blk_queue_max_segment_size(block->request_queue, PAGE_SIZE);
+       blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1);
        blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN, NULL);
 }
 
@@ -2043,8 +2057,9 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
        }
 
        if (dasd_probeonly) {
-               DEV_MESSAGE(KERN_INFO, base, "%s",
-                           "No access to device due to probeonly mode");
+               dev_info(&base->cdev->dev,
+                        "Accessing the DASD failed because it is in "
+                        "probeonly mode\n");
                rc = -EPERM;
                goto out;
        }
@@ -2101,7 +2116,8 @@ dasd_device_operations = {
        .owner          = THIS_MODULE,
        .open           = dasd_open,
        .release        = dasd_release,
-       .locked_ioctl   = dasd_ioctl,
+       .ioctl          = dasd_ioctl,
+       .compat_ioctl   = dasd_ioctl,
        .getgeo         = dasd_getgeo,
 };
 
@@ -2143,14 +2159,14 @@ int dasd_generic_probe(struct ccw_device *cdev,
 
        ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
        if (ret) {
-               printk(KERN_WARNING
+               DBF_EVENT(DBF_WARNING,
                       "dasd_generic_probe: could not set ccw-device options "
                       "for %s\n", dev_name(&cdev->dev));
                return ret;
        }
        ret = dasd_add_sysfs_files(cdev);
        if (ret) {
-               printk(KERN_WARNING
+               DBF_EVENT(DBF_WARNING,
                       "dasd_generic_probe: could not add sysfs entries "
                       "for %s\n", dev_name(&cdev->dev));
                return ret;
@@ -2166,9 +2182,7 @@ int dasd_generic_probe(struct ccw_device *cdev,
            (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0))
                ret = ccw_device_set_online(cdev);
        if (ret)
-               printk(KERN_WARNING
-                      "dasd_generic_probe: could not initially "
-                      "online ccw-device %s; return code: %d\n",
+               pr_warning("%s: Setting the DASD online failed with rc=%d\n",
                       dev_name(&cdev->dev), ret);
        return 0;
 }
@@ -2232,10 +2246,9 @@ int dasd_generic_set_online(struct ccw_device *cdev,
        discipline = base_discipline;
        if (device->features & DASD_FEATURE_USEDIAG) {
                if (!dasd_diag_discipline_pointer) {
-                       printk (KERN_WARNING
-                               "dasd_generic couldn't online device %s "
-                               "- discipline DIAG not available\n",
-                               dev_name(&cdev->dev));
+                       pr_warning("%s Setting the DASD online failed because "
+                                  "of missing DIAG discipline\n",
+                                  dev_name(&cdev->dev));
                        dasd_delete_device(device);
                        return -ENODEV;
                }
@@ -2256,10 +2269,9 @@ int dasd_generic_set_online(struct ccw_device *cdev,
        /* check_device will allocate block device if necessary */
        rc = discipline->check_device(device);
        if (rc) {
-               printk (KERN_WARNING
-                       "dasd_generic couldn't online device %s "
-                       "with discipline %s rc=%i\n",
-                       dev_name(&cdev->dev), discipline->name, rc);
+               pr_warning("%s Setting the DASD online with discipline %s "
+                          "failed with rc=%i\n",
+                          dev_name(&cdev->dev), discipline->name, rc);
                module_put(discipline->owner);
                module_put(base_discipline->owner);
                dasd_delete_device(device);
@@ -2268,9 +2280,8 @@ int dasd_generic_set_online(struct ccw_device *cdev,
 
        dasd_set_target_state(device, DASD_STATE_ONLINE);
        if (device->state <= DASD_STATE_KNOWN) {
-               printk (KERN_WARNING
-                       "dasd_generic discipline not found for %s\n",
-                       dev_name(&cdev->dev));
+               pr_warning("%s Setting the DASD online failed because of a "
+                          "missing discipline\n", dev_name(&cdev->dev));
                rc = -ENODEV;
                dasd_set_target_state(device, DASD_STATE_NEW);
                if (device->block)
@@ -2314,13 +2325,13 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
                open_count = atomic_read(&device->block->open_count);
                if (open_count > max_count) {
                        if (open_count > 0)
-                               printk(KERN_WARNING "Can't offline dasd "
-                                      "device with open count = %i.\n",
-                                      open_count);
+                               pr_warning("%s: The DASD cannot be set offline "
+                                          "with open count %i\n",
+                                          dev_name(&cdev->dev), open_count);
                        else
-                               printk(KERN_WARNING "%s",
-                                      "Can't offline dasd device due "
-                                      "to internal use\n");
+                               pr_warning("%s: The DASD cannot be set offline "
+                                          "while it is in use\n",
+                                          dev_name(&cdev->dev));
                        clear_bit(DASD_FLAG_OFFLINE, &device->flags);
                        dasd_put_device(device);
                        return -EBUSY;
@@ -2393,8 +2404,10 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
        cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
 
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                           "Could not allocate RDC request");
+               /* internal error 13 - Allocating the RDC request failed*/
+               dev_err(&device->cdev->dev,
+                        "An error occurred in the DASD device driver, "
+                        "reason=%s\n", "13");
                return cqr;
        }
 
@@ -2431,6 +2444,40 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
 }
 EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars);
 
+/*
+ *   In command mode and transport mode we need to look for sense
+ *   data in different places. The sense data itself is allways
+ *   an array of 32 bytes, so we can unify the sense data access
+ *   for both modes.
+ */
+char *dasd_get_sense(struct irb *irb)
+{
+       struct tsb *tsb = NULL;
+       char *sense = NULL;
+
+       if (scsw_is_tm(&irb->scsw) && (irb->scsw.tm.fcxs == 0x01)) {
+               if (irb->scsw.tm.tcw)
+                       tsb = tcw_get_tsb((struct tcw *)(unsigned long)
+                                         irb->scsw.tm.tcw);
+               if (tsb && tsb->length == 64 && tsb->flags)
+                       switch (tsb->flags & 0x07) {
+                       case 1: /* tsa_iostat */
+                               sense = tsb->tsa.iostat.sense;
+                               break;
+                       case 2: /* tsa_ddpc */
+                               sense = tsb->tsa.ddpc.sense;
+                               break;
+                       default:
+                               /* currently we don't use interrogate data */
+                               break;
+                       }
+       } else if (irb->esw.esw0.erw.cons) {
+               sense = irb->ecw;
+       }
+       return sense;
+}
+EXPORT_SYMBOL_GPL(dasd_get_sense);
+
 static int __init dasd_init(void)
 {
        int rc;
@@ -2472,7 +2519,7 @@ static int __init dasd_init(void)
 
        return 0;
 failed:
-       MESSAGE(KERN_INFO, "%s", "initialization not performed due to errors");
+       pr_info("The DASD device driver could not be initialized\n");
        dasd_exit();
        return rc;
 }
index d82aad5224f0c6854fdf96999fb19185b9801c5e..27991b69205625cb9c8d11e12321647b8ee272b4 100644 (file)
@@ -7,6 +7,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <asm/idals.h>
@@ -75,7 +77,7 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires)
        struct dasd_device *device = erp->startdev;
        unsigned long flags;
 
-       DEV_MESSAGE(KERN_INFO, device,
+       DBF_DEV_EVENT(DBF_INFO, device,
                    "blocking request queue for %is", expires/HZ);
 
        spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
@@ -114,9 +116,9 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp)
        } else {
 
                /* issue a message and wait for 'device ready' interrupt */
-               DEV_MESSAGE(KERN_ERR, device, "%s",
+               dev_err(&device->cdev->dev,
                            "is offline or not installed - "
-                           "INTERVENTION REQUIRED!!");
+                           "INTERVENTION REQUIRED!!\n");
 
                dasd_3990_erp_block_queue(erp, 60*HZ);
        }
@@ -158,7 +160,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
 
        if ((erp->lpm & opm) != 0x00) {
 
-               DEV_MESSAGE(KERN_DEBUG, device,
+               DBF_DEV_EVENT(DBF_WARNING, device,
                            "try alternate lpm=%x (lpum=%x / opm=%x)",
                            erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);
 
@@ -166,10 +168,9 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
                erp->status = DASD_CQR_FILLED;
                erp->retries = 10;
        } else {
-               DEV_MESSAGE(KERN_ERR, device,
-                           "No alternate channel path left (lpum=%x / "
-                           "opm=%x) -> permanent error",
-                           erp->irb.esw.esw0.sublog.lpum, opm);
+               dev_err(&device->cdev->dev,
+                       "The DASD cannot be reached on any path (lpum=%x"
+                       "/opm=%x)\n", erp->irb.esw.esw0.sublog.lpum, opm);
 
                /* post request with permanent error */
                erp->status = DASD_CQR_FAILED;
@@ -204,8 +205,8 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
                                          sizeof(struct DCTL_data),
                                          device);
        if (IS_ERR(dctl_cqr)) {
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "Unable to allocate DCTL-CQR");
+               dev_err(&device->cdev->dev,
+                           "Unable to allocate DCTL-CQR\n");
                erp->status = DASD_CQR_FAILED;
                return erp;
        }
@@ -294,7 +295,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
        /* interrupt (this enables easier enqueing of the cqr)      */
        if (erp->function != dasd_3990_erp_action_4) {
 
-               DEV_MESSAGE(KERN_INFO, device, "%s",
+               DBF_DEV_EVENT(DBF_INFO, device, "%s",
                            "dasd_3990_erp_action_4: first time retry");
 
                erp->retries = 256;
@@ -303,7 +304,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
        } else {
                if (sense && (sense[25] == 0x1D)) { /* state change pending */
 
-                       DEV_MESSAGE(KERN_INFO, device,
+                       DBF_DEV_EVENT(DBF_INFO, device,
                                    "waiting for state change pending "
                                    "interrupt, %d retries left",
                                    erp->retries);
@@ -311,15 +312,14 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
                        dasd_3990_erp_block_queue(erp, 30*HZ);
 
                } else if (sense && (sense[25] == 0x1E)) {      /* busy */
-                       DEV_MESSAGE(KERN_INFO, device,
+                       DBF_DEV_EVENT(DBF_INFO, device,
                                    "busy - redriving request later, "
                                    "%d retries left",
                                    erp->retries);
                         dasd_3990_erp_block_queue(erp, HZ);
                } else {
-
                        /* no state change pending - retry */
-                       DEV_MESSAGE (KERN_INFO, device,
+                       DBF_DEV_EVENT(DBF_INFO, device,
                                     "redriving request immediately, "
                                     "%d retries left",
                                     erp->retries);
@@ -384,6 +384,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
        struct dasd_device *device = erp->startdev;
        char msg_format = (sense[7] & 0xF0);
        char msg_no = (sense[7] & 0x0F);
+       char errorstring[ERRORLENGTH];
 
        switch (msg_format) {
        case 0x00:              /* Format 0 - Program or System Checks */
@@ -394,95 +395,97 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                        case 0x00:      /* No Message */
                                break;
                        case 0x01:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Invalid Command");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Invalid Command\n");
                                break;
                        case 0x02:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Invalid Command "
-                                           "Sequence");
+                                           "Sequence\n");
                                break;
                        case 0x03:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - CCW Count less than "
-                                           "required");
+                                           "required\n");
                                break;
                        case 0x04:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Invalid Parameter");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Invalid Parameter\n");
                                break;
                        case 0x05:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Diagnostic of Sepecial"
-                                           " Command Violates File Mask");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Diagnostic of Special"
+                                           " Command Violates File Mask\n");
                                break;
                        case 0x07:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Channel Returned with "
-                                           "Incorrect retry CCW");
+                                           "Incorrect retry CCW\n");
                                break;
                        case 0x08:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Reset Notification");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Reset Notification\n");
                                break;
                        case 0x09:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Storage Path Restart");
+                               dev_warn(&device->cdev->dev,
+                                        "FORMAT 0 - Storage Path Restart\n");
                                break;
                        case 0x0A:
-                               DEV_MESSAGE(KERN_WARNING, device,
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Channel requested "
-                                           "... %02x", sense[8]);
+                                           "... %02x\n", sense[8]);
                                break;
                        case 0x0B:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Invalid Defective/"
-                                           "Alternate Track Pointer");
+                                           "Alternate Track Pointer\n");
                                break;
                        case 0x0C:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - DPS Installation "
-                                           "Check");
+                                           "Check\n");
                                break;
                        case 0x0E:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Command Invalid on "
-                                           "Secondary Address");
+                                           "Secondary Address\n");
                                break;
                        case 0x0F:
-                               DEV_MESSAGE(KERN_WARNING, device,
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Status Not As "
-                                           "Required: reason %02x", sense[8]);
+                                           "Required: reason %02x\n",
+                                        sense[8]);
                                break;
                        default:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Reseved");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Reserved\n");
                        }
                } else {
                        switch (msg_no) {
                        case 0x00:      /* No Message */
                                break;
                        case 0x01:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Device Error Source");
+                               dev_warn(&device->cdev->dev,
+                                        "FORMAT 0 - Device Error "
+                                        "Source\n");
                                break;
                        case 0x02:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Reserved");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Reserved\n");
                                break;
                        case 0x03:
-                               DEV_MESSAGE(KERN_WARNING, device,
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Device Fenced - "
-                                           "device = %02x", sense[4]);
+                                           "device = %02x\n", sense[4]);
                                break;
                        case 0x04:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               dev_warn(&device->cdev->dev,
                                            "FORMAT 0 - Data Pinned for "
-                                           "Device");
+                                           "Device\n");
                                break;
                        default:
-                               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                           "FORMAT 0 - Reserved");
+                               dev_warn(&device->cdev->dev,
+                                           "FORMAT 0 - Reserved\n");
                        }
                }
                break;
@@ -492,348 +495,352 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                case 0x00:      /* No Message */
                        break;
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Device Status 1 not as "
-                                   "expected");
+                                   "expected\n");
                        break;
                case 0x03:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Index missing");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Index missing\n");
                        break;
                case 0x04:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Interruption cannot be reset");
+                       dev_warn(&device->cdev->dev,
+                                "FORMAT 1 - Interruption cannot be "
+                                "reset\n");
                        break;
                case 0x05:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Device did not respond to "
-                                   "selection");
+                                   "selection\n");
                        break;
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Device check-2 error or Set "
-                                   "Sector is not complete");
+                                   "Sector is not complete\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Head address does not "
-                                   "compare");
+                                   "compare\n");
                        break;
                case 0x08:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Device status 1 not valid");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Device status 1 not valid\n");
                        break;
                case 0x09:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Device not ready");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Device not ready\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Track physical address did "
-                                   "not compare");
+                                   "not compare\n");
                        break;
                case 0x0B:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Missing device address bit");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Missing device address bit\n");
                        break;
                case 0x0C:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Drive motor switch is off");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Drive motor switch is off\n");
                        break;
                case 0x0D:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Seek incomplete");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Seek incomplete\n");
                        break;
                case 0x0E:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Cylinder address did not "
-                                   "compare");
+                                   "compare\n");
                        break;
                case 0x0F:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 1 - Offset active cannot be "
-                                   "reset");
+                                   "reset\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 1 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 1 - Reserved\n");
                }
                break;
 
        case 0x20:              /* Format 2 - 3990 Equipment Checks */
                switch (msg_no) {
                case 0x08:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 2 - 3990 check-2 error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 2 - 3990 check-2 error\n");
                        break;
                case 0x0E:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 2 - Support facility errors");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 2 - Support facility errors\n");
                        break;
                case 0x0F:
-                       DEV_MESSAGE(KERN_WARNING, device,
-                                   "FORMAT 2 - Microcode detected error %02x",
-                                   sense[8]);
+                       dev_warn(&device->cdev->dev,
+                                "FORMAT 2 - Microcode detected error "
+                                "%02x\n",
+                                sense[8]);
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 2 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 2 - Reserved\n");
                }
                break;
 
        case 0x30:              /* Format 3 - 3990 Control Checks */
                switch (msg_no) {
                case 0x0F:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 3 - Allegiance terminated");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 3 - Allegiance terminated\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 3 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 3 - Reserved\n");
                }
                break;
 
        case 0x40:              /* Format 4 - Data Checks */
                switch (msg_no) {
                case 0x00:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - Home address area error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - Home address area error\n");
                        break;
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - Count area error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - Count area error\n");
                        break;
                case 0x02:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - Key area error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - Key area error\n");
                        break;
                case 0x03:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - Data area error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - Data area error\n");
                        break;
                case 0x04:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - No sync byte in home address "
-                                   "area");
+                                   "area\n");
                        break;
                case 0x05:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - No sync byte in count address "
-                                   "area");
+                                   "area\n");
                        break;
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - No sync byte in key area");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - No sync byte in key area\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - No sync byte in data area");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - No sync byte in data area\n");
                        break;
                case 0x08:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - Home address area error; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                case 0x09:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - Count area error; offset "
-                                   "active");
+                                   "active\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - Key area error; offset "
-                                   "active");
+                                   "active\n");
                        break;
                case 0x0B:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - Data area error; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                case 0x0C:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - No sync byte in home "
-                                   "address area; offset active");
+                                   "address area; offset active\n");
                        break;
                case 0x0D:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - No syn byte in count "
-                                   "address area; offset active");
+                                   "address area; offset active\n");
                        break;
                case 0x0E:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - No sync byte in key area; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                case 0x0F:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 4 - No syn byte in data area; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 4 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 4 - Reserved\n");
                }
                break;
 
        case 0x50:  /* Format 5 - Data Check with displacement information */
                switch (msg_no) {
                case 0x00:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 5 - Data Check in the "
-                                   "home address area");
+                                   "home address area\n");
                        break;
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 5 - Data Check in the count area");
+                       dev_warn(&device->cdev->dev,
+                                "FORMAT 5 - Data Check in the count "
+                                "area\n");
                        break;
                case 0x02:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 5 - Data Check in the key area");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 5 - Data Check in the key area\n");
                        break;
                case 0x03:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 5 - Data Check in the data area");
+                       dev_warn(&device->cdev->dev,
+                                "FORMAT 5 - Data Check in the data "
+                                "area\n");
                        break;
                case 0x08:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 5 - Data Check in the "
-                                   "home address area; offset active");
+                                   "home address area; offset active\n");
                        break;
                case 0x09:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 5 - Data Check in the count area; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 5 - Data Check in the key area; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                case 0x0B:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 5 - Data Check in the data area; "
-                                   "offset active");
+                                   "offset active\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 5 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 5 - Reserved\n");
                }
                break;
 
        case 0x60:  /* Format 6 - Usage Statistics/Overrun Errors */
                switch (msg_no) {
                case 0x00:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel A");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel A\n");
                        break;
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel B");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel B\n");
                        break;
                case 0x02:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel C");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel C\n");
                        break;
                case 0x03:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel D");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel D\n");
                        break;
                case 0x04:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel E");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel E\n");
                        break;
                case 0x05:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel F");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel F\n");
                        break;
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel G");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel G\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Overrun on channel H");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Overrun on channel H\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 6 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 6 - Reserved\n");
                }
                break;
 
        case 0x70:  /* Format 7 - Device Connection Control Checks */
                switch (msg_no) {
                case 0x00:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - RCC initiated by a connection "
-                                   "check alert");
+                                   "check alert\n");
                        break;
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - RCC 1 sequence not "
-                                   "successful");
+                                   "successful\n");
                        break;
                case 0x02:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - RCC 1 and RCC 2 sequences not "
-                                   "successful");
+                                   "successful\n");
                        break;
                case 0x03:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Invalid tag-in during "
-                                   "selection sequence");
+                                   "selection sequence\n");
                        break;
                case 0x04:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 7 - extra RCC required");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 7 - extra RCC required\n");
                        break;
                case 0x05:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Invalid DCC selection "
-                                   "response or timeout");
+                                   "response or timeout\n");
                        break;
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Missing end operation; device "
-                                   "transfer complete");
+                                   "transfer complete\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Missing end operation; device "
-                                   "transfer incomplete");
+                                   "transfer incomplete\n");
                        break;
                case 0x08:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Invalid tag-in for an "
-                                   "immediate command sequence");
+                                   "immediate command sequence\n");
                        break;
                case 0x09:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Invalid tag-in for an "
-                                   "extended command sequence");
+                                   "extended command sequence\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - 3990 microcode time out when "
-                                   "stopping selection");
+                                   "stopping selection\n");
                        break;
                case 0x0B:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - No response to selection "
-                                   "after a poll interruption");
+                                   "after a poll interruption\n");
                        break;
                case 0x0C:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - Permanent path error (DASD "
-                                   "controller not available)");
+                                   "controller not available)\n");
                        break;
                case 0x0D:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 7 - DASD controller not available"
-                                   " on disconnected command chain");
+                                   " on disconnected command chain\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 7 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 7 - Reserved\n");
                }
                break;
 
@@ -841,52 +848,52 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                switch (msg_no) {
                case 0x00:      /* No Message */
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - Error correction code "
-                                   "hardware fault");
+                                   "hardware fault\n");
                        break;
                case 0x03:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - Unexpected end operation "
-                                   "response code");
+                                   "response code\n");
                        break;
                case 0x04:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - End operation with transfer "
-                                   "count not zero");
+                                   "count not zero\n");
                        break;
                case 0x05:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - End operation with transfer "
-                                   "count zero");
+                                   "count zero\n");
                        break;
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - DPS checks after a system "
-                                   "reset or selective reset");
+                                   "reset or selective reset\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 8 - DPS cannot be filled");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 8 - DPS cannot be filled\n");
                        break;
                case 0x08:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - Short busy time-out during "
-                                   "device selection");
+                                   "device selection\n");
                        break;
                case 0x09:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - DASD controller failed to "
-                                   "set or reset the long busy latch");
+                                   "set or reset the long busy latch\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 8 - No interruption from device "
-                                   "during a command chain");
+                                   "during a command chain\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 8 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 8 - Reserved\n");
                }
                break;
 
@@ -895,97 +902,100 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
                case 0x00:
                        break;  /* No Message */
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 9 - Device check-2 error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 9 - Device check-2 error\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 9 - Head address did not compare");
+                       dev_warn(&device->cdev->dev,
+                                "FORMAT 9 - Head address did not "
+                                "compare\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 9 - Track physical address did "
-                                   "not compare while oriented");
+                                   "not compare while oriented\n");
                        break;
                case 0x0E:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT 9 - Cylinder address did not "
-                                   "compare");
+                                   "compare\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT 9 - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT 9 - Reserved\n");
                }
                break;
 
        case 0xF0:              /* Format F - Cache Storage Checks */
                switch (msg_no) {
                case 0x00:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Operation Terminated");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Operation Terminated\n");
                        break;
                case 0x01:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Subsystem Processing Error");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Subsystem Processing Error\n");
                        break;
                case 0x02:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT F - Cache or nonvolatile storage "
-                                   "equipment failure");
+                                   "equipment failure\n");
                        break;
                case 0x04:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Caching terminated");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Caching terminated\n");
                        break;
                case 0x06:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT F - Cache fast write access not "
-                                   "authorized");
+                                   "authorized\n");
                        break;
                case 0x07:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Track format incorrect");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Track format incorrect\n");
                        break;
                case 0x09:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Caching reinitiated");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Caching reinitiated\n");
                        break;
                case 0x0A:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT F - Nonvolatile storage "
-                                   "terminated");
+                                   "terminated\n");
                        break;
                case 0x0B:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Volume is suspended duplex");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Volume is suspended duplex\n");
                        /* call extended error reporting (EER) */
                        dasd_eer_write(device, erp->refers,
                                       DASD_EER_PPRCSUSPEND);
                        break;
                case 0x0C:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - Subsystem status connot be "
-                                   "determined");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - Subsystem status cannot be "
+                                   "determined\n");
                        break;
                case 0x0D:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                       dev_warn(&device->cdev->dev,
                                    "FORMAT F - Caching status reset to "
-                                   "default");
+                                   "default\n");
                        break;
                case 0x0E:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT F - DASD Fast Write inhibited");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT F - DASD Fast Write inhibited\n");
                        break;
                default:
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "FORMAT D - Reserved");
+                       dev_warn(&device->cdev->dev,
+                                   "FORMAT D - Reserved\n");
                }
                break;
 
-       default:        /* unknown message format - should not happen */
-               DEV_MESSAGE (KERN_WARNING, device,
-                             "unknown message format %02x",
-                             msg_format);
+       default:        /* unknown message format - should not happen
+                          internal error 03 - unknown message format */
+               snprintf(errorstring, ERRORLENGTH, "03 %x02", msg_format);
+               dev_err(&device->cdev->dev,
+                        "An error occurred in the DASD device driver, "
+                        "reason=%s\n", errorstring);
                break;
        }                       /* end switch message format */
 
@@ -1015,7 +1025,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
        /* env data present (ACTION 10 - retry should work) */
        if (sense[2] & SNS2_ENV_DATA_PRESENT) {
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Command Reject - environmental data present");
 
                dasd_3990_handle_env_data(erp, sense);
@@ -1023,9 +1033,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
                erp->retries = 5;
 
        } else {
-               /* fatal error -  set status to FAILED */
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "Command Reject - Fatal error");
+               /* fatal error -  set status to FAILED
+                  internal error 09 - Command Reject */
+               dev_err(&device->cdev->dev, "An error occurred in the DASD "
+                       "device driver, reason=%s\n", "09");
 
                erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
        }
@@ -1061,7 +1072,7 @@ dasd_3990_erp_bus_out(struct dasd_ccw_req * erp)
        } else {
 
                /* issue a message and wait for 'device ready' interrupt */
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "bus out parity error or BOPC requested by "
                            "channel");
 
@@ -1093,21 +1104,19 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
        erp->function = dasd_3990_erp_equip_check;
 
        if (sense[1] & SNS1_WRITE_INHIBITED) {
+               dev_info(&device->cdev->dev,
+                           "Write inhibited path encountered\n");
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
-                           "Write inhibited path encountered");
-
-               /* vary path offline */
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "Path should be varied off-line. "
-                           "This is not implemented yet \n - please report "
-                           "to linux390@de.ibm.com");
+               /* vary path offline
+                  internal error 04 - Path should be varied off-line.*/
+               dev_err(&device->cdev->dev, "An error occurred in the DASD "
+                       "device driver, reason=%s\n", "04");
 
                erp = dasd_3990_erp_action_1(erp);
 
        } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Equipment Check - " "environmental data present");
 
                dasd_3990_handle_env_data(erp, sense);
@@ -1116,7 +1125,7 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
 
        } else if (sense[1] & SNS1_PERM_ERR) {
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Equipment Check - retry exhausted or "
                            "undesirable");
 
@@ -1125,7 +1134,7 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
        } else {
                /* all other equipment checks - Action 5 */
                /* rest is done when retries == 0 */
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Equipment check or processing error");
 
                erp = dasd_3990_erp_action_5(erp);
@@ -1156,9 +1165,9 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
        if (sense[2] & SNS2_CORRECTABLE) {      /* correctable data check */
 
                /* issue message that the data has been corrected */
-               DEV_MESSAGE(KERN_EMERG, device, "%s",
+               dev_emerg(&device->cdev->dev,
                            "Data recovered during retry with PCI "
-                           "fetch mode active");
+                           "fetch mode active\n");
 
                /* not possible to handle this situation in Linux */
                panic("No way to inform application about the possibly "
@@ -1166,7 +1175,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
 
        } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Uncorrectable data check recovered secondary "
                            "addr of duplex pair");
 
@@ -1174,7 +1183,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
 
        } else if (sense[1] & SNS1_PERM_ERR) {
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Uncorrectable data check with internal "
                            "retry exhausted");
 
@@ -1182,7 +1191,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
 
        } else {
                /* all other data checks */
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Uncorrectable data check with retry count "
                            "exhausted...");
 
@@ -1212,7 +1221,7 @@ dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense)
 
        erp->function = dasd_3990_erp_overrun;
 
-       DEV_MESSAGE(KERN_DEBUG, device, "%s",
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                    "Overrun - service overrun or overrun"
                    " error requested by channel");
 
@@ -1243,7 +1252,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
 
        if (sense[2] & SNS2_ENV_DATA_PRESENT) {
 
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Track format error when destaging or "
                            "staging data");
 
@@ -1252,8 +1261,10 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
                erp = dasd_3990_erp_action_4(erp, sense);
 
        } else {
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "Invalid Track Format - Fatal error");
+               /* internal error 06 - The track format is not valid*/
+               dev_err(&device->cdev->dev,
+                       "An error occurred in the DASD device driver, "
+                       "reason=%s\n", "06");
 
                erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
        }
@@ -1279,8 +1290,8 @@ dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense)
 
        struct dasd_device *device = default_erp->startdev;
 
-       DEV_MESSAGE(KERN_ERR, device, "%s",
-                   "End-of-Cylinder - must never happen");
+       dev_err(&device->cdev->dev,
+               "The cylinder data for accessing the DASD is inconsistent\n");
 
        /* implement action 7 - BUG */
        return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
@@ -1306,7 +1317,7 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
 
        erp->function = dasd_3990_erp_env_data;
 
-       DEV_MESSAGE(KERN_DEBUG, device, "%s", "Environmental data present");
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Environmental data present");
 
        dasd_3990_handle_env_data(erp, sense);
 
@@ -1339,8 +1350,8 @@ dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense)
 
        struct dasd_device *device = default_erp->startdev;
 
-       DEV_MESSAGE(KERN_ERR, device, "%s",
-                   "No Record Found - Fatal error ");
+       dev_err(&device->cdev->dev,
+                   "The specified record was not found\n");
 
        return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
 
@@ -1365,7 +1376,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
 
        struct dasd_device *device = erp->startdev;
 
-       DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected");
+       dev_err(&device->cdev->dev, "Accessing the DASD failed because of "
+               "a hardware error\n");
 
        return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
 
@@ -1394,7 +1406,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(
        if (cqr->block &&
            (cqr->block->base != cqr->startdev)) {
                if (cqr->startdev->features & DASD_FEATURE_ERPLOG) {
-                       DEV_MESSAGE(KERN_ERR, cqr->startdev,
+                       DBF_DEV_EVENT(DBF_ERR, cqr->startdev,
                                    "ERP on alias device for request %p,"
                                    " recover on base device %s", cqr,
                                    dev_name(&cqr->block->base->cdev->dev));
@@ -1511,7 +1523,7 @@ dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)
        erp->retries = 256;
        erp->function = dasd_3990_erp_action_10_32;
 
-       DEV_MESSAGE(KERN_DEBUG, device, "%s", "Perform logging requested");
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Perform logging requested");
 
        return erp;
 
@@ -1549,7 +1561,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
        char *LO_data;          /* LO_eckd_data_t */
        struct ccw1 *ccw, *oldccw;
 
-       DEV_MESSAGE(KERN_DEBUG, device, "%s",
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                    "Write not finished because of unexpected condition");
 
        default_erp->function = dasd_3990_erp_action_1B_32;
@@ -1561,10 +1573,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
                cqr = cqr->refers;
        }
 
+       if (scsw_is_tm(&cqr->irb.scsw)) {
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                             "32 bit sense, action 1B is not defined"
+                             " in transport mode - just retry");
+               return default_erp;
+       }
+
        /* for imprecise ending just do default erp */
        if (sense[1] & 0x01) {
-
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Imprecise ending is set - just retry");
 
                return default_erp;
@@ -1575,8 +1593,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
        cpa = default_erp->refers->irb.scsw.cmd.cpa;
 
        if (cpa == 0) {
-
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Unable to determine address of the CCW "
                            "to be restarted");
 
@@ -1590,7 +1607,9 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
                                     sizeof(struct LO_eckd_data), device);
 
        if (IS_ERR(erp)) {
-               DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP");
+               /* internal error 01 - Unable to allocate ERP */
+               dev_err(&device->cdev->dev, "An error occurred in the DASD "
+                       "device driver, reason=%s\n", "01");
                return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
        }
 
@@ -1599,7 +1618,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
        oldccw = cqr->cpaddr;
        if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) {
                PFX_data = cqr->data;
-               memcpy(DE_data, &PFX_data->define_extend,
+               memcpy(DE_data, &PFX_data->define_extent,
                       sizeof(struct DE_eckd_data));
        } else
                memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data));
@@ -1608,10 +1627,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
        LO_data = erp->data + sizeof(struct DE_eckd_data);
 
        if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
-
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "BUG - this should not happen");
-
+               /* should not */
                return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
        }
 
@@ -1701,7 +1717,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
        char *LO_data;          /* struct LO_eckd_data */
        struct ccw1 *ccw;
 
-       DEV_MESSAGE(KERN_DEBUG, device, "%s",
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                    "Write not finished because of unexpected condition"
                    " - follow on");
 
@@ -1712,10 +1728,16 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
                cqr = cqr->refers;
        }
 
+       if (scsw_is_tm(&cqr->irb.scsw)) {
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                             "32 bit sense, action 1B, update,"
+                             " in transport mode - just retry");
+               return previous_erp;
+       }
+
        /* for imprecise ending just do default erp */
        if (sense[1] & 0x01) {
-
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Imprecise ending is set - just retry");
 
                previous_erp->status = DASD_CQR_FILLED;
@@ -1728,10 +1750,10 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
        cpa = previous_erp->irb.scsw.cmd.cpa;
 
        if (cpa == 0) {
-
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
-                           "Unable to determine address of the CCW "
-                           "to be restarted");
+               /* internal error 02 -
+                  Unable to determine address of the CCW to be restarted */
+               dev_err(&device->cdev->dev, "An error occurred in the DASD "
+                       "device driver, reason=%s\n", "02");
 
                previous_erp->status = DASD_CQR_FAILED;
 
@@ -1744,10 +1766,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
        LO_data = erp->data + sizeof(struct DE_eckd_data);
 
        if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
-
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "BUG - this should not happen");
-
+               /* should not happen */
                previous_erp->status = DASD_CQR_FAILED;
 
                return previous_erp;
@@ -1935,14 +1954,13 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)
 
        if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) {
 
-               /* set to suspended duplex state then restart */
+               /* set to suspended duplex state then restart
+                  internal error 05 - Set device to suspended duplex state
+                  should be done */
                struct dasd_device *device = erp->startdev;
-
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "Set device to suspended duplex state should be "
-                           "done!\n"
-                           "This is not implemented yet (for compound ERP)"
-                           " - please report to linux390@de.ibm.com");
+               dev_err(&device->cdev->dev,
+                       "An error occurred in the DASD device driver, "
+                       "reason=%s\n", "05");
 
        }
 
@@ -2012,15 +2030,14 @@ dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense)
 {
        /* print message according to log or message to operator mode */
        if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) {
-
                /* print SIM SRC from RefCode */
-               DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: "
-                           "%02x%02x%02x%02x", sense[22],
+               dev_err(&device->cdev->dev, "SIM - SRC: "
+                           "%02x%02x%02x%02x\n", sense[22],
                            sense[23], sense[11], sense[12]);
        } else if (sense[24] & DASD_SIM_LOG) {
                /* print SIM SRC Refcode */
-               DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: "
-                           "%02x%02x%02x%02x", sense[22],
+               dev_warn(&device->cdev->dev, "log SIM - SRC: "
+                           "%02x%02x%02x%02x\n", sense[22],
                            sense[23], sense[11], sense[12]);
        }
 }
@@ -2063,14 +2080,14 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                switch (sense[25]) {
 
                case 0x00:      /* success - use default ERP for retries */
-                       DEV_MESSAGE(KERN_DEBUG, device, "%s",
+                       DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
                                    "ERP called for successful request"
                                    " - just retry");
                        break;
 
                case 0x01:      /* fatal error */
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
-                                   "Retry not recommended - Fatal error");
+                       dev_err(&device->cdev->dev,
+                                   "ERP failed for the DASD\n");
 
                        erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
                        break;
@@ -2080,13 +2097,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        erp = dasd_3990_erp_int_req(erp);
                        break;
 
-               case 0x0F:  /* length mismatch during update write command */
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
-                                   "update write command error - should not "
-                                   "happen;\n"
-                                   "Please send this message together with "
-                                   "the above sense data to linux390@de."
-                                   "ibm.com");
+               case 0x0F:  /* length mismatch during update write command
+                              internal error 08 - update write command error*/
+                       dev_err(&device->cdev->dev, "An error occurred in the "
+                               "DASD device driver, reason=%s\n", "08");
 
                        erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
                        break;
@@ -2095,13 +2109,12 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        erp = dasd_3990_erp_action_10_32(erp, sense);
                        break;
 
-               case 0x15:      /* next track outside defined extend */
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
-                                   "next track outside defined extend - "
-                                   "should not happen;\n"
-                                   "Please send this message together with "
-                                   "the above sense data to linux390@de."
-                                   "ibm.com");
+               case 0x15:      /* next track outside defined extend
+                                  internal error 07 - The next track is not
+                                  within the defined storage extent */
+                       dev_err(&device->cdev->dev,
+                               "An error occurred in the DASD device driver, "
+                               "reason=%s\n", "07");
 
                        erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
                        break;
@@ -2112,9 +2125,9 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        break;
 
                case 0x1C:      /* invalid data */
-                       DEV_MESSAGE(KERN_EMERG, device, "%s",
+                       dev_emerg(&device->cdev->dev,
                                    "Data recovered during retry with PCI "
-                                   "fetch mode active");
+                                   "fetch mode active\n");
 
                        /* not possible to handle this situation in Linux */
                        panic
@@ -2123,7 +2136,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        break;
 
                case 0x1D:      /* state-change pending */
-                       DEV_MESSAGE(KERN_DEBUG, device, "%s",
+                       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                                    "A State change pending condition exists "
                                    "for the subsystem or device");
 
@@ -2131,7 +2144,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
                        break;
 
                case 0x1E:      /* busy */
-                        DEV_MESSAGE(KERN_DEBUG, device, "%s",
+                       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                                    "Busy condition exists "
                                    "for the subsystem or device");
                         erp = dasd_3990_erp_action_4(erp, sense);
@@ -2171,9 +2184,9 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
 {
        struct dasd_device *device = erp->startdev;
 
-       if (erp->refers->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK
+       if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK
                                           | SCHN_STAT_CHN_CTRL_CHK)) {
-               DEV_MESSAGE(KERN_DEBUG, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "channel or interface control check");
                erp = dasd_3990_erp_action_4(erp, NULL);
        }
@@ -2193,21 +2206,23 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
  *   erp_new           contens was possibly modified
  */
 static struct dasd_ccw_req *
-dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
+dasd_3990_erp_inspect(struct dasd_ccw_req *erp)
 {
 
        struct dasd_ccw_req *erp_new = NULL;
-       /* sense data are located in the refers record of the */
-       /* already set up new ERP !                           */
-       char *sense = erp->refers->irb.ecw;
+       char *sense;
 
        /* if this problem occured on an alias retry on base */
        erp_new = dasd_3990_erp_inspect_alias(erp);
        if (erp_new)
                return erp_new;
 
-       /* check if no concurrent sens is available */
-       if (!erp->refers->irb.esw.esw0.erw.cons)
+       /* sense data are located in the refers record of the
+        * already set up new ERP !
+        * check if concurrent sens is available
+        */
+       sense = dasd_get_sense(&erp->refers->irb);
+       if (!sense)
                erp_new = dasd_3990_erp_control_check(erp);
        /* distinguish between 24 and 32 byte sense data */
        else if (sense[27] & DASD_SENSE_BIT_0) {
@@ -2231,7 +2246,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
  * DESCRIPTION
  *   This funtion adds an additional request block (ERP) to the head of
  *   the given cqr (or erp).
- *   This erp is initialized as an default erp (retry TIC)
+ *   For a command mode cqr the erp is initialized as an default erp
+ *   (retry TIC).
+ *   For transport mode we make a copy of the original TCW (points to
+ *   the original TCCB, TIDALs, etc.) but give it a fresh
+ *   TSB so the original sense data will not be changed.
  *
  * PARAMETER
  *   cqr               head of the current ERP-chain (or single cqr if
@@ -2239,25 +2258,35 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
  * RETURN VALUES
  *   erp               pointer to new ERP-chain head
  */
-static struct dasd_ccw_req *
-dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
+static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
 {
 
        struct dasd_device *device = cqr->startdev;
        struct ccw1 *ccw;
-
-       /* allocate additional request block */
        struct dasd_ccw_req *erp;
+       int cplength, datasize;
+       struct tcw *tcw;
+       struct tsb *tsb;
+
+       if (cqr->cpmode == 1) {
+               cplength = 0;
+               datasize = sizeof(struct tcw) + sizeof(struct tsb);
+       } else {
+               cplength = 2;
+               datasize = 0;
+       }
 
-       erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, device);
+       /* allocate additional request block */
+       erp = dasd_alloc_erp_request((char *) &cqr->magic,
+                                    cplength, datasize, device);
        if (IS_ERR(erp)) {
                 if (cqr->retries <= 0) {
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
+                       DBF_DEV_EVENT(DBF_ERR, device, "%s",
                                    "Unable to allocate ERP request");
                        cqr->status = DASD_CQR_FAILED;
                         cqr->stopclk = get_clock ();
                } else {
-                        DEV_MESSAGE (KERN_ERR, device,
+                       DBF_DEV_EVENT(DBF_ERR, device,
                                      "Unable to allocate ERP request "
                                     "(%i retries left)",
                                      cqr->retries);
@@ -2266,13 +2295,24 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
                return cqr;
        }
 
-       /* initialize request with default TIC to current ERP/CQR */
-       ccw = erp->cpaddr;
-       ccw->cmd_code = CCW_CMD_NOOP;
-       ccw->flags = CCW_FLAG_CC;
-       ccw++;
-       ccw->cmd_code = CCW_CMD_TIC;
-       ccw->cda      = (long)(cqr->cpaddr);
+       if (cqr->cpmode == 1) {
+               /* make a shallow copy of the original tcw but set new tsb */
+               erp->cpmode = 1;
+               erp->cpaddr = erp->data;
+               tcw = erp->data;
+               tsb = (struct tsb *) &tcw[1];
+               *tcw = *((struct tcw *)cqr->cpaddr);
+               tcw->tsb = (long)tsb;
+       } else {
+               /* initialize request with default TIC to current ERP/CQR */
+               ccw = erp->cpaddr;
+               ccw->cmd_code = CCW_CMD_NOOP;
+               ccw->flags = CCW_FLAG_CC;
+               ccw++;
+               ccw->cmd_code = CCW_CMD_TIC;
+               ccw->cda      = (long)(cqr->cpaddr);
+       }
+
        erp->function = dasd_3990_erp_add_erp;
        erp->refers   = cqr;
        erp->startdev = device;
@@ -2282,7 +2322,6 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
        erp->expires  = 0;
        erp->retries  = 256;
        erp->buildclk = get_clock();
-
        erp->status = DASD_CQR_FILLED;
 
        return erp;
@@ -2340,28 +2379,33 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr)
  *   match             'boolean' for match found
  *                     returns 1 if match found, otherwise 0.
  */
-static int
-dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
+static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1,
+                                    struct dasd_ccw_req *cqr2)
 {
+       char *sense1, *sense2;
 
        if (cqr1->startdev != cqr2->startdev)
                return 0;
 
-       if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons)
-               return 0;
+       sense1 = dasd_get_sense(&cqr1->irb);
+       sense2 = dasd_get_sense(&cqr2->irb);
 
-       if ((cqr1->irb.esw.esw0.erw.cons == 0) &&
-           (cqr2->irb.esw.esw0.erw.cons == 0)) {
-               if ((cqr1->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK |
-                                            SCHN_STAT_CHN_CTRL_CHK)) ==
-                   (cqr2->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK |
-                                            SCHN_STAT_CHN_CTRL_CHK)))
+       /* one request has sense data, the other not -> no match, return 0 */
+       if (!sense1 != !sense2)
+               return 0;
+       /* no sense data in both cases -> check cstat for IFCC */
+       if (!sense1 && !sense2) {
+               if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |
+                                                   SCHN_STAT_CHN_CTRL_CHK)) ==
+                   (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |
+                                                   SCHN_STAT_CHN_CTRL_CHK)))
                        return 1; /* match with ifcc*/
        }
        /* check sense data; byte 0-2,25,27 */
-       if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) &&
-             (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) &&
-             (cqr1->irb.ecw[25] == cqr2->irb.ecw[25]))) {
+       if (!(sense1 && sense2 &&
+             (memcmp(sense1, sense2, 3) == 0) &&
+             (sense1[27] == sense2[27]) &&
+             (sense1[25] == sense2[25]))) {
 
                return 0;       /* sense doesn't match */
        }
@@ -2434,7 +2478,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
 {
 
        struct dasd_device *device = erp->startdev;
-       char *sense = erp->irb.ecw;
+       char *sense = dasd_get_sense(&erp->irb);
 
        /* check for 24 byte sense ERP */
        if ((erp->function == dasd_3990_erp_bus_out) ||
@@ -2449,7 +2493,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
                /* prepare erp for retry on different channel path */
                erp = dasd_3990_erp_action_1(erp);
 
-               if (!(sense[2] & DASD_SENSE_BIT_0)) {
+               if (sense && !(sense[2] & DASD_SENSE_BIT_0)) {
 
                        /* issue a Diagnostic Control command with an
                         * Inhibit Write subcommand */
@@ -2471,7 +2515,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
                                        break;
                                }
                        default:
-                               DEV_MESSAGE(KERN_DEBUG, device,
+                               DBF_DEV_EVENT(DBF_WARNING, device,
                                            "invalid subcommand modifier 0x%x "
                                            "for Diagnostic Control Command",
                                            sense[25]);
@@ -2479,19 +2523,21 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
                }
 
                /* check for 32 byte sense ERP */
-       } else if ((erp->function == dasd_3990_erp_compound_retry) ||
-                  (erp->function == dasd_3990_erp_compound_path) ||
-                  (erp->function == dasd_3990_erp_compound_code) ||
-                  (erp->function == dasd_3990_erp_compound_config)) {
+       } else if (sense &&
+                  ((erp->function == dasd_3990_erp_compound_retry) ||
+                   (erp->function == dasd_3990_erp_compound_path) ||
+                   (erp->function == dasd_3990_erp_compound_code) ||
+                   (erp->function == dasd_3990_erp_compound_config))) {
 
                erp = dasd_3990_erp_compound(erp, sense);
 
        } else {
-               /* No retry left and no additional special handling */
-               /*necessary */
-               DEV_MESSAGE(KERN_ERR, device,
-                           "no retries left for erp %p - "
-                           "set status to FAILED", erp);
+               /*
+                * No retry left and no additional special handling
+                * necessary
+                */
+               dev_err(&device->cdev->dev,
+                       "ERP %p has run out of retries and failed\n", erp);
 
                erp->status = DASD_CQR_FAILED;
        }
@@ -2548,24 +2594,25 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
 
        if (erp->retries > 0) {
 
-               char *sense = erp->refers->irb.ecw;
+               char *sense = dasd_get_sense(&erp->refers->irb);
 
                /* check for special retries */
-               if (erp->function == dasd_3990_erp_action_4) {
+               if (sense && erp->function == dasd_3990_erp_action_4) {
 
                        erp = dasd_3990_erp_action_4(erp, sense);
 
-               } else if (erp->function == dasd_3990_erp_action_1B_32) {
+               } else if (sense &&
+                          erp->function == dasd_3990_erp_action_1B_32) {
 
                        erp = dasd_3990_update_1B(erp, sense);
 
-               } else if (erp->function == dasd_3990_erp_int_req) {
+               } else if (sense && erp->function == dasd_3990_erp_int_req) {
 
                        erp = dasd_3990_erp_int_req(erp);
 
                } else {
                        /* simple retry   */
-                       DEV_MESSAGE(KERN_DEBUG, device,
+                       DBF_DEV_EVENT(DBF_DEBUG, device,
                                    "%i retries left for erp %p",
                                    erp->retries, erp);
 
@@ -2609,24 +2656,24 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
 
        if (device->features & DASD_FEATURE_ERPLOG) {
                /* print current erp_chain */
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "ERP chain at BEGINNING of ERP-ACTION");
+               dev_err(&device->cdev->dev,
+                           "ERP chain at BEGINNING of ERP-ACTION\n");
                for (temp_erp = cqr;
                     temp_erp != NULL; temp_erp = temp_erp->refers) {
 
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "   erp %p (%02x) refers to %p",
+                       dev_err(&device->cdev->dev,
+                                   "ERP %p (%02x) refers to %p\n",
                                    temp_erp, temp_erp->status,
                                    temp_erp->refers);
                }
        }
 
        /* double-check if current erp/cqr was successful */
-       if ((cqr->irb.scsw.cmd.cstat == 0x00) &&
-           (cqr->irb.scsw.cmd.dstat ==
+       if ((scsw_cstat(&cqr->irb.scsw) == 0x00) &&
+           (scsw_dstat(&cqr->irb.scsw) ==
             (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
 
-               DEV_MESSAGE(KERN_DEBUG, device,
+               DBF_DEV_EVENT(DBF_DEBUG, device,
                            "ERP called for successful request %p"
                            " - NO ERP necessary", cqr);
 
@@ -2648,13 +2695,13 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
 
        if (device->features & DASD_FEATURE_ERPLOG) {
                /* print current erp_chain */
-               DEV_MESSAGE(KERN_ERR, device, "%s",
-                           "ERP chain at END of ERP-ACTION");
+               dev_err(&device->cdev->dev,
+                           "ERP chain at END of ERP-ACTION\n");
                for (temp_erp = erp;
                     temp_erp != NULL; temp_erp = temp_erp->refers) {
 
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "   erp %p (%02x) refers to %p",
+                       dev_err(&device->cdev->dev,
+                                   "ERP %p (%02x) refers to %p\n",
                                    temp_erp, temp_erp->status,
                                    temp_erp->refers);
                }
@@ -2667,6 +2714,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
                list_add_tail(&erp->blocklist, &cqr->blocklist);
        }
 
+
+
        return erp;
 
 }                              /* end dasd_3990_erp_action */
index 20676cdef4a519802b1d1a605d637f21ae64319b..5b7bbc87593b3b5172504d32dddbbfe11aac11b4 100644 (file)
@@ -5,6 +5,8 @@
  * Author(s): Stefan Weinhuber <wein@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/list.h>
 #include <asm/ebcdic.h>
 #include "dasd_int.h"
@@ -503,7 +505,7 @@ static void lcu_update_work(struct work_struct *work)
         */
        spin_lock_irqsave(&lcu->lock, flags);
        if (rc || (lcu->flags & NEED_UAC_UPDATE)) {
-               DEV_MESSAGE(KERN_WARNING, device, "could not update"
+               DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
                            " alias data in lcu (rc = %d), retry later", rc);
                schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
        } else {
@@ -646,14 +648,16 @@ static int reset_summary_unit_check(struct alias_lcu *lcu,
 {
        struct dasd_ccw_req *cqr;
        int rc = 0;
+       struct ccw1 *ccw;
 
        cqr = lcu->rsu_cqr;
        strncpy((char *) &cqr->magic, "ECKD", 4);
        ASCEBC((char *) &cqr->magic, 4);
-       cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RSCK;
-       cqr->cpaddr->flags = 0 ;
-       cqr->cpaddr->count = 16;
-       cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = DASD_ECKD_CCW_RSCK;
+       ccw->flags = 0 ;
+       ccw->count = 16;
+       ccw->cda = (__u32)(addr_t) cqr->data;
        ((char *)cqr->data)[0] = reason;
 
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
@@ -855,16 +859,25 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
        struct alias_lcu *lcu;
        char reason;
        struct dasd_eckd_private *private;
+       char *sense;
 
        private = (struct dasd_eckd_private *) device->private;
 
-       reason = irb->ecw[8];
-       DEV_MESSAGE(KERN_WARNING, device, "%s %x",
-                   "eckd handle summary unit check: reason", reason);
+       sense = dasd_get_sense(irb);
+       if (sense) {
+               reason = sense[8];
+               DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x",
+                           "eckd handle summary unit check: reason", reason);
+       } else {
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                           "eckd handle summary unit check:"
+                           " no reason code available");
+               return;
+       }
 
        lcu = private->lcu;
        if (!lcu) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "device not ready to handle summary"
                            " unit check (no lcu structure)");
                return;
@@ -877,7 +890,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
         * the next interrupt on a different device
         */
        if (list_empty(&device->alias_list)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "device is in offline processing,"
                            " don't do summary unit check handling");
                spin_unlock(&lcu->lock);
@@ -885,7 +898,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
        }
        if (lcu->suc_data.device) {
                /* already scheduled or running */
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "previous instance of summary unit check worker"
                            " still pending");
                spin_unlock(&lcu->lock);
index 34339902efb9efd2ed64f9ca6515141b0b85c9cb..e77666c8e6c01af8df79963215c686112b8a2a42 100644 (file)
@@ -13,6 +13,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -67,6 +69,8 @@ int dasd_probeonly =  0;      /* is true, when probeonly mode is active */
 int dasd_autodetect = 0;       /* is true, when autodetection is active */
 int dasd_nopav = 0;            /* is true, when PAV is disabled */
 EXPORT_SYMBOL_GPL(dasd_nopav);
+int dasd_nofcx;                        /* disable High Performance Ficon */
+EXPORT_SYMBOL_GPL(dasd_nofcx);
 
 /*
  * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
@@ -125,6 +129,7 @@ __setup ("dasd=", dasd_call_setup);
  * Read a device busid/devno from a string.
  */
 static int
+
 dasd_busid(char **str, int *id0, int *id1, int *devno)
 {
        int val, old_style;
@@ -132,8 +137,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno)
        /* Interpret ipldev busid */
        if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) {
                if (ipl_info.type != IPL_TYPE_CCW) {
-                       MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw "
-                               "device");
+                       pr_err("The IPL device is not a CCW device\n");
                        return -EINVAL;
                }
                *id0 = 0;
@@ -209,9 +213,8 @@ dasd_feature_list(char *str, char **endp)
                else if (len == 8 && !strncmp(str, "failfast", 8))
                        features |= DASD_FEATURE_FAILFAST;
                else {
-                       MESSAGE(KERN_WARNING,
-                               "unsupported feature: %*s, "
-                               "ignoring setting", len, str);
+                       pr_warning("%*s is not a supported device option\n",
+                                  len, str);
                        rc = -EINVAL;
                }
                str += len;
@@ -220,8 +223,8 @@ dasd_feature_list(char *str, char **endp)
                str++;
        }
        if (*str != ')') {
-               MESSAGE(KERN_WARNING, "%s",
-                       "missing ')' in dasd parameter string\n");
+               pr_warning("A closing parenthesis ')' is missing in the "
+                          "dasd= parameter\n");
                rc = -EINVAL;
        } else
                str++;
@@ -253,25 +256,29 @@ dasd_parse_keyword( char *parsestring ) {
         }
        if (strncmp("autodetect", parsestring, length) == 0) {
                dasd_autodetect = 1;
-               MESSAGE (KERN_INFO, "%s",
-                        "turning to autodetection mode");
+               pr_info("The autodetection mode has been activated\n");
                 return residual_str;
         }
        if (strncmp("probeonly", parsestring, length) == 0) {
                dasd_probeonly = 1;
-               MESSAGE(KERN_INFO, "%s",
-                       "turning to probeonly mode");
+               pr_info("The probeonly mode has been activated\n");
                 return residual_str;
         }
        if (strncmp("nopav", parsestring, length) == 0) {
                if (MACHINE_IS_VM)
-                       MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
+                       pr_info("'nopav' is not supported on z/VM\n");
                else {
                        dasd_nopav = 1;
-                       MESSAGE(KERN_INFO, "%s", "disable PAV mode");
+                       pr_info("PAV support has be deactivated\n");
                }
                return residual_str;
        }
+       if (strncmp("nofcx", parsestring, length) == 0) {
+               dasd_nofcx = 1;
+               pr_info("High Performance FICON support has been "
+                       "deactivated\n");
+               return residual_str;
+       }
        if (strncmp("fixedbuffers", parsestring, length) == 0) {
                if (dasd_page_cache)
                        return residual_str;
@@ -280,10 +287,10 @@ dasd_parse_keyword( char *parsestring ) {
                                          PAGE_SIZE, SLAB_CACHE_DMA,
                                          NULL);
                if (!dasd_page_cache)
-                       MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
+                       DBF_EVENT(DBF_WARNING, "%s", "Failed to create slab, "
                                "fixed buffer mode disabled.");
                else
-                       MESSAGE (KERN_INFO, "%s",
+                       DBF_EVENT(DBF_INFO, "%s",
                                 "turning on fixed buffer mode");
                 return residual_str;
         }
@@ -321,7 +328,7 @@ dasd_parse_range( char *parsestring ) {
            (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
                rc = -EINVAL;
        if (rc) {
-               MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
+               pr_err("%s is not a valid device range\n", parsestring);
                return ERR_PTR(rc);
        }
        features = dasd_feature_list(str, &str);
@@ -340,8 +347,8 @@ dasd_parse_range( char *parsestring ) {
                return str + 1;
        if (*str == '\0')
                return str;
-       MESSAGE(KERN_WARNING,
-               "junk at end of dasd parameter string: %s\n", str);
+       pr_warning("The dasd= parameter value %s has an invalid ending\n",
+                  str);
        return ERR_PTR(-EINVAL);
 }
 
index ef2a5695205442a05c4ff817444066076df5d6e7..b9a7f77334468ff5afc4e34d59a6baffadb543ea 100644 (file)
@@ -8,6 +8,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -144,8 +146,8 @@ dasd_diag_erp(struct dasd_device *device)
        mdsk_term_io(device);
        rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
        if (rc)
-               DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, "
-                           "rc=%d", rc);
+               dev_warn(&device->cdev->dev, "DIAG ERP failed with "
+                           "rc=%d\n", rc);
 }
 
 /* Start a given request at the device. Return zero on success, non-zero
@@ -160,7 +162,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
 
        device = cqr->startdev;
        if (cqr->retries < 0) {
-               DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p "
+               DBF_DEV_EVENT(DBF_ERR, device, "DIAG start_IO: request %p "
                            "- no retry left)", cqr);
                cqr->status = DASD_CQR_ERROR;
                return -EIO;
@@ -195,7 +197,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
                break;
        default: /* Error condition */
                cqr->status = DASD_CQR_QUEUED;
-               DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc);
+               DBF_DEV_EVENT(DBF_WARNING, device, "dia250 returned rc=%d", rc);
                dasd_diag_erp(device);
                rc = -EIO;
                break;
@@ -243,13 +245,14 @@ dasd_ext_handler(__u16 code)
                return;
        }
        if (!ip) {              /* no intparm: unsolicited interrupt */
-               MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
+               DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
+                             "interrupt");
                return;
        }
        cqr = (struct dasd_ccw_req *) ip;
        device = (struct dasd_device *) cqr->startdev;
        if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
-               DEV_MESSAGE(KERN_WARNING, device,
+               DBF_DEV_EVENT(DBF_WARNING, device,
                            " magic number of dasd_ccw_req 0x%08X doesn't"
                            " match discipline 0x%08X",
                            cqr->magic, *(int *) (&device->discipline->name));
@@ -281,15 +284,11 @@ dasd_ext_handler(__u16 code)
                                rc = dasd_start_diag(next);
                                if (rc == 0)
                                        expires = next->expires;
-                               else if (rc != -EACCES)
-                                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                                   "Interrupt fastpath "
-                                                   "failed!");
                        }
                }
        } else {
                cqr->status = DASD_CQR_QUEUED;
-               DEV_MESSAGE(KERN_WARNING, device, "interrupt status for "
+               DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "
                            "request %p was %d (%d retries left)", cqr, status,
                            cqr->retries);
                dasd_diag_erp(device);
@@ -322,8 +321,9 @@ dasd_diag_check_device(struct dasd_device *device)
        if (private == NULL) {
                private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL);
                if (private == NULL) {
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                               "memory allocation failed for private data");
+                       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                               "Allocating memory for private DASD data "
+                                     "failed\n");
                        return -ENOMEM;
                }
                ccw_device_get_id(device->cdev, &private->dev_id);
@@ -331,7 +331,7 @@ dasd_diag_check_device(struct dasd_device *device)
        }
        block = dasd_alloc_block();
        if (IS_ERR(block)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "could not allocate dasd block structure");
                device->private = NULL;
                kfree(private);
@@ -347,7 +347,7 @@ dasd_diag_check_device(struct dasd_device *device)
 
        rc = diag210((struct diag210 *) rdc_data);
        if (rc) {
-               DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device "
+               DBF_DEV_EVENT(DBF_WARNING, device, "failed to retrieve device "
                            "information (rc=%d)", rc);
                rc = -EOPNOTSUPP;
                goto out;
@@ -362,8 +362,8 @@ dasd_diag_check_device(struct dasd_device *device)
                private->pt_block = 2;
                break;
        default:
-               DEV_MESSAGE(KERN_WARNING, device, "unsupported device class "
-                           "(class=%d)", private->rdc_data.vdev_class);
+               dev_warn(&device->cdev->dev, "Device type %d is not supported "
+                           "in DIAG mode\n", private->rdc_data.vdev_class);
                rc = -EOPNOTSUPP;
                goto out;
        }
@@ -380,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device)
        /* figure out blocksize of device */
        label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);
        if (label == NULL)  {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "No memory to allocate initialization request");
                rc = -ENOMEM;
                goto out;
@@ -404,8 +404,8 @@ dasd_diag_check_device(struct dasd_device *device)
                private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
                rc = dia250(&private->iob, RW_BIO);
                if (rc == 3) {
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                               "DIAG call failed");
+                       dev_warn(&device->cdev->dev,
+                               "A 64-bit DIAG call failed\n");
                        rc = -EOPNOTSUPP;
                        goto out_label;
                }
@@ -414,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device)
                        break;
        }
        if (bsize > PAGE_SIZE) {
-               DEV_MESSAGE(KERN_WARNING, device, "device access failed "
-                           "(rc=%d)", rc);
+               dev_warn(&device->cdev->dev, "Accessing the DASD failed because"
+                        " of an incorrect format (rc=%d)\n", rc);
                rc = -EIO;
                goto out_label;
        }
@@ -433,15 +433,15 @@ dasd_diag_check_device(struct dasd_device *device)
                block->s2b_shift++;
        rc = mdsk_init_io(device, block->bp_block, 0, NULL);
        if (rc) {
-               DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization "
-                       "failed (rc=%d)", rc);
+               dev_warn(&device->cdev->dev, "DIAG initialization "
+                       "failed with rc=%d\n", rc);
                rc = -EIO;
        } else {
-               DEV_MESSAGE(KERN_INFO, device,
-                           "(%ld B/blk): %ldkB",
-                           (unsigned long) block->bp_block,
-                           (unsigned long) (block->blocks <<
-                               block->s2b_shift) >> 1);
+               dev_info(&device->cdev->dev,
+                        "New DASD with %ld byte/block, total size %ld KB\n",
+                        (unsigned long) block->bp_block,
+                        (unsigned long) (block->blocks <<
+                                         block->s2b_shift) >> 1);
        }
 out_label:
        free_page((long) label);
@@ -595,7 +595,7 @@ static void
 dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                     struct irb *stat)
 {
-       DEV_MESSAGE(KERN_ERR, device, "%s",
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                    "dump sense not available for DIAG data");
 }
 
@@ -621,10 +621,8 @@ static int __init
 dasd_diag_init(void)
 {
        if (!MACHINE_IS_VM) {
-               MESSAGE_LOG(KERN_INFO,
-                           "Machine is not VM: %s "
-                           "discipline not initializing",
-                           dasd_diag_discipline.name);
+               pr_info("Discipline %s cannot be used without z/VM\n",
+                       dasd_diag_discipline.name);
                return -ENODEV;
        }
        ASCEBC(dasd_diag_discipline.ebcname, 4);
index bdb87998f364f276067470e672a0db49bfc21e26..21254793c60416e9f2162e7e962f5741b07d39b3 100644 (file)
@@ -11,6 +11,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/cio.h>
 #include <asm/ccwdev.h>
+#include <asm/itcw.h>
 
 #include "dasd_int.h"
 #include "dasd_eckd.h"
+#include "../cio/chsc.h"
+
 
 #ifdef PRINTK_HEADER
 #undef PRINTK_HEADER
@@ -84,7 +89,7 @@ dasd_eckd_probe (struct ccw_device *cdev)
        /* set ECKD specific ccw-device options */
        ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE);
        if (ret) {
-               printk(KERN_WARNING
+               DBF_EVENT(DBF_WARNING,
                       "dasd_eckd_probe: could not set ccw-device options "
                       "for %s\n", dev_name(&cdev->dev));
                return ret;
@@ -159,6 +164,14 @@ recs_per_track(struct dasd_eckd_characteristics * rdc,
        return 0;
 }
 
+static void set_ch_t(struct ch_t *geo, __u32 cyl, __u8 head)
+{
+       geo->cyl = (__u16) cyl;
+       geo->head = cyl >> 16;
+       geo->head <<= 4;
+       geo->head |= head;
+}
+
 static int
 check_XRC (struct ccw1         *de_ccw,
            struct DE_eckd_data *data,
@@ -186,11 +199,12 @@ check_XRC (struct ccw1         *de_ccw,
 }
 
 static int
-define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
-             int totrk, int cmd, struct dasd_device * device)
+define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk,
+             unsigned int totrk, int cmd, struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
-       struct ch_t geo, beg, end;
+       u32 begcyl, endcyl;
+       u16 heads, beghead, endhead;
        int rc = 0;
 
        private = (struct dasd_eckd_private *) device->private;
@@ -236,7 +250,8 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
                rc = check_XRC (ccw, data, device);
                break;
        default:
-               DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
+               dev_err(&device->cdev->dev,
+                       "0x%x is not a known command\n", cmd);
                break;
        }
 
@@ -248,27 +263,24 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
            && !(private->uses_cdl && trk < 2))
                data->ga_extended |= 0x40; /* Regular Data Format Mode */
 
-       geo.cyl = private->rdc_data.no_cyl;
-       geo.head = private->rdc_data.trk_per_cyl;
-       beg.cyl = trk / geo.head;
-       beg.head = trk % geo.head;
-       end.cyl = totrk / geo.head;
-       end.head = totrk % geo.head;
+       heads = private->rdc_data.trk_per_cyl;
+       begcyl = trk / heads;
+       beghead = trk % heads;
+       endcyl = totrk / heads;
+       endhead = totrk % heads;
 
        /* check for sequential prestage - enhance cylinder range */
        if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
            data->attributes.operation == DASD_SEQ_ACCESS) {
 
-               if (end.cyl + private->attrib.nr_cyl < geo.cyl)
-                       end.cyl += private->attrib.nr_cyl;
+               if (endcyl + private->attrib.nr_cyl < private->real_cyl)
+                       endcyl += private->attrib.nr_cyl;
                else
-                       end.cyl = (geo.cyl - 1);
+                       endcyl = (private->real_cyl - 1);
        }
 
-       data->beg_ext.cyl = beg.cyl;
-       data->beg_ext.head = beg.head;
-       data->end_ext.cyl = end.cyl;
-       data->end_ext.head = end.head;
+       set_ch_t(&data->beg_ext, begcyl, beghead);
+       set_ch_t(&data->end_ext, endcyl, endhead);
        return rc;
 }
 
@@ -283,29 +295,145 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata,
                return 0;
 
        /* switch on System Time Stamp - needed for XRC Support */
-       pfxdata->define_extend.ga_extended |= 0x08; /* 'Time Stamp Valid'   */
-       pfxdata->define_extend.ga_extended |= 0x02; /* 'Extended Parameter' */
+       pfxdata->define_extent.ga_extended |= 0x08; /* 'Time Stamp Valid'   */
+       pfxdata->define_extent.ga_extended |= 0x02; /* 'Extended Parameter' */
        pfxdata->validity.time_stamp = 1;           /* 'Time Stamp Valid'   */
 
-       rc = get_sync_clock(&pfxdata->define_extend.ep_sys_time);
+       rc = get_sync_clock(&pfxdata->define_extent.ep_sys_time);
        /* Ignore return code if sync clock is switched off. */
        if (rc == -ENOSYS || rc == -EACCES)
                rc = 0;
        return rc;
 }
 
-static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
-                 int totrk, int cmd, struct dasd_device *basedev,
-                 struct dasd_device *startdev)
+static void fill_LRE_data(struct LRE_eckd_data *data, unsigned int trk,
+                         unsigned int rec_on_trk, int count, int cmd,
+                         struct dasd_device *device, unsigned int reclen,
+                         unsigned int tlf)
+{
+       struct dasd_eckd_private *private;
+       int sector;
+       int dn, d;
+
+       private = (struct dasd_eckd_private *) device->private;
+
+       memset(data, 0, sizeof(*data));
+       sector = 0;
+       if (rec_on_trk) {
+               switch (private->rdc_data.dev_type) {
+               case 0x3390:
+                       dn = ceil_quot(reclen + 6, 232);
+                       d = 9 + ceil_quot(reclen + 6 * (dn + 1), 34);
+                       sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
+                       break;
+               case 0x3380:
+                       d = 7 + ceil_quot(reclen + 12, 32);
+                       sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
+                       break;
+               }
+       }
+       data->sector = sector;
+       /* note: meaning of count depends on the operation
+        *       for record based I/O it's the number of records, but for
+        *       track based I/O it's the number of tracks
+        */
+       data->count = count;
+       switch (cmd) {
+       case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
+               data->operation.orientation = 0x3;
+               data->operation.operation = 0x03;
+               break;
+       case DASD_ECKD_CCW_READ_HOME_ADDRESS:
+               data->operation.orientation = 0x3;
+               data->operation.operation = 0x16;
+               break;
+       case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
+               data->operation.orientation = 0x1;
+               data->operation.operation = 0x03;
+               data->count++;
+               break;
+       case DASD_ECKD_CCW_READ_RECORD_ZERO:
+               data->operation.orientation = 0x3;
+               data->operation.operation = 0x16;
+               data->count++;
+               break;
+       case DASD_ECKD_CCW_WRITE:
+       case DASD_ECKD_CCW_WRITE_MT:
+       case DASD_ECKD_CCW_WRITE_KD:
+       case DASD_ECKD_CCW_WRITE_KD_MT:
+               data->auxiliary.length_valid = 0x1;
+               data->length = reclen;
+               data->operation.operation = 0x01;
+               break;
+       case DASD_ECKD_CCW_WRITE_CKD:
+       case DASD_ECKD_CCW_WRITE_CKD_MT:
+               data->auxiliary.length_valid = 0x1;
+               data->length = reclen;
+               data->operation.operation = 0x03;
+               break;
+       case DASD_ECKD_CCW_WRITE_TRACK_DATA:
+               data->auxiliary.length_valid = 0x1;
+               data->length = reclen;  /* not tlf, as one might think */
+               data->operation.operation = 0x3F;
+               data->extended_operation = 0x23;
+               break;
+       case DASD_ECKD_CCW_READ:
+       case DASD_ECKD_CCW_READ_MT:
+       case DASD_ECKD_CCW_READ_KD:
+       case DASD_ECKD_CCW_READ_KD_MT:
+               data->auxiliary.length_valid = 0x1;
+               data->length = reclen;
+               data->operation.operation = 0x06;
+               break;
+       case DASD_ECKD_CCW_READ_CKD:
+       case DASD_ECKD_CCW_READ_CKD_MT:
+               data->auxiliary.length_valid = 0x1;
+               data->length = reclen;
+               data->operation.operation = 0x16;
+               break;
+       case DASD_ECKD_CCW_READ_COUNT:
+               data->operation.operation = 0x06;
+               break;
+       case DASD_ECKD_CCW_READ_TRACK_DATA:
+               data->auxiliary.length_valid = 0x1;
+               data->length = tlf;
+               data->operation.operation = 0x0C;
+               break;
+       case DASD_ECKD_CCW_ERASE:
+               data->length = reclen;
+               data->auxiliary.length_valid = 0x1;
+               data->operation.operation = 0x0b;
+               break;
+       default:
+               DBF_DEV_EVENT(DBF_ERR, device,
+                           "fill LRE unknown opcode 0x%x", cmd);
+               BUG();
+       }
+       set_ch_t(&data->seek_addr,
+                trk / private->rdc_data.trk_per_cyl,
+                trk % private->rdc_data.trk_per_cyl);
+       data->search_arg.cyl = data->seek_addr.cyl;
+       data->search_arg.head = data->seek_addr.head;
+       data->search_arg.record = rec_on_trk;
+}
+
+static int prefix_LRE(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata,
+                     unsigned int trk, unsigned int totrk, int cmd,
+                     struct dasd_device *basedev, struct dasd_device *startdev,
+                     unsigned char format, unsigned int rec_on_trk, int count,
+                     unsigned int blksize, unsigned int tlf)
 {
        struct dasd_eckd_private *basepriv, *startpriv;
-       struct DE_eckd_data *data;
-       struct ch_t geo, beg, end;
+       struct DE_eckd_data *dedata;
+       struct LRE_eckd_data *lredata;
+       u32 begcyl, endcyl;
+       u16 heads, beghead, endhead;
        int rc = 0;
 
        basepriv = (struct dasd_eckd_private *) basedev->private;
        startpriv = (struct dasd_eckd_private *) startdev->private;
-       data = &pfxdata->define_extend;
+       dedata = &pfxdata->define_extent;
+       lredata = &pfxdata->locate_record;
 
        ccw->cmd_code = DASD_ECKD_CCW_PFX;
        ccw->flags = 0;
@@ -314,10 +442,16 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
 
        memset(pfxdata, 0, sizeof(*pfxdata));
        /* prefix data */
-       pfxdata->format = 0;
+       if (format > 1) {
+               DBF_DEV_EVENT(DBF_ERR, basedev,
+                             "PFX LRE unknown format 0x%x", format);
+               BUG();
+               return -EINVAL;
+       }
+       pfxdata->format = format;
        pfxdata->base_address = basepriv->ned->unit_addr;
        pfxdata->base_lss = basepriv->ned->ID;
-       pfxdata->validity.define_extend = 1;
+       pfxdata->validity.define_extent = 1;
 
        /* private uid is kept up to date, conf_data may be outdated */
        if (startpriv->uid.type != UA_BASE_DEVICE) {
@@ -337,70 +471,94 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk,
        case DASD_ECKD_CCW_READ_KD:
        case DASD_ECKD_CCW_READ_KD_MT:
        case DASD_ECKD_CCW_READ_COUNT:
-               data->mask.perm = 0x1;
-               data->attributes.operation = basepriv->attrib.operation;
+               dedata->mask.perm = 0x1;
+               dedata->attributes.operation = basepriv->attrib.operation;
+               break;
+       case DASD_ECKD_CCW_READ_TRACK_DATA:
+               dedata->mask.perm = 0x1;
+               dedata->attributes.operation = basepriv->attrib.operation;
+               dedata->blk_size = 0;
                break;
        case DASD_ECKD_CCW_WRITE:
        case DASD_ECKD_CCW_WRITE_MT:
        case DASD_ECKD_CCW_WRITE_KD:
        case DASD_ECKD_CCW_WRITE_KD_MT:
-               data->mask.perm = 0x02;
-               data->attributes.operation = basepriv->attrib.operation;
+               dedata->mask.perm = 0x02;
+               dedata->attributes.operation = basepriv->attrib.operation;
                rc = check_XRC_on_prefix(pfxdata, basedev);
                break;
        case DASD_ECKD_CCW_WRITE_CKD:
        case DASD_ECKD_CCW_WRITE_CKD_MT:
-               data->attributes.operation = DASD_BYPASS_CACHE;
+               dedata->attributes.operation = DASD_BYPASS_CACHE;
                rc = check_XRC_on_prefix(pfxdata, basedev);
                break;
        case DASD_ECKD_CCW_ERASE:
        case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
        case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
-               data->mask.perm = 0x3;
-               data->mask.auth = 0x1;
-               data->attributes.operation = DASD_BYPASS_CACHE;
+               dedata->mask.perm = 0x3;
+               dedata->mask.auth = 0x1;
+               dedata->attributes.operation = DASD_BYPASS_CACHE;
                rc = check_XRC_on_prefix(pfxdata, basedev);
                break;
-       default:
-               DEV_MESSAGE(KERN_ERR, basedev, "unknown opcode 0x%x", cmd);
+       case DASD_ECKD_CCW_WRITE_TRACK_DATA:
+               dedata->mask.perm = 0x02;
+               dedata->attributes.operation = basepriv->attrib.operation;
+               dedata->blk_size = blksize;
+               rc = check_XRC_on_prefix(pfxdata, basedev);
                break;
+       default:
+               DBF_DEV_EVENT(DBF_ERR, basedev,
+                           "PFX LRE unknown opcode 0x%x", cmd);
+               BUG();
+               return -EINVAL;
        }
 
-       data->attributes.mode = 0x3;    /* ECKD */
+       dedata->attributes.mode = 0x3;  /* ECKD */
 
        if ((basepriv->rdc_data.cu_type == 0x2105 ||
             basepriv->rdc_data.cu_type == 0x2107 ||
             basepriv->rdc_data.cu_type == 0x1750)
            && !(basepriv->uses_cdl && trk < 2))
-               data->ga_extended |= 0x40; /* Regular Data Format Mode */
+               dedata->ga_extended |= 0x40; /* Regular Data Format Mode */
 
-       geo.cyl = basepriv->rdc_data.no_cyl;
-       geo.head = basepriv->rdc_data.trk_per_cyl;
-       beg.cyl = trk / geo.head;
-       beg.head = trk % geo.head;
-       end.cyl = totrk / geo.head;
-       end.head = totrk % geo.head;
+       heads = basepriv->rdc_data.trk_per_cyl;
+       begcyl = trk / heads;
+       beghead = trk % heads;
+       endcyl = totrk / heads;
+       endhead = totrk % heads;
 
        /* check for sequential prestage - enhance cylinder range */
-       if (data->attributes.operation == DASD_SEQ_PRESTAGE ||
-           data->attributes.operation == DASD_SEQ_ACCESS) {
+       if (dedata->attributes.operation == DASD_SEQ_PRESTAGE ||
+           dedata->attributes.operation == DASD_SEQ_ACCESS) {
 
-               if (end.cyl + basepriv->attrib.nr_cyl < geo.cyl)
-                       end.cyl += basepriv->attrib.nr_cyl;
+               if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl)
+                       endcyl += basepriv->attrib.nr_cyl;
                else
-                       end.cyl = (geo.cyl - 1);
+                       endcyl = (basepriv->real_cyl - 1);
+       }
+
+       set_ch_t(&dedata->beg_ext, begcyl, beghead);
+       set_ch_t(&dedata->end_ext, endcyl, endhead);
+
+       if (format == 1) {
+               fill_LRE_data(lredata, trk, rec_on_trk, count, cmd,
+                             basedev, blksize, tlf);
        }
 
-       data->beg_ext.cyl = beg.cyl;
-       data->beg_ext.head = beg.head;
-       data->end_ext.cyl = end.cyl;
-       data->end_ext.head = end.head;
        return rc;
 }
 
+static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata,
+                 unsigned int trk, unsigned int totrk, int cmd,
+                 struct dasd_device *basedev, struct dasd_device *startdev)
+{
+       return prefix_LRE(ccw, pfxdata, trk, totrk, cmd, basedev, startdev,
+                         0, 0, 0, 0, 0);
+}
+
 static void
-locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
-             int rec_on_trk, int no_rec, int cmd,
+locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk,
+             unsigned int rec_on_trk, int no_rec, int cmd,
              struct dasd_device * device, int reclen)
 {
        struct dasd_eckd_private *private;
@@ -491,12 +649,14 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
                data->operation.operation = 0x0b;
                break;
        default:
-               DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
-       }
-       data->seek_addr.cyl = data->search_arg.cyl =
-               trk / private->rdc_data.trk_per_cyl;
-       data->seek_addr.head = data->search_arg.head =
-               trk % private->rdc_data.trk_per_cyl;
+               DBF_DEV_EVENT(DBF_ERR, device, "unknown locate record "
+                             "opcode 0x%x", cmd);
+       }
+       set_ch_t(&data->seek_addr,
+                trk / private->rdc_data.trk_per_cyl,
+                trk % private->rdc_data.trk_per_cyl);
+       data->search_arg.cyl = data->seek_addr.cyl;
+       data->search_arg.head = data->seek_addr.head;
        data->search_arg.record = rec_on_trk;
 }
 
@@ -585,8 +745,8 @@ static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
        cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
 
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                           "Could not allocate RCD request");
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                             "Could not allocate RCD request");
                return cqr;
        }
 
@@ -736,14 +896,16 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
                        rc = dasd_eckd_read_conf_lpm(device, &conf_data,
                                                     &conf_len, lpm);
                        if (rc && rc != -EOPNOTSUPP) {  /* -EOPNOTSUPP is ok */
-                               MESSAGE(KERN_WARNING,
-                                       "Read configuration data returned "
-                                       "error %d", rc);
+                               DBF_EVENT(DBF_WARNING,
+                                         "Read configuration data returned "
+                                         "error %d for device: %s", rc,
+                                         dev_name(&device->cdev->dev));
                                return rc;
                        }
                        if (conf_data == NULL) {
-                               MESSAGE(KERN_WARNING, "%s", "No configuration "
-                                       "data retrieved");
+                               DBF_EVENT(DBF_WARNING, "No configuration "
+                                         "data retrieved for device: %s",
+                                         dev_name(&device->cdev->dev));
                                continue;       /* no error */
                        }
                        /* save first valid configuration data */
@@ -790,8 +952,9 @@ static int dasd_eckd_read_features(struct dasd_device *device)
                                    sizeof(struct dasd_rssd_features)),
                                   device);
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                           "Could not allocate initialization request");
+               DBF_EVENT(DBF_WARNING, "Could not allocate initialization "
+                         "request for device: %s",
+                         dev_name(&device->cdev->dev));
                return PTR_ERR(cqr);
        }
        cqr->startdev = device;
@@ -840,7 +1003,8 @@ static int dasd_eckd_read_features(struct dasd_device *device)
 /*
  * Build CP for Perform Subsystem Function - SSC.
  */
-static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device)
+static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,
+                                                   int enable_pav)
 {
        struct dasd_ccw_req *cqr;
        struct dasd_psf_ssc_data *psf_ssc_data;
@@ -851,15 +1015,17 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device)
                                  device);
 
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                           "Could not allocate PSF-SSC request");
                return cqr;
        }
        psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data;
        psf_ssc_data->order = PSF_ORDER_SSC;
-       psf_ssc_data->suborder = 0x88;
-       psf_ssc_data->reserved[0] = 0x88;
-
+       psf_ssc_data->suborder = 0x40;
+       if (enable_pav) {
+               psf_ssc_data->suborder |= 0x88;
+               psf_ssc_data->reserved[0] = 0x88;
+       }
        ccw = cqr->cpaddr;
        ccw->cmd_code = DASD_ECKD_CCW_PSF;
        ccw->cda = (__u32)(addr_t)psf_ssc_data;
@@ -880,12 +1046,12 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device)
  * call might change behaviour of DASD devices.
  */
 static int
-dasd_eckd_psf_ssc(struct dasd_device *device)
+dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
 {
        struct dasd_ccw_req *cqr;
        int rc;
 
-       cqr = dasd_eckd_build_psf_ssc(device);
+       cqr = dasd_eckd_build_psf_ssc(device, enable_pav);
        if (IS_ERR(cqr))
                return PTR_ERR(cqr);
 
@@ -904,19 +1070,20 @@ static int dasd_eckd_validate_server(struct dasd_device *device)
 {
        int rc;
        struct dasd_eckd_private *private;
+       int enable_pav;
 
-       /* Currently PAV is the only reason to 'validate' server on LPAR */
        if (dasd_nopav || MACHINE_IS_VM)
-               return 0;
-
-       rc = dasd_eckd_psf_ssc(device);
+               enable_pav = 0;
+       else
+               enable_pav = 1;
+       rc = dasd_eckd_psf_ssc(device, enable_pav);
        /* may be requested feature is not available on server,
         * therefore just report error and go ahead */
        private = (struct dasd_eckd_private *) device->private;
-       DEV_MESSAGE(KERN_INFO, device,
-                   "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d",
-                   private->uid.vendor, private->uid.serial,
-                   private->uid.ssid, rc);
+       DBF_EVENT(DBF_WARNING, "PSF-SSC on storage subsystem %s.%s.%04x "
+                 "returned rc=%d for device: %s",
+                 private->uid.vendor, private->uid.serial,
+                 private->uid.ssid, rc, dev_name(&device->cdev->dev));
        /* RE-Read Configuration Data */
        return dasd_eckd_read_conf(device);
 }
@@ -938,9 +1105,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                private = kzalloc(sizeof(struct dasd_eckd_private),
                                  GFP_KERNEL | GFP_DMA);
                if (private == NULL) {
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "memory allocation failed for private "
-                                   "data");
+                       dev_warn(&device->cdev->dev,
+                                "Allocating memory for private DASD data "
+                                "failed\n");
                        return -ENOMEM;
                }
                device->private = (void *) private;
@@ -965,8 +1132,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        if (private->uid.type == UA_BASE_DEVICE) {
                block = dasd_alloc_block();
                if (IS_ERR(block)) {
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "could not allocate dasd block structure");
+                       DBF_EVENT(DBF_WARNING, "could not allocate dasd "
+                                 "block structure for device: %s",
+                                 dev_name(&device->cdev->dev));
                        rc = PTR_ERR(block);
                        goto out_err1;
                }
@@ -997,20 +1165,27 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        memset(rdc_data, 0, sizeof(rdc_data));
        rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
        if (rc) {
-               DEV_MESSAGE(KERN_WARNING, device,
-                           "Read device characteristics returned "
-                           "rc=%d", rc);
+               DBF_EVENT(DBF_WARNING,
+                         "Read device characteristics failed, rc=%d for "
+                         "device: %s", rc, dev_name(&device->cdev->dev));
                goto out_err3;
        }
-       DEV_MESSAGE(KERN_INFO, device,
-                   "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d",
-                   private->rdc_data.dev_type,
-                   private->rdc_data.dev_model,
-                   private->rdc_data.cu_type,
-                   private->rdc_data.cu_model.model,
-                   private->rdc_data.no_cyl,
-                   private->rdc_data.trk_per_cyl,
-                   private->rdc_data.sec_per_trk);
+       /* find the vaild cylinder size */
+       if (private->rdc_data.no_cyl == LV_COMPAT_CYL &&
+           private->rdc_data.long_no_cyl)
+               private->real_cyl = private->rdc_data.long_no_cyl;
+       else
+               private->real_cyl = private->rdc_data.no_cyl;
+
+       dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) "
+                "with %d cylinders, %d heads, %d sectors\n",
+                private->rdc_data.dev_type,
+                private->rdc_data.dev_model,
+                private->rdc_data.cu_type,
+                private->rdc_data.cu_model.model,
+                   private->real_cyl,
+                private->rdc_data.trk_per_cyl,
+                private->rdc_data.sec_per_trk);
        return 0;
 
 out_err3:
@@ -1151,14 +1326,12 @@ dasd_eckd_end_analysis(struct dasd_block *block)
        status = private->init_cqr_status;
        private->init_cqr_status = -1;
        if (status != DASD_CQR_DONE) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                           "volume analysis returned unformatted disk");
+               dev_warn(&device->cdev->dev,
+                           "The DASD is not formatted\n");
                return -EMEDIUMTYPE;
        }
 
        private->uses_cdl = 1;
-       /* Calculate number of blocks/records per track. */
-       blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
        /* Check Track 0 for Compatible Disk Layout */
        count_area = NULL;
        for (i = 0; i < 3; i++) {
@@ -1182,8 +1355,8 @@ dasd_eckd_end_analysis(struct dasd_block *block)
                        count_area = &private->count_area[0];
        } else {
                if (private->count_area[3].record == 1)
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "Trk 0: no records after VTOC!");
+                       dev_warn(&device->cdev->dev,
+                                "Track 0 has no records following the VTOC\n");
        }
        if (count_area != NULL && count_area->kl == 0) {
                /* we found notthing violating our disk layout */
@@ -1191,8 +1364,8 @@ dasd_eckd_end_analysis(struct dasd_block *block)
                        block->bp_block = count_area->dl;
        }
        if (block->bp_block == 0) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                           "Volume has incompatible disk layout");
+               dev_warn(&device->cdev->dev,
+                        "The disk layout of the DASD is not supported\n");
                return -EMEDIUMTYPE;
        }
        block->s2b_shift = 0;   /* bits to shift 512 to get a block */
@@ -1200,19 +1373,19 @@ dasd_eckd_end_analysis(struct dasd_block *block)
                block->s2b_shift++;
 
        blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block);
-       block->blocks = (private->rdc_data.no_cyl *
+       block->blocks = (private->real_cyl *
                          private->rdc_data.trk_per_cyl *
                          blk_per_trk);
 
-       DEV_MESSAGE(KERN_INFO, device,
-                   "(%dkB blks): %dkB at %dkB/trk %s",
-                   (block->bp_block >> 10),
-                   ((private->rdc_data.no_cyl *
-                     private->rdc_data.trk_per_cyl *
-                     blk_per_trk * (block->bp_block >> 9)) >> 1),
-                   ((blk_per_trk * block->bp_block) >> 10),
-                   private->uses_cdl ?
-                   "compatible disk layout" : "linux disk layout");
+       dev_info(&device->cdev->dev,
+                "DASD with %d KB/block, %d KB total size, %d KB/track, "
+                "%s\n", (block->bp_block >> 10),
+                ((private->real_cyl *
+                  private->rdc_data.trk_per_cyl *
+                  blk_per_trk * (block->bp_block >> 9)) >> 1),
+                ((blk_per_trk * block->bp_block) >> 10),
+                private->uses_cdl ?
+                "compatible disk layout" : "linux disk layout");
 
        return 0;
 }
@@ -1262,31 +1435,35 @@ dasd_eckd_format_device(struct dasd_device * device,
        struct eckd_count *ect;
        struct ccw1 *ccw;
        void *data;
-       int rpt, cyl, head;
+       int rpt;
+       struct ch_t address;
        int cplength, datasize;
        int i;
+       int intensity = 0;
+       int r0_perm;
 
        private = (struct dasd_eckd_private *) device->private;
        rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
-       cyl = fdata->start_unit / private->rdc_data.trk_per_cyl;
-       head = fdata->start_unit % private->rdc_data.trk_per_cyl;
+       set_ch_t(&address,
+                fdata->start_unit / private->rdc_data.trk_per_cyl,
+                fdata->start_unit % private->rdc_data.trk_per_cyl);
 
        /* Sanity checks. */
        if (fdata->start_unit >=
-           (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) {
-               DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!",
-                           fdata->start_unit);
+           (private->real_cyl * private->rdc_data.trk_per_cyl)) {
+               dev_warn(&device->cdev->dev, "Start track number %d used in "
+                        "formatting is too big\n", fdata->start_unit);
                return ERR_PTR(-EINVAL);
        }
        if (fdata->start_unit > fdata->stop_unit) {
-               DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.",
-                           fdata->start_unit);
+               dev_warn(&device->cdev->dev, "Start track %d used in "
+                        "formatting exceeds end track\n", fdata->start_unit);
                return ERR_PTR(-EINVAL);
        }
        if (dasd_check_blocksize(fdata->blksize) != 0) {
-               DEV_MESSAGE(KERN_WARNING, device,
-                           "Invalid blocksize %d...terminating!",
-                           fdata->blksize);
+               dev_warn(&device->cdev->dev,
+                        "The DASD cannot be formatted with block size %d\n",
+                        fdata->blksize);
                return ERR_PTR(-EINVAL);
        }
 
@@ -1296,9 +1473,17 @@ dasd_eckd_format_device(struct dasd_device * device,
         *   Bit 1: write home address, currently not supported
         *   Bit 2: invalidate tracks
         *   Bit 3: use OS/390 compatible disk layout (cdl)
+        *   Bit 4: do not allow storage subsystem to modify record zero
         * Only some bit combinations do make sense.
         */
-       switch (fdata->intensity) {
+       if (fdata->intensity & 0x10) {
+               r0_perm = 0;
+               intensity = fdata->intensity & ~0x10;
+       } else {
+               r0_perm = 1;
+               intensity = fdata->intensity;
+       }
+       switch (intensity) {
        case 0x00:      /* Normal format */
        case 0x08:      /* Normal format, use cdl. */
                cplength = 2 + rpt;
@@ -1322,8 +1507,8 @@ dasd_eckd_format_device(struct dasd_device * device,
                        sizeof(struct eckd_count);
                break;
        default:
-               DEV_MESSAGE(KERN_WARNING, device, "Invalid flags 0x%x.",
-                           fdata->intensity);
+               dev_warn(&device->cdev->dev, "An I/O control call used "
+                        "incorrect flags 0x%x\n", fdata->intensity);
                return ERR_PTR(-EINVAL);
        }
        /* Allocate the format ccw request. */
@@ -1335,11 +1520,14 @@ dasd_eckd_format_device(struct dasd_device * device,
        data = fcp->data;
        ccw = fcp->cpaddr;
 
-       switch (fdata->intensity & ~0x08) {
+       switch (intensity & ~0x08) {
        case 0x00: /* Normal format. */
                define_extent(ccw++, (struct DE_eckd_data *) data,
                              fdata->start_unit, fdata->start_unit,
                              DASD_ECKD_CCW_WRITE_CKD, device);
+               /* grant subsystem permission to format R0 */
+               if (r0_perm)
+                       ((struct DE_eckd_data *)data)->ga_extended |= 0x04;
                data += sizeof(struct DE_eckd_data);
                ccw[-1].flags |= CCW_FLAG_CC;
                locate_record(ccw++, (struct LO_eckd_data *) data,
@@ -1373,11 +1561,11 @@ dasd_eckd_format_device(struct dasd_device * device,
                data += sizeof(struct LO_eckd_data);
                break;
        }
-       if (fdata->intensity & 0x01) {  /* write record zero */
+       if (intensity & 0x01) { /* write record zero */
                ect = (struct eckd_count *) data;
                data += sizeof(struct eckd_count);
-               ect->cyl = cyl;
-               ect->head = head;
+               ect->cyl = address.cyl;
+               ect->head = address.head;
                ect->record = 0;
                ect->kl = 0;
                ect->dl = 8;
@@ -1388,11 +1576,11 @@ dasd_eckd_format_device(struct dasd_device * device,
                ccw->cda = (__u32)(addr_t) ect;
                ccw++;
        }
-       if ((fdata->intensity & ~0x08) & 0x04) {        /* erase track */
+       if ((intensity & ~0x08) & 0x04) {       /* erase track */
                ect = (struct eckd_count *) data;
                data += sizeof(struct eckd_count);
-               ect->cyl = cyl;
-               ect->head = head;
+               ect->cyl = address.cyl;
+               ect->head = address.head;
                ect->record = 1;
                ect->kl = 0;
                ect->dl = 0;
@@ -1405,20 +1593,20 @@ dasd_eckd_format_device(struct dasd_device * device,
                for (i = 0; i < rpt; i++) {
                        ect = (struct eckd_count *) data;
                        data += sizeof(struct eckd_count);
-                       ect->cyl = cyl;
-                       ect->head = head;
+                       ect->cyl = address.cyl;
+                       ect->head = address.head;
                        ect->record = i + 1;
                        ect->kl = 0;
                        ect->dl = fdata->blksize;
                        /* Check for special tracks 0-1 when formatting CDL */
-                       if ((fdata->intensity & 0x08) &&
+                       if ((intensity & 0x08) &&
                            fdata->start_unit == 0) {
                                if (i < 3) {
                                        ect->kl = 4;
                                        ect->dl = sizes_trk0[i] - 4;
                                }
                        }
-                       if ((fdata->intensity & 0x08) &&
+                       if ((intensity & 0x08) &&
                            fdata->start_unit == 1) {
                                ect->kl = 44;
                                ect->dl = LABEL_SIZE - 44;
@@ -1479,57 +1667,69 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
                                                   struct irb *irb)
 {
        char mask;
+       char *sense = NULL;
 
        /* first of all check for state change pending interrupt */
        mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
-       if ((irb->scsw.cmd.dstat & mask) == mask) {
+       if ((scsw_dstat(&irb->scsw) & mask) == mask) {
                dasd_generic_handle_state_change(device);
                return;
        }
 
        /* summary unit check */
-       if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
+       if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
            (irb->ecw[7] == 0x0D)) {
                dasd_alias_handle_summary_unit_check(device, irb);
                return;
        }
 
-
+       sense = dasd_get_sense(irb);
        /* service information message SIM */
-       if (irb->esw.esw0.erw.cons && !(irb->ecw[27] & DASD_SENSE_BIT_0) &&
-           ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) {
-               dasd_3990_erp_handle_sim(device, irb->ecw);
+       if (sense && !(sense[27] & DASD_SENSE_BIT_0) &&
+           ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) {
+               dasd_3990_erp_handle_sim(device, sense);
                dasd_schedule_device_bh(device);
                return;
        }
 
-       if ((irb->scsw.cmd.cc == 1) &&
-           (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
-           (irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) &&
-           (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) {
+       if ((scsw_cc(&irb->scsw) == 1) &&
+           (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
+           (scsw_actl(&irb->scsw) & SCSW_ACTL_START_PEND) &&
+           (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND)) {
                /* fake irb do nothing, they are handled elsewhere */
                dasd_schedule_device_bh(device);
                return;
        }
 
-       if (!(irb->esw.esw0.erw.cons)) {
+       if (!sense) {
                /* just report other unsolicited interrupts */
-               DEV_MESSAGE(KERN_ERR, device, "%s",
+               DBF_DEV_EVENT(DBF_ERR, device, "%s",
                            "unsolicited interrupt received");
        } else {
-               DEV_MESSAGE(KERN_ERR, device, "%s",
+               DBF_DEV_EVENT(DBF_ERR, device, "%s",
                            "unsolicited interrupt received "
                            "(sense available)");
-               device->discipline->dump_sense(device, NULL, irb);
+               device->discipline->dump_sense_dbf(device, NULL, irb,
+                                                  "unsolicited");
        }
 
        dasd_schedule_device_bh(device);
        return;
 };
 
-static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
+
+static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
+                                              struct dasd_device *startdev,
                                               struct dasd_block *block,
-                                              struct request *req)
+                                              struct request *req,
+                                              sector_t first_rec,
+                                              sector_t last_rec,
+                                              sector_t first_trk,
+                                              sector_t last_trk,
+                                              unsigned int first_offs,
+                                              unsigned int last_offs,
+                                              unsigned int blk_per_trk,
+                                              unsigned int blksize)
 {
        struct dasd_eckd_private *private;
        unsigned long *idaws;
@@ -1539,11 +1739,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
        struct req_iterator iter;
        struct bio_vec *bv;
        char *dst;
-       unsigned int blksize, blk_per_trk, off;
+       unsigned int off;
        int count, cidaw, cplength, datasize;
-       sector_t recid, first_rec, last_rec;
-       sector_t first_trk, last_trk;
-       unsigned int first_offs, last_offs;
+       sector_t recid;
        unsigned char cmd, rcmd;
        int use_prefix;
        struct dasd_device *basedev;
@@ -1556,15 +1754,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
                cmd = DASD_ECKD_CCW_WRITE_MT;
        else
                return ERR_PTR(-EINVAL);
-       /* Calculate number of blocks/records per track. */
-       blksize = block->bp_block;
-       blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
-       /* Calculate record id of first and last block. */
-       first_rec = first_trk = req->sector >> block->s2b_shift;
-       first_offs = sector_div(first_trk, blk_per_trk);
-       last_rec = last_trk =
-               (req->sector + req->nr_sectors - 1) >> block->s2b_shift;
-       last_offs = sector_div(last_trk, blk_per_trk);
+
        /* Check struct bio and count the number of blocks for the request. */
        count = 0;
        cidaw = 0;
@@ -1714,6 +1904,497 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
        return cqr;
 }
 
+static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
+                                              struct dasd_device *startdev,
+                                              struct dasd_block *block,
+                                              struct request *req,
+                                              sector_t first_rec,
+                                              sector_t last_rec,
+                                              sector_t first_trk,
+                                              sector_t last_trk,
+                                              unsigned int first_offs,
+                                              unsigned int last_offs,
+                                              unsigned int blk_per_trk,
+                                              unsigned int blksize)
+{
+       struct dasd_eckd_private *private;
+       unsigned long *idaws;
+       struct dasd_ccw_req *cqr;
+       struct ccw1 *ccw;
+       struct req_iterator iter;
+       struct bio_vec *bv;
+       char *dst, *idaw_dst;
+       unsigned int cidaw, cplength, datasize;
+       unsigned int tlf;
+       sector_t recid;
+       unsigned char cmd;
+       struct dasd_device *basedev;
+       unsigned int trkcount, count, count_to_trk_end;
+       unsigned int idaw_len, seg_len, part_len, len_to_track_end;
+       unsigned char new_track, end_idaw;
+       sector_t trkid;
+       unsigned int recoffs;
+
+       basedev = block->base;
+       private = (struct dasd_eckd_private *) basedev->private;
+       if (rq_data_dir(req) == READ)
+               cmd = DASD_ECKD_CCW_READ_TRACK_DATA;
+       else if (rq_data_dir(req) == WRITE)
+               cmd = DASD_ECKD_CCW_WRITE_TRACK_DATA;
+       else
+               return ERR_PTR(-EINVAL);
+
+       /* Track based I/O needs IDAWs for each page, and not just for
+        * 64 bit addresses. We need additional idals for pages
+        * that get filled from two tracks, so we use the number
+        * of records as upper limit.
+        */
+       cidaw = last_rec - first_rec + 1;
+       trkcount = last_trk - first_trk + 1;
+
+       /* 1x prefix + one read/write ccw per track */
+       cplength = 1 + trkcount;
+
+       /* on 31-bit we need space for two 32 bit addresses per page
+        * on 64-bit one 64 bit address
+        */
+       datasize = sizeof(struct PFX_eckd_data) +
+               cidaw * sizeof(unsigned long long);
+
+       /* Allocate the ccw request. */
+       cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
+                                  cplength, datasize, startdev);
+       if (IS_ERR(cqr))
+               return cqr;
+       ccw = cqr->cpaddr;
+       /* transfer length factor: how many bytes to read from the last track */
+       if (first_trk == last_trk)
+               tlf = last_offs - first_offs + 1;
+       else
+               tlf = last_offs + 1;
+       tlf *= blksize;
+
+       if (prefix_LRE(ccw++, cqr->data, first_trk,
+                      last_trk, cmd, basedev, startdev,
+                      1 /* format */, first_offs + 1,
+                      trkcount, blksize,
+                      tlf) == -EAGAIN) {
+               /* Clock not in sync and XRC is enabled.
+                * Try again later.
+                */
+               dasd_sfree_request(cqr, startdev);
+               return ERR_PTR(-EAGAIN);
+       }
+
+       /*
+        * The translation of request into ccw programs must meet the
+        * following conditions:
+        * - all idaws but the first and the last must address full pages
+        *   (or 2K blocks on 31-bit)
+        * - the scope of a ccw and it's idal ends with the track boundaries
+        */
+       idaws = (unsigned long *) (cqr->data + sizeof(struct PFX_eckd_data));
+       recid = first_rec;
+       new_track = 1;
+       end_idaw = 0;
+       len_to_track_end = 0;
+       idaw_dst = 0;
+       idaw_len = 0;
+       rq_for_each_segment(bv, req, iter) {
+               dst = page_address(bv->bv_page) + bv->bv_offset;
+               seg_len = bv->bv_len;
+               while (seg_len) {
+                       if (new_track) {
+                               trkid = recid;
+                               recoffs = sector_div(trkid, blk_per_trk);
+                               count_to_trk_end = blk_per_trk - recoffs;
+                               count = min((last_rec - recid + 1),
+                                           (sector_t)count_to_trk_end);
+                               len_to_track_end = count * blksize;
+                               ccw[-1].flags |= CCW_FLAG_CC;
+                               ccw->cmd_code = cmd;
+                               ccw->count = len_to_track_end;
+                               ccw->cda = (__u32)(addr_t)idaws;
+                               ccw->flags = CCW_FLAG_IDA;
+                               ccw++;
+                               recid += count;
+                               new_track = 0;
+                       }
+                       /* If we start a new idaw, everything is fine and the
+                        * start of the new idaw is the start of this segment.
+                        * If we continue an idaw, we must make sure that the
+                        * current segment begins where the so far accumulated
+                        * idaw ends
+                        */
+                       if (!idaw_dst)
+                               idaw_dst = dst;
+                       if ((idaw_dst + idaw_len) != dst) {
+                               dasd_sfree_request(cqr, startdev);
+                               return ERR_PTR(-ERANGE);
+                       }
+                       part_len = min(seg_len, len_to_track_end);
+                       seg_len -= part_len;
+                       dst += part_len;
+                       idaw_len += part_len;
+                       len_to_track_end -= part_len;
+                       /* collected memory area ends on an IDA_BLOCK border,
+                        * -> create an idaw
+                        * idal_create_words will handle cases where idaw_len
+                        * is larger then IDA_BLOCK_SIZE
+                        */
+                       if (!(__pa(idaw_dst + idaw_len) & (IDA_BLOCK_SIZE-1)))
+                               end_idaw = 1;
+                       /* We also need to end the idaw at track end */
+                       if (!len_to_track_end) {
+                               new_track = 1;
+                               end_idaw = 1;
+                       }
+                       if (end_idaw) {
+                               idaws = idal_create_words(idaws, idaw_dst,
+                                                         idaw_len);
+                               idaw_dst = 0;
+                               idaw_len = 0;
+                               end_idaw = 0;
+                       }
+               }
+       }
+
+       if (blk_noretry_request(req) ||
+           block->base->features & DASD_FEATURE_FAILFAST)
+               set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+       cqr->startdev = startdev;
+       cqr->memdev = startdev;
+       cqr->block = block;
+       cqr->expires = 5 * 60 * HZ;     /* 5 minutes */
+       cqr->lpm = private->path_data.ppm;
+       cqr->retries = 256;
+       cqr->buildclk = get_clock();
+       cqr->status = DASD_CQR_FILLED;
+       return cqr;
+}
+
+static int prepare_itcw(struct itcw *itcw,
+                       unsigned int trk, unsigned int totrk, int cmd,
+                       struct dasd_device *basedev,
+                       struct dasd_device *startdev,
+                       unsigned int rec_on_trk, int count,
+                       unsigned int blksize,
+                       unsigned int total_data_size,
+                       unsigned int tlf,
+                       unsigned int blk_per_trk)
+{
+       struct PFX_eckd_data pfxdata;
+       struct dasd_eckd_private *basepriv, *startpriv;
+       struct DE_eckd_data *dedata;
+       struct LRE_eckd_data *lredata;
+       struct dcw *dcw;
+
+       u32 begcyl, endcyl;
+       u16 heads, beghead, endhead;
+       u8 pfx_cmd;
+
+       int rc = 0;
+       int sector = 0;
+       int dn, d;
+
+
+       /* setup prefix data */
+       basepriv = (struct dasd_eckd_private *) basedev->private;
+       startpriv = (struct dasd_eckd_private *) startdev->private;
+       dedata = &pfxdata.define_extent;
+       lredata = &pfxdata.locate_record;
+
+       memset(&pfxdata, 0, sizeof(pfxdata));
+       pfxdata.format = 1; /* PFX with LRE */
+       pfxdata.base_address = basepriv->ned->unit_addr;
+       pfxdata.base_lss = basepriv->ned->ID;
+       pfxdata.validity.define_extent = 1;
+
+       /* private uid is kept up to date, conf_data may be outdated */
+       if (startpriv->uid.type != UA_BASE_DEVICE) {
+               pfxdata.validity.verify_base = 1;
+               if (startpriv->uid.type == UA_HYPER_PAV_ALIAS)
+                       pfxdata.validity.hyper_pav = 1;
+       }
+
+       switch (cmd) {
+       case DASD_ECKD_CCW_READ_TRACK_DATA:
+               dedata->mask.perm = 0x1;
+               dedata->attributes.operation = basepriv->attrib.operation;
+               dedata->blk_size = blksize;
+               dedata->ga_extended |= 0x42;
+               lredata->operation.orientation = 0x0;
+               lredata->operation.operation = 0x0C;
+               lredata->auxiliary.check_bytes = 0x01;
+               pfx_cmd = DASD_ECKD_CCW_PFX_READ;
+               break;
+       case DASD_ECKD_CCW_WRITE_TRACK_DATA:
+               dedata->mask.perm = 0x02;
+               dedata->attributes.operation = basepriv->attrib.operation;
+               dedata->blk_size = blksize;
+               rc = check_XRC_on_prefix(&pfxdata, basedev);
+               dedata->ga_extended |= 0x42;
+               lredata->operation.orientation = 0x0;
+               lredata->operation.operation = 0x3F;
+               lredata->extended_operation = 0x23;
+               lredata->auxiliary.check_bytes = 0x2;
+               pfx_cmd = DASD_ECKD_CCW_PFX;
+               break;
+       default:
+               DBF_DEV_EVENT(DBF_ERR, basedev,
+                             "prepare itcw, unknown opcode 0x%x", cmd);
+               BUG();
+               break;
+       }
+       if (rc)
+               return rc;
+
+       dedata->attributes.mode = 0x3;  /* ECKD */
+
+       heads = basepriv->rdc_data.trk_per_cyl;
+       begcyl = trk / heads;
+       beghead = trk % heads;
+       endcyl = totrk / heads;
+       endhead = totrk % heads;
+
+       /* check for sequential prestage - enhance cylinder range */
+       if (dedata->attributes.operation == DASD_SEQ_PRESTAGE ||
+           dedata->attributes.operation == DASD_SEQ_ACCESS) {
+
+               if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl)
+                       endcyl += basepriv->attrib.nr_cyl;
+               else
+                       endcyl = (basepriv->real_cyl - 1);
+       }
+
+       set_ch_t(&dedata->beg_ext, begcyl, beghead);
+       set_ch_t(&dedata->end_ext, endcyl, endhead);
+
+       dedata->ep_format = 0x20; /* records per track is valid */
+       dedata->ep_rec_per_track = blk_per_trk;
+
+       if (rec_on_trk) {
+               switch (basepriv->rdc_data.dev_type) {
+               case 0x3390:
+                       dn = ceil_quot(blksize + 6, 232);
+                       d = 9 + ceil_quot(blksize + 6 * (dn + 1), 34);
+                       sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
+                       break;
+               case 0x3380:
+                       d = 7 + ceil_quot(blksize + 12, 32);
+                       sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
+                       break;
+               }
+       }
+
+       lredata->auxiliary.length_valid = 1;
+       lredata->auxiliary.length_scope = 1;
+       lredata->auxiliary.imbedded_ccw_valid = 1;
+       lredata->length = tlf;
+       lredata->imbedded_ccw = cmd;
+       lredata->count = count;
+       lredata->sector = sector;
+       set_ch_t(&lredata->seek_addr, begcyl, beghead);
+       lredata->search_arg.cyl = lredata->seek_addr.cyl;
+       lredata->search_arg.head = lredata->seek_addr.head;
+       lredata->search_arg.record = rec_on_trk;
+
+       dcw = itcw_add_dcw(itcw, pfx_cmd, 0,
+                    &pfxdata, sizeof(pfxdata), total_data_size);
+
+       return rc;
+}
+
+static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
+                                              struct dasd_device *startdev,
+                                              struct dasd_block *block,
+                                              struct request *req,
+                                              sector_t first_rec,
+                                              sector_t last_rec,
+                                              sector_t first_trk,
+                                              sector_t last_trk,
+                                              unsigned int first_offs,
+                                              unsigned int last_offs,
+                                              unsigned int blk_per_trk,
+                                              unsigned int blksize)
+{
+       struct dasd_eckd_private *private;
+       struct dasd_ccw_req *cqr;
+       struct req_iterator iter;
+       struct bio_vec *bv;
+       char *dst;
+       unsigned int trkcount, ctidaw;
+       unsigned char cmd;
+       struct dasd_device *basedev;
+       unsigned int tlf;
+       struct itcw *itcw;
+       struct tidaw *last_tidaw = NULL;
+       int itcw_op;
+       size_t itcw_size;
+
+       basedev = block->base;
+       private = (struct dasd_eckd_private *) basedev->private;
+       if (rq_data_dir(req) == READ) {
+               cmd = DASD_ECKD_CCW_READ_TRACK_DATA;
+               itcw_op = ITCW_OP_READ;
+       } else if (rq_data_dir(req) == WRITE) {
+               cmd = DASD_ECKD_CCW_WRITE_TRACK_DATA;
+               itcw_op = ITCW_OP_WRITE;
+       } else
+               return ERR_PTR(-EINVAL);
+
+       /* trackbased I/O needs address all memory via TIDAWs,
+        * not just for 64 bit addresses. This allows us to map
+        * each segment directly to one tidaw.
+        */
+       trkcount = last_trk - first_trk + 1;
+       ctidaw = 0;
+       rq_for_each_segment(bv, req, iter) {
+               ++ctidaw;
+       }
+
+       /* Allocate the ccw request. */
+       itcw_size = itcw_calc_size(0, ctidaw, 0);
+       cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
+                                  0, itcw_size, startdev);
+       if (IS_ERR(cqr))
+               return cqr;
+
+       cqr->cpmode = 1;
+       cqr->startdev = startdev;
+       cqr->memdev = startdev;
+       cqr->block = block;
+       cqr->expires = 100*HZ;
+       cqr->buildclk = get_clock();
+       cqr->status = DASD_CQR_FILLED;
+       cqr->retries = 10;
+
+       /* transfer length factor: how many bytes to read from the last track */
+       if (first_trk == last_trk)
+               tlf = last_offs - first_offs + 1;
+       else
+               tlf = last_offs + 1;
+       tlf *= blksize;
+
+       itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0);
+       cqr->cpaddr = itcw_get_tcw(itcw);
+
+       if (prepare_itcw(itcw, first_trk, last_trk,
+                        cmd, basedev, startdev,
+                        first_offs + 1,
+                        trkcount, blksize,
+                        (last_rec - first_rec + 1) * blksize,
+                        tlf, blk_per_trk) == -EAGAIN) {
+               /* Clock not in sync and XRC is enabled.
+                * Try again later.
+                */
+               dasd_sfree_request(cqr, startdev);
+               return ERR_PTR(-EAGAIN);
+       }
+
+       /*
+        * A tidaw can address 4k of memory, but must not cross page boundaries
+        * We can let the block layer handle this by setting
+        * blk_queue_segment_boundary to page boundaries and
+        * blk_max_segment_size to page size when setting up the request queue.
+        */
+       rq_for_each_segment(bv, req, iter) {
+               dst = page_address(bv->bv_page) + bv->bv_offset;
+               last_tidaw = itcw_add_tidaw(itcw, 0x00, dst, bv->bv_len);
+               if (IS_ERR(last_tidaw))
+                       return (struct dasd_ccw_req *)last_tidaw;
+       }
+
+       last_tidaw->flags |= 0x80;
+       itcw_finalize(itcw);
+
+       if (blk_noretry_request(req) ||
+           block->base->features & DASD_FEATURE_FAILFAST)
+               set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
+       cqr->startdev = startdev;
+       cqr->memdev = startdev;
+       cqr->block = block;
+       cqr->expires = 5 * 60 * HZ;     /* 5 minutes */
+       cqr->lpm = private->path_data.ppm;
+       cqr->retries = 256;
+       cqr->buildclk = get_clock();
+       cqr->status = DASD_CQR_FILLED;
+       return cqr;
+}
+
+static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
+                                              struct dasd_block *block,
+                                              struct request *req)
+{
+       int tpm, cmdrtd, cmdwtd;
+       int use_prefix;
+
+       struct dasd_eckd_private *private;
+       int fcx_in_css, fcx_in_gneq, fcx_in_features;
+       struct dasd_device *basedev;
+       sector_t first_rec, last_rec;
+       sector_t first_trk, last_trk;
+       unsigned int first_offs, last_offs;
+       unsigned int blk_per_trk, blksize;
+       int cdlspecial;
+       struct dasd_ccw_req *cqr;
+
+       basedev = block->base;
+       private = (struct dasd_eckd_private *) basedev->private;
+
+       /* Calculate number of blocks/records per track. */
+       blksize = block->bp_block;
+       blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
+       /* Calculate record id of first and last block. */
+       first_rec = first_trk = req->sector >> block->s2b_shift;
+       first_offs = sector_div(first_trk, blk_per_trk);
+       last_rec = last_trk =
+               (req->sector + req->nr_sectors - 1) >> block->s2b_shift;
+       last_offs = sector_div(last_trk, blk_per_trk);
+       cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk);
+
+       /* is transport mode supported ? */
+       fcx_in_css = css_general_characteristics.fcx;
+       fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
+       fcx_in_features = private->features.feature[40] & 0x80;
+       tpm = fcx_in_css && fcx_in_gneq && fcx_in_features;
+
+       /* is read track data and write track data in command mode supported? */
+       cmdrtd = private->features.feature[9] & 0x20;
+       cmdwtd = private->features.feature[12] & 0x40;
+       use_prefix = private->features.feature[8] & 0x01;
+
+       cqr = NULL;
+       if (cdlspecial || dasd_page_cache) {
+               /* do nothing, just fall through to the cmd mode single case */
+       } else if (!dasd_nofcx && tpm && (first_trk == last_trk)) {
+               cqr = dasd_eckd_build_cp_tpm_track(startdev, block, req,
+                                                   first_rec, last_rec,
+                                                   first_trk, last_trk,
+                                                   first_offs, last_offs,
+                                                   blk_per_trk, blksize);
+               if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
+                       cqr = NULL;
+       } else if (use_prefix &&
+                  (((rq_data_dir(req) == READ) && cmdrtd) ||
+                   ((rq_data_dir(req) == WRITE) && cmdwtd))) {
+               cqr = dasd_eckd_build_cp_cmd_track(startdev, block, req,
+                                                  first_rec, last_rec,
+                                                  first_trk, last_trk,
+                                                  first_offs, last_offs,
+                                                  blk_per_trk, blksize);
+               if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN)
+                       cqr = NULL;
+       }
+       if (!cqr)
+               cqr = dasd_eckd_build_cp_cmd_single(startdev, block, req,
+                                                   first_rec, last_rec,
+                                                   first_trk, last_trk,
+                                                   first_offs, last_offs,
+                                                   blk_per_trk, blksize);
+       return cqr;
+}
+
 static int
 dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
 {
@@ -1767,7 +2448,7 @@ out:
 }
 
 /*
- * Modify ccw chain in cqr so it can be started on a base device.
+ * Modify ccw/tcw in cqr so it can be started on a base device.
  *
  * Note that this is not enough to restart the cqr!
  * Either reset cqr->startdev as well (summary unit check handling)
@@ -1777,13 +2458,24 @@ void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *cqr)
 {
        struct ccw1 *ccw;
        struct PFX_eckd_data *pfxdata;
-
-       ccw = cqr->cpaddr;
-       pfxdata = cqr->data;
-
-       if (ccw->cmd_code == DASD_ECKD_CCW_PFX) {
+       struct tcw *tcw;
+       struct tccb *tccb;
+       struct dcw *dcw;
+
+       if (cqr->cpmode == 1) {
+               tcw = cqr->cpaddr;
+               tccb = tcw_get_tccb(tcw);
+               dcw = (struct dcw *)&tccb->tca[0];
+               pfxdata = (struct PFX_eckd_data *)&dcw->cd[0];
                pfxdata->validity.verify_base = 0;
                pfxdata->validity.hyper_pav = 0;
+       } else {
+               ccw = cqr->cpaddr;
+               pfxdata = cqr->data;
+               if (ccw->cmd_code == DASD_ECKD_CCW_PFX) {
+                       pfxdata->validity.verify_base = 0;
+                       pfxdata->validity.hyper_pav = 0;
+               }
        }
 }
 
@@ -1861,6 +2553,7 @@ dasd_eckd_release(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
        int rc;
+       struct ccw1 *ccw;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -1868,14 +2561,15 @@ dasd_eckd_release(struct dasd_device *device)
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 32, device);
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Could not allocate initialization request");
                return PTR_ERR(cqr);
        }
-       cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;
-        cqr->cpaddr->flags |= CCW_FLAG_SLI;
-        cqr->cpaddr->count = 32;
-       cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = DASD_ECKD_CCW_RELEASE;
+       ccw->flags |= CCW_FLAG_SLI;
+       ccw->count = 32;
+       ccw->cda = (__u32)(addr_t) cqr->data;
        cqr->startdev = device;
        cqr->memdev = device;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
@@ -1902,6 +2596,7 @@ dasd_eckd_reserve(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
        int rc;
+       struct ccw1 *ccw;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -1909,14 +2604,15 @@ dasd_eckd_reserve(struct dasd_device *device)
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 32, device);
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Could not allocate initialization request");
                return PTR_ERR(cqr);
        }
-       cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;
-        cqr->cpaddr->flags |= CCW_FLAG_SLI;
-        cqr->cpaddr->count = 32;
-       cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = DASD_ECKD_CCW_RESERVE;
+       ccw->flags |= CCW_FLAG_SLI;
+       ccw->count = 32;
+       ccw->cda = (__u32)(addr_t) cqr->data;
        cqr->startdev = device;
        cqr->memdev = device;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
@@ -1942,6 +2638,7 @@ dasd_eckd_steal_lock(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
        int rc;
+       struct ccw1 *ccw;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -1949,14 +2646,15 @@ dasd_eckd_steal_lock(struct dasd_device *device)
        cqr = dasd_smalloc_request(dasd_eckd_discipline.name,
                                   1, 32, device);
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Could not allocate initialization request");
                return PTR_ERR(cqr);
        }
-       cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK;
-        cqr->cpaddr->flags |= CCW_FLAG_SLI;
-        cqr->cpaddr->count = 32;
-       cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = DASD_ECKD_CCW_SLCK;
+       ccw->flags |= CCW_FLAG_SLI;
+       ccw->count = 32;
+       ccw->cda = (__u32)(addr_t) cqr->data;
        cqr->startdev = device;
        cqr->memdev = device;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
@@ -1990,7 +2688,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp)
                                    sizeof(struct dasd_rssd_perf_stats_t)),
                                   device);
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "Could not allocate initialization request");
                return PTR_ERR(cqr);
        }
@@ -2080,9 +2778,9 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
                return -EFAULT;
        private->attrib = attrib;
 
-       DEV_MESSAGE(KERN_INFO, device,
-                   "cache operation mode set to %x (%i cylinder prestage)",
-                   private->attrib.operation, private->attrib.nr_cyl);
+       dev_info(&device->cdev->dev,
+                "The DASD cache mode was set to %x (%i cylinder prestage)\n",
+                private->attrib.operation, private->attrib.nr_cyl);
        return 0;
 }
 
@@ -2133,7 +2831,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
        /* setup CCWs for PSF + RSSD */
        cqr = dasd_smalloc_request("ECKD", 2 , 0, device);
        if (IS_ERR(cqr)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                        "Could not allocate initialization request");
                rc = PTR_ERR(cqr);
                goto out_free;
@@ -2242,11 +2940,54 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
        return len;
 }
 
+static void
+dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req,
+                        struct irb *irb, char *reason)
+{
+       u64 *sense;
+       int sl;
+       struct tsb *tsb;
+
+       sense = NULL;
+       tsb = NULL;
+       if (req && scsw_is_tm(&req->irb.scsw)) {
+               if (irb->scsw.tm.tcw)
+                       tsb = tcw_get_tsb(
+                               (struct tcw *)(unsigned long)irb->scsw.tm.tcw);
+               if (tsb && (irb->scsw.tm.fcxs == 0x01)) {
+                       switch (tsb->flags & 0x07) {
+                       case 1: /* tsa_iostat */
+                               sense = (u64 *)tsb->tsa.iostat.sense;
+                       break;
+                       case 2: /* ts_ddpc */
+                               sense = (u64 *)tsb->tsa.ddpc.sense;
+                       break;
+                       case 3: /* tsa_intrg */
+                       break;
+                       }
+               }
+       } else {
+               if (irb->esw.esw0.erw.cons)
+                       sense = (u64 *)irb->ecw;
+       }
+       if (sense) {
+               for (sl = 0; sl < 4; sl++) {
+                       DBF_DEV_EVENT(DBF_EMERG, device,
+                                     "%s: %016llx %016llx %016llx %016llx",
+                                     reason, sense[0], sense[1], sense[2],
+                                     sense[3]);
+               }
+       } else {
+               DBF_DEV_EVENT(DBF_EMERG, device, "%s",
+                             "SORRY - NO VALID SENSE AVAILABLE\n");
+       }
+}
+
 /*
  * Print sense data and related channel program.
  * Parts are printed because printk buffer is only 1024 bytes.
  */
-static void dasd_eckd_dump_sense(struct dasd_device *device,
+static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                                 struct dasd_ccw_req *req, struct irb *irb)
 {
        char *page;
@@ -2255,8 +2996,8 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
 
        page = (char *) get_zeroed_page(GFP_ATOMIC);
        if (page == NULL) {
-               DEV_MESSAGE(KERN_ERR, device, " %s",
-                           "No memory to dump sense data");
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                             "No memory to dump sense data\n");
                return;
        }
        /* dump the sense data */
@@ -2265,7 +3006,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
                      dev_name(&device->cdev->dev));
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
-                      irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
+                      scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw));
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       dev_name(&device->cdev->dev),
@@ -2341,6 +3082,147 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
        free_page((unsigned long) page);
 }
 
+
+/*
+ * Print sense data from a tcw.
+ */
+static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
+                                struct dasd_ccw_req *req, struct irb *irb)
+{
+       char *page;
+       int len, sl, sct, residual;
+
+       struct tsb *tsb;
+       u8 *sense;
+
+
+       page = (char *) get_zeroed_page(GFP_ATOMIC);
+       if (page == NULL) {
+               DBF_DEV_EVENT(DBF_WARNING, device, " %s",
+                           "No memory to dump sense data");
+               return;
+       }
+       /* dump the sense data */
+       len = sprintf(page,  KERN_ERR PRINTK_HEADER
+                     " I/O status report for device %s:\n",
+                     dev_name(&device->cdev->dev));
+       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                      " in req: %p CS: 0x%02X DS: 0x%02X "
+                      "fcxs: 0x%02X schxs: 0x%02X\n", req,
+                      scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
+                      irb->scsw.tm.fcxs, irb->scsw.tm.schxs);
+       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                      " device %s: Failing TCW: %p\n",
+                      dev_name(&device->cdev->dev),
+                      (void *) (addr_t) irb->scsw.tm.tcw);
+
+       tsb = NULL;
+       sense = NULL;
+       if (irb->scsw.tm.tcw)
+               tsb = tcw_get_tsb(
+                       (struct tcw *)(unsigned long)irb->scsw.tm.tcw);
+
+       if (tsb && (irb->scsw.tm.fcxs == 0x01)) {
+               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->length %d\n", tsb->length);
+               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->flags %x\n", tsb->flags);
+               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->dcw_offset %d\n", tsb->dcw_offset);
+               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->count %d\n", tsb->count);
+               residual = tsb->count - 28;
+               len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " residual %d\n", residual);
+
+               switch (tsb->flags & 0x07) {
+               case 1: /* tsa_iostat */
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.iostat.dev_time %d\n",
+                                      tsb->tsa.iostat.dev_time);
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.iostat.def_time %d\n",
+                                      tsb->tsa.iostat.def_time);
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.iostat.queue_time %d\n",
+                                      tsb->tsa.iostat.queue_time);
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.iostat.dev_busy_time %d\n",
+                                      tsb->tsa.iostat.dev_busy_time);
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.iostat.dev_act_time %d\n",
+                                      tsb->tsa.iostat.dev_act_time);
+                       sense = tsb->tsa.iostat.sense;
+                       break;
+               case 2: /* ts_ddpc */
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc);
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                              " tsb->tsa.ddpc.rcq:  ");
+                       for (sl = 0; sl < 16; sl++) {
+                               for (sct = 0; sct < 8; sct++) {
+                                       len += sprintf(page + len, " %02x",
+                                                      tsb->tsa.ddpc.rcq[sl]);
+                               }
+                               len += sprintf(page + len, "\n");
+                       }
+                       sense = tsb->tsa.ddpc.sense;
+                       break;
+               case 3: /* tsa_intrg */
+                       len += sprintf(page + len, KERN_ERR PRINTK_HEADER
+                                     " tsb->tsa.intrg.: not supportet yet \n");
+                       break;
+               }
+
+               if (sense) {
+                       for (sl = 0; sl < 4; sl++) {
+                               len += sprintf(page + len,
+                                              KERN_ERR PRINTK_HEADER
+                                              " Sense(hex) %2d-%2d:",
+                                              (8 * sl), ((8 * sl) + 7));
+                               for (sct = 0; sct < 8; sct++) {
+                                       len += sprintf(page + len, " %02x",
+                                                      sense[8 * sl + sct]);
+                               }
+                               len += sprintf(page + len, "\n");
+                       }
+
+                       if (sense[27] & DASD_SENSE_BIT_0) {
+                               /* 24 Byte Sense Data */
+                               sprintf(page + len, KERN_ERR PRINTK_HEADER
+                                       " 24 Byte: %x MSG %x, "
+                                       "%s MSGb to SYSOP\n",
+                                       sense[7] >> 4, sense[7] & 0x0f,
+                                       sense[1] & 0x10 ? "" : "no");
+                       } else {
+                               /* 32 Byte Sense Data */
+                               sprintf(page + len, KERN_ERR PRINTK_HEADER
+                                       " 32 Byte: Format: %x "
+                                       "Exception class %x\n",
+                                       sense[6] & 0x0f, sense[22] >> 4);
+                       }
+               } else {
+                       sprintf(page + len, KERN_ERR PRINTK_HEADER
+                               " SORRY - NO VALID SENSE AVAILABLE\n");
+               }
+       } else {
+               sprintf(page + len, KERN_ERR PRINTK_HEADER
+                       " SORRY - NO TSB DATA AVAILABLE\n");
+       }
+       printk("%s", page);
+       free_page((unsigned long) page);
+}
+
+static void dasd_eckd_dump_sense(struct dasd_device *device,
+                                struct dasd_ccw_req *req, struct irb *irb)
+{
+       if (req && scsw_is_tm(&req->irb.scsw))
+               dasd_eckd_dump_sense_tcw(device, req, irb);
+       else
+               dasd_eckd_dump_sense_ccw(device, req, irb);
+}
+
+
 /*
  * max_blocks is dependent on the amount of storage that is available
  * in the static io buffer for each device. Currently each device has
@@ -2375,6 +3257,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .build_cp = dasd_eckd_build_alias_cp,
        .free_cp = dasd_eckd_free_alias_cp,
        .dump_sense = dasd_eckd_dump_sense,
+       .dump_sense_dbf = dasd_eckd_dump_sense_dbf,
        .fill_info = dasd_eckd_fill_info,
        .ioctl = dasd_eckd_ioctl,
 };
index 2476f87d21d0027ae61dc08e546abb15b37ec979..ad45bcac3ce4b20bd5f54c8a4ecdc16d13fdcc20 100644 (file)
 #define DASD_ECKD_CCW_RELEASE           0x94
 #define DASD_ECKD_CCW_READ_CKD_MT       0x9e
 #define DASD_ECKD_CCW_WRITE_CKD_MT      0x9d
+#define DASD_ECKD_CCW_WRITE_TRACK_DATA  0xA5
+#define DASD_ECKD_CCW_READ_TRACK_DATA   0xA6
 #define DASD_ECKD_CCW_RESERVE           0xB4
 #define DASD_ECKD_CCW_PFX               0xE7
+#define DASD_ECKD_CCW_PFX_READ          0xEA
 #define DASD_ECKD_CCW_RSCK              0xF9
 
 /*
 #define PSF_ORDER_PRSSD 0x18
 #define PSF_ORDER_SSC  0x1D
 
+/*
+ * Size that is reportet for large volumes in the old 16-bit no_cyl field
+ */
+#define LV_COMPAT_CYL 0xFFFE
+
 /*****************************************************************************
  * SECTION: Type Definitions
  ****************************************************************************/
@@ -118,7 +126,9 @@ struct DE_eckd_data {
        unsigned long long ep_sys_time; /* Ext Parameter - System Time Stamp */
        __u8 ep_format;        /* Extended Parameter format byte       */
        __u8 ep_prio;          /* Extended Parameter priority I/O byte */
-       __u8 ep_reserved[6];   /* Extended Parameter Reserved          */
+       __u8 ep_reserved1;     /* Extended Parameter Reserved          */
+       __u8 ep_rec_per_track; /* Number of records on a track         */
+       __u8 ep_reserved[4];   /* Extended Parameter Reserved          */
 } __attribute__ ((packed));
 
 struct LO_eckd_data {
@@ -139,11 +149,37 @@ struct LO_eckd_data {
        __u16 length;
 } __attribute__ ((packed));
 
+struct LRE_eckd_data {
+       struct {
+               unsigned char orientation:2;
+               unsigned char operation:6;
+       } __attribute__ ((packed)) operation;
+       struct {
+               unsigned char length_valid:1;
+               unsigned char length_scope:1;
+               unsigned char imbedded_ccw_valid:1;
+               unsigned char check_bytes:2;
+               unsigned char imbedded_count_valid:1;
+               unsigned char reserved:1;
+               unsigned char read_count_suffix:1;
+       } __attribute__ ((packed)) auxiliary;
+       __u8 imbedded_ccw;
+       __u8 count;
+       struct ch_t seek_addr;
+       struct chr_t search_arg;
+       __u8 sector;
+       __u16 length;
+       __u8 imbedded_count;
+       __u8 extended_operation;
+       __u16 extended_parameter_length;
+       __u8 extended_parameter[0];
+} __attribute__ ((packed));
+
 /* Prefix data for format 0x00 and 0x01 */
 struct PFX_eckd_data {
        unsigned char format;
        struct {
-               unsigned char define_extend:1;
+               unsigned char define_extent:1;
                unsigned char time_stamp:1;
                unsigned char verify_base:1;
                unsigned char hyper_pav:1;
@@ -153,9 +189,8 @@ struct PFX_eckd_data {
        __u8 aux;
        __u8 base_lss;
        __u8 reserved[7];
-       struct DE_eckd_data define_extend;
-       struct LO_eckd_data locate_record;
-       __u8 LO_extended_data[4];
+       struct DE_eckd_data define_extent;
+       struct LRE_eckd_data locate_record;
 } __attribute__ ((packed));
 
 struct dasd_eckd_characteristics {
@@ -228,7 +263,8 @@ struct dasd_eckd_characteristics {
        __u8 factor7;
        __u8 factor8;
        __u8 reserved2[3];
-       __u8 reserved3[10];
+       __u8 reserved3[6];
+       __u32 long_no_cyl;
 } __attribute__ ((packed));
 
 /* elements of the configuration data */
@@ -406,6 +442,7 @@ struct dasd_eckd_private {
        int uses_cdl;
        struct attrib_data_t attrib;    /* e.g. cache operations */
        struct dasd_rssd_features features;
+       u32 real_cyl;
 
        /* alias managemnet */
        struct dasd_uid uid;
index f8e05ce98621d41155ab9952bc5abfe6b0d192ac..c24c8c30380d30b45042e49db17e9afc206b1084 100644 (file)
@@ -6,6 +6,8 @@
  *  Author(s): Stefan Weinhuber <wein@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -297,11 +299,12 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
        struct dasd_eer_header header;
        unsigned long flags;
        struct eerbuffer *eerb;
+       char *sense;
 
        /* go through cqr chain and count the valid sense data sets */
        data_size = 0;
        for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers)
-               if (temp_cqr->irb.esw.esw0.erw.cons)
+               if (dasd_get_sense(&temp_cqr->irb))
                        data_size += 32;
 
        header.total_size = sizeof(header) + data_size + 4; /* "EOR" */
@@ -316,9 +319,11 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device,
        list_for_each_entry(eerb, &bufferlist, list) {
                dasd_eer_start_record(eerb, header.total_size);
                dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header));
-               for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers)
-                       if (temp_cqr->irb.esw.esw0.erw.cons)
-                               dasd_eer_write_buffer(eerb, cqr->irb.ecw, 32);
+               for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) {
+                       sense = dasd_get_sense(&temp_cqr->irb);
+                       if (sense)
+                               dasd_eer_write_buffer(eerb, sense, 32);
+               }
                dasd_eer_write_buffer(eerb, "EOR", 4);
        }
        spin_unlock_irqrestore(&bufferlock, flags);
@@ -451,6 +456,7 @@ int dasd_eer_enable(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
        unsigned long flags;
+       struct ccw1 *ccw;
 
        if (device->eer_cqr)
                return 0;
@@ -468,10 +474,11 @@ int dasd_eer_enable(struct dasd_device *device)
        cqr->expires = 10 * HZ;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
 
-       cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS;
-       cqr->cpaddr->count = SNSS_DATA_SIZE;
-       cqr->cpaddr->flags = 0;
-       cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = DASD_ECKD_CCW_SNSS;
+       ccw->count = SNSS_DATA_SIZE;
+       ccw->flags = 0;
+       ccw->cda = (__u32)(addr_t) cqr->data;
 
        cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
@@ -534,7 +541,7 @@ static int dasd_eer_open(struct inode *inp, struct file *filp)
        if (eerb->buffer_page_count < 1 ||
            eerb->buffer_page_count > INT_MAX / PAGE_SIZE) {
                kfree(eerb);
-               MESSAGE(KERN_WARNING, "can't open device since module "
+               DBF_EVENT(DBF_WARNING, "can't open device since module "
                        "parameter eer_pages is smaller than 1 or"
                        " bigger than %d", (int)(INT_MAX / PAGE_SIZE));
                unlock_kernel();
@@ -687,7 +694,7 @@ int __init dasd_eer_init(void)
        if (rc) {
                kfree(dasd_eer_dev);
                dasd_eer_dev = NULL;
-               MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
+               DBF_EVENT(DBF_ERR, "%s", "dasd_eer_init could not "
                       "register misc device");
                return rc;
        }
index 8f10000851a3acc603e941ff7741d6a16097dffa..d970ce2814bedf9af63b5a74e1eb8ff967641820 100644 (file)
@@ -9,6 +9,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/ctype.h>
 #include <linux/init.h>
 
@@ -91,14 +93,14 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr)
 
         /* just retry - there is nothing to save ... I got no sense data.... */
         if (cqr->retries > 0) {
-               DEV_MESSAGE (KERN_DEBUG, device,
+               DBF_DEV_EVENT(DBF_DEBUG, device,
                              "default ERP called (%i retries left)",
                              cqr->retries);
                cqr->lpm    = LPM_ANYPATH;
                cqr->status = DASD_CQR_FILLED;
         } else {
-                DEV_MESSAGE (KERN_WARNING, device, "%s",
-                            "default ERP called (NO retry left)");
+               dev_err(&device->cdev->dev,
+                       "default ERP has run out of retries and failed\n");
                cqr->status = DASD_CQR_FAILED;
                cqr->stopclk = get_clock();
         }
@@ -162,8 +164,21 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
                device->discipline->dump_sense(device, cqr, irb);
 }
 
+void
+dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb)
+{
+       struct dasd_device *device;
+
+       device = cqr->startdev;
+       /* dump sense data to s390 debugfeature*/
+       if (device->discipline && device->discipline->dump_sense_dbf)
+               device->discipline->dump_sense_dbf(device, cqr, irb, "log");
+}
+EXPORT_SYMBOL(dasd_log_sense_dbf);
+
 EXPORT_SYMBOL(dasd_default_erp_action);
 EXPORT_SYMBOL(dasd_default_erp_postaction);
 EXPORT_SYMBOL(dasd_alloc_erp_request);
 EXPORT_SYMBOL(dasd_free_erp_request);
 EXPORT_SYMBOL(dasd_log_sense);
+
index f1d176021694886fc1b6c2ba1f30ee6318c322c8..a3eb6fd146731dad7ef87c9f1dbe28a72eb504da 100644 (file)
@@ -6,6 +6,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <asm/debug.h>
@@ -128,17 +130,18 @@ dasd_fba_check_characteristics(struct dasd_device *device)
                private = kzalloc(sizeof(struct dasd_fba_private),
                                  GFP_KERNEL | GFP_DMA);
                if (private == NULL) {
-                       DEV_MESSAGE(KERN_WARNING, device, "%s",
-                                   "memory allocation failed for private "
-                                   "data");
+                       dev_warn(&device->cdev->dev,
+                                "Allocating memory for private DASD "
+                                "data failed\n");
                        return -ENOMEM;
                }
                device->private = (void *) private;
        }
        block = dasd_alloc_block();
        if (IS_ERR(block)) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s",
-                           "could not allocate dasd block structure");
+               DBF_EVENT(DBF_WARNING, "could not allocate dasd block "
+                         "structure for device: %s",
+                         dev_name(&device->cdev->dev));
                device->private = NULL;
                kfree(private);
                return PTR_ERR(block);
@@ -150,9 +153,9 @@ dasd_fba_check_characteristics(struct dasd_device *device)
        rdc_data = (void *) &(private->rdc_data);
        rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32);
        if (rc) {
-               DEV_MESSAGE(KERN_WARNING, device,
-                           "Read device characteristics returned error %d",
-                           rc);
+               DBF_EVENT(DBF_WARNING, "Read device characteristics returned "
+                         "error %d for device: %s",
+                         rc, dev_name(&device->cdev->dev));
                device->block = NULL;
                dasd_free_block(block);
                device->private = NULL;
@@ -160,15 +163,16 @@ dasd_fba_check_characteristics(struct dasd_device *device)
                return rc;
        }
 
-       DEV_MESSAGE(KERN_INFO, device,
-                   "%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)",
-                   cdev->id.dev_type,
-                   cdev->id.dev_model,
-                   cdev->id.cu_type,
-                   cdev->id.cu_model,
-                   ((private->rdc_data.blk_bdsa *
-                     (private->rdc_data.blk_size >> 9)) >> 11),
-                   private->rdc_data.blk_size);
+       dev_info(&device->cdev->dev,
+                "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB "
+                "and %d B/blk\n",
+                cdev->id.dev_type,
+                cdev->id.dev_model,
+                cdev->id.cu_type,
+                cdev->id.cu_model,
+                ((private->rdc_data.blk_bdsa *
+                  (private->rdc_data.blk_size >> 9)) >> 11),
+                private->rdc_data.blk_size);
        return 0;
 }
 
@@ -180,7 +184,7 @@ static int dasd_fba_do_analysis(struct dasd_block *block)
        private = (struct dasd_fba_private *) block->base->private;
        rc = dasd_check_blocksize(private->rdc_data.blk_size);
        if (rc) {
-               DEV_MESSAGE(KERN_INFO, block->base, "unknown blocksize %d",
+               DBF_DEV_EVENT(DBF_WARNING, block->base, "unknown blocksize %d",
                            private->rdc_data.blk_size);
                return rc;
        }
@@ -215,7 +219,7 @@ dasd_fba_erp_postaction(struct dasd_ccw_req * cqr)
        if (cqr->function == dasd_default_erp_action)
                return dasd_default_erp_postaction;
 
-       DEV_MESSAGE(KERN_WARNING, cqr->startdev, "unknown ERP action %p",
+       DBF_DEV_EVENT(DBF_WARNING, cqr->startdev, "unknown ERP action %p",
                    cqr->function);
        return NULL;
 }
@@ -233,9 +237,9 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device,
        }
 
        /* check for unsolicited interrupts */
-       DEV_MESSAGE(KERN_DEBUG, device, "%s",
+       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                    "unsolicited interrupt received");
-       device->discipline->dump_sense(device, NULL, irb);
+       device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited");
        dasd_schedule_device_bh(device);
        return;
 };
@@ -436,6 +440,25 @@ dasd_fba_fill_info(struct dasd_device * device,
        return 0;
 }
 
+static void
+dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req,
+                        struct irb *irb, char *reason)
+{
+       int sl;
+       if (irb->esw.esw0.erw.cons) {
+               for (sl = 0; sl < 4; sl++) {
+                       DBF_DEV_EVENT(DBF_EMERG, device,
+                                     "%s: %08x %08x %08x %08x",
+                                     reason, irb->ecw[8 * 0], irb->ecw[8 * 1],
+                                     irb->ecw[8 * 2], irb->ecw[8 * 3]);
+               }
+       } else {
+               DBF_DEV_EVENT(DBF_EMERG, device, "%s",
+                             "SORRY - NO VALID SENSE AVAILABLE\n");
+       }
+}
+
+
 static void
 dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                    struct irb *irb)
@@ -446,7 +469,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 
        page = (char *) get_zeroed_page(GFP_ATOMIC);
        if (page == NULL) {
-               DEV_MESSAGE(KERN_ERR, device, " %s",
+               DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "No memory to dump sense data");
                return;
        }
@@ -476,8 +499,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                               " SORRY - NO VALID SENSE AVAILABLE\n");
        }
-       MESSAGE_LOG(KERN_ERR, "%s",
-                   page + sizeof(KERN_ERR PRINTK_HEADER));
+       printk(KERN_ERR "%s", page);
 
        /* dump the Channel Program */
        /* print first CCWs (maximum 8) */
@@ -498,8 +520,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                len += sprintf(page + len, "\n");
                act++;
        }
-       MESSAGE_LOG(KERN_ERR, "%s",
-                   page + sizeof(KERN_ERR PRINTK_HEADER));
+       printk(KERN_ERR "%s", page);
 
 
        /* print failing CCW area */
@@ -540,8 +561,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                act++;
        }
        if (len > 0)
-               MESSAGE_LOG(KERN_ERR, "%s",
-                           page + sizeof(KERN_ERR PRINTK_HEADER));
+               printk(KERN_ERR "%s", page);
        free_page((unsigned long) page);
 }
 
@@ -576,6 +596,7 @@ static struct dasd_discipline dasd_fba_discipline = {
        .build_cp = dasd_fba_build_cp,
        .free_cp = dasd_fba_free_cp,
        .dump_sense = dasd_fba_dump_sense,
+       .dump_sense_dbf = dasd_fba_dump_sense_dbf,
        .fill_info = dasd_fba_fill_info,
 };
 
index e99d566b69cccdbdce2b5b680a1ec46ac97d2c3a..d3198303b93c5b004f0a14712fc39f6ef16ee0c0 100644 (file)
@@ -11,6 +11,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
@@ -163,9 +165,8 @@ int dasd_gendisk_init(void)
        /* Register to static dasd major 94 */
        rc = register_blkdev(DASD_MAJOR, "dasd");
        if (rc != 0) {
-               MESSAGE(KERN_WARNING,
-                       "Couldn't register successfully to "
-                       "major no %d", DASD_MAJOR);
+               pr_warning("Registering the device driver with major number "
+                          "%d failed\n", DASD_MAJOR);
                return rc;
        }
        return 0;
index 4a39084d9c95cd4f47370903143484bc04bae10f..c1e487f774c67fb5638be3cdbdadf73f1ea87474 100644 (file)
@@ -112,6 +112,9 @@ do { \
                                d_data); \
 } while(0)
 
+/* limit size for an errorstring */
+#define ERRORLENGTH 30
+
 /* definition of dbf debug levels */
 #define        DBF_EMERG       0       /* system is unusable                   */
 #define        DBF_ALERT       1       /* action must be taken immediately     */
@@ -157,7 +160,8 @@ struct dasd_ccw_req {
        struct dasd_block *block;       /* the originating block device */
        struct dasd_device *memdev;     /* the device used to allocate this */
        struct dasd_device *startdev;   /* device the request is started on */
-       struct ccw1 *cpaddr;            /* address of channel program */
+       void *cpaddr;                   /* address of ccw or tcw */
+       unsigned char cpmode;           /* 0 = cmd mode, 1 = itcw */
        char status;                    /* status of this request */
        short retries;                  /* A retry counter */
        unsigned long flags;            /* flags of this request */
@@ -280,6 +284,8 @@ struct dasd_discipline {
        dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *);
        void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *,
                            struct irb *);
+       void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *,
+                           struct irb *, char *);
 
        void (*handle_unsolicited_interrupt) (struct dasd_device *,
                                              struct irb *);
@@ -378,7 +384,7 @@ struct dasd_block {
        struct block_device *bdev;
        atomic_t open_count;
 
-       unsigned long blocks;      /* size of volume in blocks */
+       unsigned long long blocks; /* size of volume in blocks */
        unsigned int bp_block;     /* bytes per block */
        unsigned int s2b_shift;    /* log2 (bp_block/512) */
 
@@ -573,12 +579,14 @@ int dasd_generic_notify(struct ccw_device *, int);
 void dasd_generic_handle_state_change(struct dasd_device *);
 
 int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int);
+char *dasd_get_sense(struct irb *);
 
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
 extern int dasd_probeonly;
 extern int dasd_autodetect;
 extern int dasd_nopav;
+extern int dasd_nofcx;
 
 int dasd_devmap_init(void);
 void dasd_devmap_exit(void);
@@ -623,6 +631,7 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int,
                                            struct dasd_device *);
 void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *);
 void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
+void dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb);
 
 /* externals in dasd_3990_erp.c */
 struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *);
index b82d816d9ef7adda1d7d9ddd3c6f463666dc041b..4ce3f72ee1c13e2485e9a781b389f0eda2fd1c08 100644 (file)
@@ -9,6 +9,9 @@
  *
  * i/o controls for the dasd driver.
  */
+
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/interrupt.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -94,7 +97,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block)
        if (!capable (CAP_SYS_ADMIN))
                return -EACCES;
 
-       DEV_MESSAGE(KERN_DEBUG, base, "%s", "Quiesce IO on device");
+       dev_info(&base->cdev->dev, "The DASD has been put in the quiesce "
+                "state\n");
        spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
        base->stopped |= DASD_STOPPED_QUIESCE;
        spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
@@ -103,7 +107,7 @@ static int dasd_ioctl_quiesce(struct dasd_block *block)
 
 
 /*
- * Quiesce device.
+ * Resume device.
  */
 static int dasd_ioctl_resume(struct dasd_block *block)
 {
@@ -114,7 +118,8 @@ static int dasd_ioctl_resume(struct dasd_block *block)
        if (!capable (CAP_SYS_ADMIN))
                return -EACCES;
 
-       DEV_MESSAGE(KERN_DEBUG, base, "%s", "resume IO on device");
+       dev_info(&base->cdev->dev, "I/O operations have been resumed "
+                "on the DASD\n");
        spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
        base->stopped &= ~DASD_STOPPED_QUIESCE;
        spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
@@ -140,13 +145,13 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
                return -EPERM;
 
        if (base->state != DASD_STATE_BASIC) {
-               DEV_MESSAGE(KERN_WARNING, base, "%s",
-                           "dasd_format: device is not disabled! ");
+               dev_warn(&base->cdev->dev,
+                        "The DASD cannot be formatted while it is enabled\n");
                return -EBUSY;
        }
 
        DBF_DEV_EVENT(DBF_NOTICE, base,
-                     "formatting units %d to %d (%d B blocks) flags %d",
+                     "formatting units %u to %u (%u B blocks) flags %u",
                      fdata->start_unit,
                      fdata->stop_unit, fdata->blksize, fdata->intensity);
 
@@ -169,10 +174,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
                dasd_sfree_request(cqr, cqr->memdev);
                if (rc) {
                        if (rc != -ERESTARTSYS)
-                               DEV_MESSAGE(KERN_ERR, base,
-                                           " Formatting of unit %d failed "
-                                           "with rc = %d",
-                                           fdata->start_unit, rc);
+                               dev_err(&base->cdev->dev,
+                                       "Formatting unit %d failed with "
+                                       "rc=%d\n", fdata->start_unit, rc);
                        return rc;
                }
                fdata->start_unit++;
@@ -199,8 +203,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
        if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
                return -EFAULT;
        if (bdev != bdev->bd_contains) {
-               DEV_MESSAGE(KERN_WARNING, block->base, "%s",
-                           "Cannot low-level format a partition");
+               dev_warn(&block->base->cdev->dev,
+                        "The specified DASD is a partition and cannot be "
+                        "formatted\n");
                return -EINVAL;
        }
        return dasd_format(block, &fdata);
@@ -365,9 +370,9 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
        return ret;
 }
 
-int
-dasd_ioctl(struct block_device *bdev, fmode_t mode,
-          unsigned int cmd, unsigned long arg)
+static int
+dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
+             unsigned int cmd, unsigned long arg)
 {
        struct dasd_block *block = bdev->bd_disk->private_data;
        void __user *argp = (void __user *)arg;
@@ -420,3 +425,14 @@ dasd_ioctl(struct block_device *bdev, fmode_t mode,
                return -EINVAL;
        }
 }
+
+int dasd_ioctl(struct block_device *bdev, fmode_t mode,
+              unsigned int cmd, unsigned long arg)
+{
+       int rc;
+
+       lock_kernel();
+       rc = dasd_do_ioctl(bdev, mode, cmd, arg);
+       unlock_kernel();
+       return rc;
+}
index bf6fd348f20e5b97849fb44f75b5210e1853871f..2080ba6a69b0ea5b906c0a3bfc1c6ed639651b8b 100644 (file)
@@ -11,6 +11,8 @@
  *
  */
 
+#define KMSG_COMPONENT "dasd"
+
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
 #include <linux/vmalloc.h>
@@ -112,7 +114,7 @@ dasd_devices_show(struct seq_file *m, void *v)
                        seq_printf(m, "n/f       ");
                else
                        seq_printf(m,
-                                  "at blocksize: %d, %ld blocks, %ld MB",
+                                  "at blocksize: %d, %lld blocks, %lld MB",
                                   block->bp_block, block->blocks,
                                   ((block->bp_block >> 9) *
                                    block->blocks) >> 11);
@@ -267,7 +269,7 @@ dasd_statistics_write(struct file *file, const char __user *user_buf,
        buffer = dasd_get_user_string(user_buf, user_len);
        if (IS_ERR(buffer))
                return PTR_ERR(buffer);
-       MESSAGE_LOG(KERN_INFO, "/proc/dasd/statictics: '%s'", buffer);
+       DBF_EVENT(DBF_DEBUG, "/proc/dasd/statictics: '%s'\n", buffer);
 
        /* check for valid verbs */
        for (str = buffer; isspace(*str); str++);
@@ -277,33 +279,33 @@ dasd_statistics_write(struct file *file, const char __user *user_buf,
                if (strcmp(str, "on") == 0) {
                        /* switch on statistics profiling */
                        dasd_profile_level = DASD_PROFILE_ON;
-                       MESSAGE(KERN_INFO, "%s", "Statistics switched on");
+                       pr_info("The statistics feature has been switched "
+                               "on\n");
                } else if (strcmp(str, "off") == 0) {
                        /* switch off and reset statistics profiling */
                        memset(&dasd_global_profile,
                               0, sizeof (struct dasd_profile_info_t));
                        dasd_profile_level = DASD_PROFILE_OFF;
-                       MESSAGE(KERN_INFO, "%s", "Statistics switched off");
+                       pr_info("The statistics feature has been switched "
+                               "off\n");
                } else
                        goto out_error;
        } else if (strncmp(str, "reset", 5) == 0) {
                /* reset the statistics */
                memset(&dasd_global_profile, 0,
                       sizeof (struct dasd_profile_info_t));
-               MESSAGE(KERN_INFO, "%s", "Statistics reset");
+               pr_info("The statistics have been reset\n");
        } else
                goto out_error;
        kfree(buffer);
        return user_len;
 out_error:
-       MESSAGE(KERN_WARNING, "%s",
-               "/proc/dasd/statistics: only 'set on', 'set off' "
-               "and 'reset' are supported verbs");
+       pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
+               str);
        kfree(buffer);
        return -EINVAL;
 #else
-       MESSAGE(KERN_WARNING, "%s",
-               "/proc/dasd/statistics: is not activated in this kernel");
+       pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
        return user_len;
 #endif                         /* CONFIG_DASD_PROFILE */
 }
index d0d565a05dfebf63a5ddea6ed93b37949465c431..c07809c8016ab13e1fed7df19a333038a34ff2cb 100644 (file)
@@ -324,8 +324,6 @@ static inline void tape_proc_cleanup (void) {;}
 #endif
 
 /* a function for dumping device sense info */
-extern void tape_dump_sense(struct tape_device *, struct tape_request *,
-                           struct irb *);
 extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *,
                                struct irb *);
 
index 22ca34361ed7711e15eb9a7c5688970aab46b81d..807ded5eb0493fa1bc52f64582d316372a8b080d 100644 (file)
@@ -8,6 +8,8 @@
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "tape"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/bio.h>
@@ -18,8 +20,6 @@
 #include "tape.h"
 #include "tape_std.h"
 
-#define PRINTK_HEADER "TAPE_34XX: "
-
 /*
  * Pointer to debug area.
  */
@@ -203,8 +203,7 @@ tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb)
                tape_34xx_schedule_work(device, TO_MSEN);
        } else {
                DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
-               PRINT_WARN("Unsolicited IRQ (Device End) caught.\n");
-               tape_dump_sense(device, NULL, irb);
+               tape_dump_sense_dbf(device, NULL, irb);
        }
        return TAPE_IO_SUCCESS;
 }
@@ -226,9 +225,7 @@ tape_34xx_erp_read_opposite(struct tape_device *device,
                tape_std_read_backward(device, request);
                return tape_34xx_erp_retry(request);
        }
-       if (request->op != TO_RBA)
-               PRINT_ERR("read_opposite called with state:%s\n",
-                         tape_op_verbose[request->op]);
+
        /*
         * We tried to read forward and backward, but hat no
         * success -> failed.
@@ -241,13 +238,9 @@ tape_34xx_erp_bug(struct tape_device *device, struct tape_request *request,
                  struct irb *irb, int no)
 {
        if (request->op != TO_ASSIGN) {
-               PRINT_WARN("An unexpected condition #%d was caught in "
-                          "tape error recovery.\n", no);
-               PRINT_WARN("Please report this incident.\n");
-               if (request)
-                       PRINT_WARN("Operation of tape:%s\n",
-                                  tape_op_verbose[request->op]);
-               tape_dump_sense(device, request, irb);
+               dev_err(&device->cdev->dev, "An unexpected condition %d "
+                       "occurred in tape error recovery\n", no);
+               tape_dump_sense_dbf(device, request, irb);
        }
        return tape_34xx_erp_failed(request, -EIO);
 }
@@ -261,9 +254,8 @@ tape_34xx_erp_overrun(struct tape_device *device, struct tape_request *request,
                      struct irb *irb)
 {
        if (irb->ecw[3] == 0x40) {
-               PRINT_WARN ("Data overrun error between control-unit "
-                           "and drive. Use a faster channel connection, "
-                           "if possible! \n");
+               dev_warn (&device->cdev->dev, "A data overrun occurred between"
+                       " the control unit and tape unit\n");
                return tape_34xx_erp_failed(request, -EIO);
        }
        return tape_34xx_erp_bug(device, request, irb, -1);
@@ -280,7 +272,8 @@ tape_34xx_erp_sequence(struct tape_device *device,
                /*
                 * cu detected incorrect block-id sequence on tape.
                 */
-               PRINT_WARN("Illegal block-id sequence found!\n");
+               dev_warn (&device->cdev->dev, "The block ID sequence on the "
+                       "tape is incorrect\n");
                return tape_34xx_erp_failed(request, -EIO);
        }
        /*
@@ -393,8 +386,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                        /* Writing at physical end of volume */
                        return tape_34xx_erp_failed(request, -ENOSPC);
                default:
-                       PRINT_ERR("Invalid op in %s:%i\n",
-                                 __func__, __LINE__);
                        return tape_34xx_erp_failed(request, 0);
                }
        }
@@ -420,7 +411,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                                                         irb, -4);
 
                        /* data check is permanent, CU recovery has failed */
-                       PRINT_WARN("Permanent read error\n");
+                       dev_warn (&device->cdev->dev, "A read error occurred "
+                               "that cannot be recovered\n");
                        return tape_34xx_erp_failed(request, -EIO);
                case 0x25:
                        // a write data check occurred
@@ -433,22 +425,26 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                                                         irb, -5);
 
                        // data check is permanent, cu-recovery has failed
-                       PRINT_WARN("Permanent write error\n");
+                       dev_warn (&device->cdev->dev, "A write error on the "
+                               "tape cannot be recovered\n");
                        return tape_34xx_erp_failed(request, -EIO);
                case 0x26:
                        /* Data Check (read opposite) occurred. */
                        return tape_34xx_erp_read_opposite(device, request);
                case 0x28:
                        /* ID-Mark at tape start couldn't be written */
-                       PRINT_WARN("ID-Mark could not be written.\n");
+                       dev_warn (&device->cdev->dev, "Writing the ID-mark "
+                               "failed\n");
                        return tape_34xx_erp_failed(request, -EIO);
                case 0x31:
                        /* Tape void. Tried to read beyond end of device. */
-                       PRINT_WARN("Read beyond end of recorded area.\n");
+                       dev_warn (&device->cdev->dev, "Reading the tape beyond"
+                               " the end of the recorded area failed\n");
                        return tape_34xx_erp_failed(request, -ENOSPC);
                case 0x41:
                        /* Record sequence error. */
-                       PRINT_WARN("Invalid block-id sequence found.\n");
+                       dev_warn (&device->cdev->dev, "The tape contains an "
+                               "incorrect block ID sequence\n");
                        return tape_34xx_erp_failed(request, -EIO);
                default:
                        /* all data checks for 3480 should result in one of
@@ -470,16 +466,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
        switch (sense[3]) {
        case 0x00:
                /* Unit check with erpa code 0. Report and ignore. */
-               PRINT_WARN("Non-error sense was found. "
-                          "Unit-check will be ignored.\n");
                return TAPE_IO_SUCCESS;
        case 0x21:
                /*
                 * Data streaming not operational. CU will switch to
                 * interlock mode. Reissue the command.
                 */
-               PRINT_WARN("Data streaming not operational. "
-                          "Switching to interlock-mode.\n");
                return tape_34xx_erp_retry(request);
        case 0x22:
                /*
@@ -487,11 +479,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * error on the lower interface, internal path not usable,
                 * or error during cartridge load.
                 */
-               PRINT_WARN("A path equipment check occurred. One of the "
-                          "following conditions occurred:\n");
-               PRINT_WARN("drive adapter error, buffer error on the lower "
-                          "interface, internal path not usable, error "
-                          "during cartridge load.\n");
+               dev_warn (&device->cdev->dev, "A path equipment check occurred"
+                       " for the tape device\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x24:
                /*
@@ -514,7 +503,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * but the hardware isn't capable to do idrc, or a perform
                 * subsystem func is issued and the CU is not on-line.
                 */
-               PRINT_WARN ("Function incompatible. Try to switch off idrc\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x2a:
                /*
@@ -552,23 +540,26 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * reading the format id mark or that that format specified
                 * is not supported by the drive.
                 */
-               PRINT_WARN("Drive not capable processing the tape format!\n");
+               dev_warn (&device->cdev->dev, "The tape unit cannot process "
+                       "the tape format\n");
                return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
        case 0x30:
                /* The medium is write protected. */
-               PRINT_WARN("Medium is write protected!\n");
+               dev_warn (&device->cdev->dev, "The tape medium is write-"
+                       "protected\n");
                return tape_34xx_erp_failed(request, -EACCES);
        case 0x32:
                // Tension loss. We cannot recover this, it's an I/O error.
-               PRINT_WARN("The drive lost tape tension.\n");
+               dev_warn (&device->cdev->dev, "The tape does not have the "
+                       "required tape tension\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x33:
                /*
                 * Load Failure. The cartridge was not inserted correctly or
                 * the tape is not threaded correctly.
                 */
-               PRINT_WARN("Cartridge load failure. Reload the cartridge "
-                          "and try again.\n");
+               dev_warn (&device->cdev->dev, "The tape unit failed to load"
+                       " the cartridge\n");
                tape_34xx_delete_sbid_from(device, 0);
                return tape_34xx_erp_failed(request, -EIO);
        case 0x34:
@@ -576,8 +567,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * Unload failure. The drive cannot maintain tape tension
                 * and control tape movement during an unload operation.
                 */
-               PRINT_WARN("Failure during cartridge unload. "
-                          "Please try manually.\n");
+               dev_warn (&device->cdev->dev, "Automatic unloading of the tape"
+                       " cartridge failed\n");
                if (request->op == TO_RUN)
                        return tape_34xx_erp_failed(request, -EIO);
                return tape_34xx_erp_bug(device, request, irb, sense[3]);
@@ -589,8 +580,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * - the cartridge loader does not respond correctly
                 * - a failure occurs during an index, load, or unload cycle
                 */
-               PRINT_WARN("Equipment check! Please check the drive and "
-                          "the cartridge loader.\n");
+               dev_warn (&device->cdev->dev, "An equipment check has occurred"
+                       " on the tape unit\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x36:
                if (device->cdev->id.driver_info == tape_3490)
@@ -603,7 +594,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * Tape length error. The tape is shorter than reported in
                 * the beginning-of-tape data.
                 */
-               PRINT_WARN("Tape length error.\n");
+               dev_warn (&device->cdev->dev, "The tape information states an"
+                       " incorrect length\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x38:
                /*
@@ -620,12 +612,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                return tape_34xx_erp_failed(request, -EIO);
        case 0x3a:
                /* Drive switched to not ready. */
-               PRINT_WARN("Drive not ready. Turn the ready/not ready switch "
-                          "to ready position and try again.\n");
+               dev_warn (&device->cdev->dev, "The tape unit is not ready\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x3b:
                /* Manual rewind or unload. This causes an I/O error. */
-               PRINT_WARN("Medium was rewound or unloaded manually.\n");
+               dev_warn (&device->cdev->dev, "The tape medium has been "
+                       "rewound or unloaded manually\n");
                tape_34xx_delete_sbid_from(device, 0);
                return tape_34xx_erp_failed(request, -EIO);
        case 0x42:
@@ -633,7 +625,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * Degraded mode. A condition that can cause degraded
                 * performance is detected.
                 */
-               PRINT_WARN("Subsystem is running in degraded mode.\n");
+               dev_warn (&device->cdev->dev, "The tape subsystem is running "
+                       "in degraded mode\n");
                return tape_34xx_erp_retry(request);
        case 0x43:
                /* Drive not ready. */
@@ -652,7 +645,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                                        break;
                        }
                }
-               PRINT_WARN("The drive is not ready.\n");
                return tape_34xx_erp_failed(request, -ENOMEDIUM);
        case 0x44:
                /* Locate Block unsuccessful. */
@@ -663,7 +655,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                return tape_34xx_erp_failed(request, -EIO);
        case 0x45:
                /* The drive is assigned to a different channel path. */
-               PRINT_WARN("The drive is assigned elsewhere.\n");
+               dev_warn (&device->cdev->dev, "The tape unit is already "
+                       "assigned\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x46:
                /*
@@ -671,11 +664,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * the power supply may be switched off or
                 * the drive address may not be set correctly.
                 */
-               PRINT_WARN("The drive is not on-line.");
+               dev_warn (&device->cdev->dev, "The tape unit is not online\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x47:
                /* Volume fenced. CU reports volume integrity is lost. */
-               PRINT_WARN("Volume fenced. The volume integrity is lost.\n");
+               dev_warn (&device->cdev->dev, "The control unit has fenced "
+                       "access to the tape volume\n");
                tape_34xx_delete_sbid_from(device, 0);
                return tape_34xx_erp_failed(request, -EIO);
        case 0x48:
@@ -683,20 +677,21 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                return tape_34xx_erp_retry(request);
        case 0x49:
                /* Bus out check. A parity check error on the bus was found. */
-               PRINT_WARN("Bus out check. A data transfer over the bus "
-                          "has been corrupted.\n");
+               dev_warn (&device->cdev->dev, "A parity error occurred on the "
+                       "tape bus\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x4a:
                /* Control unit erp failed. */
-               PRINT_WARN("The control unit I/O error recovery failed.\n");
+               dev_warn (&device->cdev->dev, "I/O error recovery failed on "
+                       "the tape control unit\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x4b:
                /*
                 * CU and drive incompatible. The drive requests micro-program
                 * patches, which are not available on the CU.
                 */
-               PRINT_WARN("The drive needs microprogram patches from the "
-                          "control unit, which are not available.\n");
+               dev_warn (&device->cdev->dev, "The tape unit requires a "
+                       "firmware update\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x4c:
                /*
@@ -721,8 +716,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                         * the block to be written is larger than allowed for
                         * buffered mode.
                         */
-                       PRINT_WARN("Maximum block size for buffered "
-                                  "mode exceeded.\n");
+                       dev_warn (&device->cdev->dev, "The maximum block size"
+                               " for buffered mode is exceeded\n");
                        return tape_34xx_erp_failed(request, -ENOBUFS);
                }
                /* This erpa is reserved for 3480. */
@@ -759,22 +754,20 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                return tape_34xx_erp_retry(request);
        case 0x55:
                /* Channel interface recovery (permanent). */
-               PRINT_WARN("A permanent channel interface error occurred.\n");
+               dev_warn (&device->cdev->dev, "A channel interface error cannot be"
+                       " recovered\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x56:
                /* Channel protocol error. */
-               PRINT_WARN("A channel protocol error occurred.\n");
+               dev_warn (&device->cdev->dev, "A channel protocol error "
+                       "occurred\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x57:
                if (device->cdev->id.driver_info == tape_3480) {
                        /* Attention intercept. */
-                       PRINT_WARN("An attention intercept occurred, "
-                                  "which will be recovered.\n");
                        return tape_34xx_erp_retry(request);
                } else {
                        /* Global status intercept. */
-                       PRINT_WARN("An global status intercept was received, "
-                                  "which will be recovered.\n");
                        return tape_34xx_erp_retry(request);
                }
        case 0x5a:
@@ -782,42 +775,31 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
                 * Tape length incompatible. The tape inserted is too long,
                 * which could cause damage to the tape or the drive.
                 */
-               PRINT_WARN("Tape Length Incompatible\n");
-               PRINT_WARN("Tape length exceeds IBM enhanced capacity "
-                       "cartdridge length or a medium\n");
-               PRINT_WARN("with EC-CST identification mark has been mounted "
-                       "in a device that writes\n");
-               PRINT_WARN("3480 or 3480 XF format.\n");
+               dev_warn (&device->cdev->dev, "The tape unit does not support "
+                       "the tape length\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x5b:
                /* Format 3480 XF incompatible */
                if (sense[1] & SENSE_BEGINNING_OF_TAPE)
                        /* The tape will get overwritten. */
                        return tape_34xx_erp_retry(request);
-               PRINT_WARN("Format 3480 XF Incompatible\n");
-               PRINT_WARN("Medium has been created in 3480 format. "
-                       "To change the format writes\n");
-               PRINT_WARN("must be issued at BOT.\n");
+               dev_warn (&device->cdev->dev, "The tape unit does not support"
+                       " format 3480 XF\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x5c:
                /* Format 3480-2 XF incompatible */
-               PRINT_WARN("Format 3480-2 XF Incompatible\n");
-               PRINT_WARN("Device can only read 3480 or 3480 XF format.\n");
+               dev_warn (&device->cdev->dev, "The tape unit does not support tape "
+                       "format 3480-2 XF\n");
                return tape_34xx_erp_failed(request, -EIO);
        case 0x5d:
                /* Tape length violation. */
-               PRINT_WARN("Tape Length Violation\n");
-               PRINT_WARN("The mounted tape exceeds IBM Enhanced Capacity "
-                       "Cartdridge System Tape length.\n");
-               PRINT_WARN("This may cause damage to the drive or tape when "
-                       "processing to the EOV\n");
+               dev_warn (&device->cdev->dev, "The tape unit does not support"
+                       " the current tape length\n");
                return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
        case 0x5e:
                /* Compaction algorithm incompatible. */
-               PRINT_WARN("Compaction Algorithm Incompatible\n");
-               PRINT_WARN("The volume is recorded using an incompatible "
-                       "compaction algorithm,\n");
-               PRINT_WARN("which is not supported by the device.\n");
+               dev_warn (&device->cdev->dev, "The tape unit does not support"
+                       " the compaction algorithm\n");
                return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
 
                /* The following erpas should have been covered earlier. */
@@ -848,7 +830,6 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request,
            (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
            (request->op == TO_WRI)) {
                /* Write at end of volume */
-               PRINT_INFO("End of volume\n"); /* XXX */
                return tape_34xx_erp_failed(request, -ENOSPC);
        }
 
@@ -869,9 +850,7 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request,
        }
 
        DBF_EVENT(6, "xunknownirq\n");
-       PRINT_ERR("Unexpected interrupt.\n");
-       PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]);
-       tape_dump_sense(device, request, irb);
+       tape_dump_sense_dbf(device, request, irb);
        return TAPE_IO_STOP;
 }
 
index 71605a179d65e6740839413ad9ec99811a5fd248..fc1d91294143192dbc57a8f12d3bfe9e1b6aeed7 100644 (file)
@@ -8,12 +8,15 @@
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "tape"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/bio.h>
 #include <asm/ebcdic.h>
 
 #define TAPE_DBF_AREA  tape_3590_dbf
+#define BUFSIZE 512    /* size of buffers for dynamic generated messages */
 
 #include "tape.h"
 #include "tape_std.h"
@@ -36,7 +39,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA);
  * - Read Alternate:            implemented
  *******************************************************************/
 
-#define PRINTK_HEADER "TAPE_3590: "
+#define KMSG_COMPONENT "tape"
 
 static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = {
        [0x00] = "",
@@ -661,8 +664,7 @@ tape_3590_bread(struct tape_device *device, struct request *req)
                        ccw++;
                        dst += TAPEBLOCK_HSEC_SIZE;
                }
-               if (off > bv->bv_len)
-                       BUG();
+               BUG_ON(off > bv->bv_len);
        }
        ccw = tape_ccw_end(ccw, NOP, 0, NULL);
        DBF_EVENT(6, "xBREDccwg\n");
@@ -726,7 +728,7 @@ static void tape_3590_med_state_set(struct tape_device *device,
        }
        c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK;
        if (sense->flags & MSENSE_CRYPT_MASK) {
-               PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags);
+               DBF_EVENT(6, "Medium is encrypted (%04x)\n", sense->flags);
                c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK;
        } else  {
                DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags);
@@ -847,8 +849,7 @@ tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb)
                tape_3590_schedule_work(device, TO_READ_ATTMSG);
        } else {
                DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
-               PRINT_WARN("Unsolicited IRQ (Device End) caught.\n");
-               tape_dump_sense(device, NULL, irb);
+               tape_dump_sense_dbf(device, NULL, irb);
        }
        /* check medium state */
        tape_3590_schedule_work(device, TO_MSEN);
@@ -876,8 +877,6 @@ tape_3590_erp_basic(struct tape_device *device, struct tape_request *request,
        case SENSE_BRA_DRE:
                return tape_3590_erp_failed(device, request, irb, rc);
        default:
-               PRINT_ERR("Unknown BRA %x - This should not happen!\n",
-                         sense->bra);
                BUG();
                return TAPE_IO_STOP;
        }
@@ -910,7 +909,8 @@ tape_3590_erp_swap(struct tape_device *device, struct tape_request *request,
         * should proceed with the new tape... this
         * should probably be done in user space!
         */
-       PRINT_WARN("(%s): Swap Tape Device!\n", dev_name(&device->cdev->dev));
+       dev_warn (&device->cdev->dev, "The tape medium must be loaded into a "
+               "different tape unit\n");
        return tape_3590_erp_basic(device, request, irb, -EIO);
 }
 
@@ -985,8 +985,6 @@ tape_3590_erp_read_opposite(struct tape_device *device,
                return tape_3590_erp_failed(device, request, irb, -EIO);
                break;
        default:
-               PRINT_WARN("read_opposite_recovery_called_with_op: %s\n",
-                          tape_op_verbose[request->op]);
                return tape_3590_erp_failed(device, request, irb, -EIO);
        }
 }
@@ -998,50 +996,61 @@ static void
 tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb)
 {
        struct tape_3590_sense *sense;
+       char *exception, *service;
+
+       exception = kmalloc(BUFSIZE, GFP_ATOMIC);
+       service = kmalloc(BUFSIZE, GFP_ATOMIC);
+
+       if (!exception || !service)
+               goto out_nomem;
 
        sense = (struct tape_3590_sense *) irb->ecw;
        /* Exception Message */
        switch (sense->fmt.f70.emc) {
        case 0x02:
-               PRINT_WARN("(%s): Data degraded\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "Data degraded");
                break;
        case 0x03:
-               PRINT_WARN("(%s): Data degraded in partion %i\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f70.mp);
+               snprintf(exception, BUFSIZE, "Data degraded in partion %i",
+                       sense->fmt.f70.mp);
                break;
        case 0x04:
-               PRINT_WARN("(%s): Medium degraded\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "Medium degraded");
                break;
        case 0x05:
-               PRINT_WARN("(%s): Medium degraded in partition %i\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f70.mp);
+               snprintf(exception, BUFSIZE, "Medium degraded in partition %i",
+                       sense->fmt.f70.mp);
                break;
        case 0x06:
-               PRINT_WARN("(%s): Block 0 Error\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "Block 0 Error");
                break;
        case 0x07:
-               PRINT_WARN("(%s): Medium Exception 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f70.md);
+               snprintf(exception, BUFSIZE, "Medium Exception 0x%02x",
+                       sense->fmt.f70.md);
                break;
        default:
-               PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f70.emc);
+               snprintf(exception, BUFSIZE, "0x%02x",
+                       sense->fmt.f70.emc);
                break;
        }
        /* Service Message */
        switch (sense->fmt.f70.smc) {
        case 0x02:
-               PRINT_WARN("(%s): Reference Media maintenance procedure %i\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f70.md);
+               snprintf(service, BUFSIZE, "Reference Media maintenance "
+                       "procedure %i", sense->fmt.f70.md);
                break;
        default:
-               PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f70.smc);
+               snprintf(service, BUFSIZE, "0x%02x",
+                       sense->fmt.f70.smc);
                break;
        }
+
+       dev_warn (&device->cdev->dev, "Tape media information: exception %s, "
+               "service %s\n", exception, service);
+
+out_nomem:
+       kfree(exception);
+       kfree(service);
 }
 
 /*
@@ -1051,108 +1060,108 @@ static void
 tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb)
 {
        struct tape_3590_sense *sense;
+       char *exception, *service;
+
+       exception = kmalloc(BUFSIZE, GFP_ATOMIC);
+       service = kmalloc(BUFSIZE, GFP_ATOMIC);
+
+       if (!exception || !service)
+               goto out_nomem;
 
        sense = (struct tape_3590_sense *) irb->ecw;
        /* Exception Message */
        switch (sense->fmt.f71.emc) {
        case 0x01:
-               PRINT_WARN("(%s): Effect of failure is unknown\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "Effect of failure is unknown");
                break;
        case 0x02:
-               PRINT_WARN("(%s): CU Exception - no performance impact\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "CU Exception - no performance "
+                       "impact");
                break;
        case 0x03:
-               PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "CU Exception on channel "
+                       "interface 0x%02x", sense->fmt.f71.md[0]);
                break;
        case 0x04:
-               PRINT_WARN("(%s): CU Exception on device path 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "CU Exception on device path "
+                       "0x%02x", sense->fmt.f71.md[0]);
                break;
        case 0x05:
-               PRINT_WARN("(%s): CU Exception on library path 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "CU Exception on library path "
+                       "0x%02x", sense->fmt.f71.md[0]);
                break;
        case 0x06:
-               PRINT_WARN("(%s): CU Exception on node 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "CU Exception on node 0x%02x",
+                       sense->fmt.f71.md[0]);
                break;
        case 0x07:
-               PRINT_WARN("(%s): CU Exception on partition 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "CU Exception on partition "
+                       "0x%02x", sense->fmt.f71.md[0]);
                break;
        default:
-               PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.emc);
+               snprintf(exception, BUFSIZE, "0x%02x",
+                       sense->fmt.f71.emc);
        }
        /* Service Message */
        switch (sense->fmt.f71.smc) {
        case 0x01:
-               PRINT_WARN("(%s): Repair impact is unknown\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Repair impact is unknown");
                break;
        case 0x02:
-               PRINT_WARN("(%s): Repair will not impact cu performance\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Repair will not impact cu "
+                       "performance");
                break;
        case 0x03:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable node "
-                                  "0x%x on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable node "
+                               "0x%x on CU", sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable nodes "
-                                  "(0x%x-0x%x) on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "nodes (0x%x-0x%x) on CU", sense->fmt.f71.md[1],
+                               sense->fmt.f71.md[2]);
                break;
        case 0x04:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable cannel path "
-                                  "0x%x on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "channel path 0x%x on CU",
+                               sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable cannel paths "
-                                  "(0x%x-0x%x) on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable cannel"
+                               " paths (0x%x-0x%x) on CU",
+                               sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x05:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable device path "
-                                  "0x%x on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable device"
+                               " path 0x%x on CU", sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable device paths "
-                                  "(0x%x-0x%x) on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable device"
+                               " paths (0x%x-0x%x) on CU",
+                               sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x06:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable library path "
-                                  "0x%x on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "library path 0x%x on CU",
+                               sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable library paths "
-                                  "(0x%x-0x%x) on CU\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "library paths (0x%x-0x%x) on CU",
+                               sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x07:
-               PRINT_WARN("(%s): Repair will disable access to CU\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Repair will disable access to CU");
                break;
        default:
-               PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.smc);
+               snprintf(service, BUFSIZE, "0x%02x",
+                       sense->fmt.f71.smc);
        }
+
+       dev_warn (&device->cdev->dev, "I/O subsystem information: exception"
+               " %s, service %s\n", exception, service);
+out_nomem:
+       kfree(exception);
+       kfree(service);
 }
 
 /*
@@ -1162,111 +1171,109 @@ static void
 tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb)
 {
        struct tape_3590_sense *sense;
+       char *exception, *service;
+
+       exception = kmalloc(BUFSIZE, GFP_ATOMIC);
+       service = kmalloc(BUFSIZE, GFP_ATOMIC);
+
+       if (!exception || !service)
+               goto out_nomem;
 
        sense = (struct tape_3590_sense *) irb->ecw;
        /* Exception Message */
        switch (sense->fmt.f71.emc) {
        case 0x01:
-               PRINT_WARN("(%s): Effect of failure is unknown\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "Effect of failure is unknown");
                break;
        case 0x02:
-               PRINT_WARN("(%s): DV Exception - no performance impact\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "DV Exception - no performance"
+                       " impact");
                break;
        case 0x03:
-               PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "DV Exception on channel "
+                       "interface 0x%02x", sense->fmt.f71.md[0]);
                break;
        case 0x04:
-               PRINT_WARN("(%s): DV Exception on loader 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "DV Exception on loader 0x%02x",
+                       sense->fmt.f71.md[0]);
                break;
        case 0x05:
-               PRINT_WARN("(%s): DV Exception on message display 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.md[0]);
+               snprintf(exception, BUFSIZE, "DV Exception on message display"
+                       " 0x%02x", sense->fmt.f71.md[0]);
                break;
        case 0x06:
-               PRINT_WARN("(%s): DV Exception in tape path\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "DV Exception in tape path");
                break;
        case 0x07:
-               PRINT_WARN("(%s): DV Exception in drive\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(exception, BUFSIZE, "DV Exception in drive");
                break;
        default:
-               PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.emc);
+               snprintf(exception, BUFSIZE, "0x%02x",
+                       sense->fmt.f71.emc);
        }
        /* Service Message */
        switch (sense->fmt.f71.smc) {
        case 0x01:
-               PRINT_WARN("(%s): Repair impact is unknown\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Repair impact is unknown");
                break;
        case 0x02:
-               PRINT_WARN("(%s): Repair will not impact device performance\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Repair will not impact device "
+                       "performance");
                break;
        case 0x03:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable channel path "
-                                  "0x%x on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "channel path 0x%x on DV",
+                               sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable channel path "
-                                  "(0x%x-0x%x) on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "channel path (0x%x-0x%x) on DV",
+                               sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x04:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable interface 0x%x "
-                                  "on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "interface 0x%x on DV", sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable interfaces "
-                                  "(0x%x-0x%x) on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "interfaces (0x%x-0x%x) on DV",
+                               sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x05:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable loader 0x%x "
-                                  "on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable loader"
+                               " 0x%x on DV", sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable loader "
-                                  "(0x%x-0x%x) on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable loader"
+                               " (0x%x-0x%x) on DV",
+                               sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x07:
-               PRINT_WARN("(%s): Repair will disable access to DV\n",
-                          dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Repair will disable access to DV");
                break;
        case 0x08:
                if (sense->fmt.f71.mdf == 0)
-                       PRINT_WARN("(%s): Repair will disable message "
-                                  "display 0x%x on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "message display 0x%x on DV",
+                               sense->fmt.f71.md[1]);
                else
-                       PRINT_WARN("(%s): Repair will disable message "
-                                  "displays (0x%x-0x%x) on DV\n",
-                                  dev_name(&device->cdev->dev),
-                                  sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
+                       snprintf(service, BUFSIZE, "Repair will disable "
+                               "message displays (0x%x-0x%x) on DV",
+                                sense->fmt.f71.md[1], sense->fmt.f71.md[2]);
                break;
        case 0x09:
-               PRINT_WARN("(%s): Clean DV\n", dev_name(&device->cdev->dev));
+               snprintf(service, BUFSIZE, "Clean DV");
                break;
        default:
-               PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.smc);
+               snprintf(service, BUFSIZE, "0x%02x",
+                       sense->fmt.f71.smc);
        }
+
+       dev_warn (&device->cdev->dev, "Device subsystem information: exception"
+               " %s, service %s\n", exception, service);
+out_nomem:
+       kfree(exception);
+       kfree(service);
 }
 
 /*
@@ -1282,46 +1289,44 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
                return;
        if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) {
                if (tape_3590_msg[sense->mc] != NULL)
-                       PRINT_WARN("(%s): %s\n", dev_name(&device->cdev->dev),
-                                  tape_3590_msg[sense->mc]);
-               else {
-                       PRINT_WARN("(%s): Message Code 0x%x\n",
-                                  dev_name(&device->cdev->dev), sense->mc);
-               }
+                       dev_warn (&device->cdev->dev, "The tape unit has "
+                               "issued sense message %s\n",
+                               tape_3590_msg[sense->mc]);
+               else
+                       dev_warn (&device->cdev->dev, "The tape unit has "
+                               "issued an unknown sense message code 0x%x\n",
+                               sense->mc);
                return;
        }
        if (sense->mc == 0xf0) {
                /* Standard Media Information Message */
-               PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, "
-                          "RC=%02x-%04x-%02x\n", dev_name(&device->cdev->dev),
-                          sense->fmt.f70.sev, sense->mc,
-                          sense->fmt.f70.emc, sense->fmt.f70.smc,
-                          sense->fmt.f70.refcode, sense->fmt.f70.mid,
-                          sense->fmt.f70.fid);
+               dev_warn (&device->cdev->dev, "MIM SEV=%i, MC=%02x, ES=%x/%x, "
+                       "RC=%02x-%04x-%02x\n", sense->fmt.f70.sev, sense->mc,
+                       sense->fmt.f70.emc, sense->fmt.f70.smc,
+                       sense->fmt.f70.refcode, sense->fmt.f70.mid,
+                       sense->fmt.f70.fid);
                tape_3590_print_mim_msg_f0(device, irb);
                return;
        }
        if (sense->mc == 0xf1) {
                /* Standard I/O Subsystem Service Information Message */
-               PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, "
-                          "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.sev,
-                          device->cdev->id.dev_model,
-                          sense->mc, sense->fmt.f71.emc,
-                          sense->fmt.f71.smc, sense->fmt.f71.refcode1,
-                          sense->fmt.f71.refcode2, sense->fmt.f71.refcode3);
+               dev_warn (&device->cdev->dev, "IOSIM SEV=%i, DEVTYPE=3590/%02x,"
+                       " MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
+                       sense->fmt.f71.sev, device->cdev->id.dev_model,
+                       sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc,
+                       sense->fmt.f71.refcode1, sense->fmt.f71.refcode2,
+                       sense->fmt.f71.refcode3);
                tape_3590_print_io_sim_msg_f1(device, irb);
                return;
        }
        if (sense->mc == 0xf2) {
                /* Standard Device Service Information Message */
-               PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, "
-                          "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
-                          dev_name(&device->cdev->dev), sense->fmt.f71.sev,
-                          device->cdev->id.dev_model,
-                          sense->mc, sense->fmt.f71.emc,
-                          sense->fmt.f71.smc, sense->fmt.f71.refcode1,
-                          sense->fmt.f71.refcode2, sense->fmt.f71.refcode3);
+               dev_warn (&device->cdev->dev, "DEVSIM SEV=%i, DEVTYPE=3590/%02x"
+                       ", MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",
+                       sense->fmt.f71.sev, device->cdev->id.dev_model,
+                       sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc,
+                       sense->fmt.f71.refcode1, sense->fmt.f71.refcode2,
+                       sense->fmt.f71.refcode3);
                tape_3590_print_dev_sim_msg_f2(device, irb);
                return;
        }
@@ -1329,8 +1334,8 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
                /* Standard Library Service Information Message */
                return;
        }
-       PRINT_WARN("(%s): Device Message(%x)\n",
-                  dev_name(&device->cdev->dev), sense->mc);
+       dev_warn (&device->cdev->dev, "The tape unit has issued an unknown "
+               "sense message code %x\n", sense->mc);
 }
 
 static int tape_3590_crypt_error(struct tape_device *device,
@@ -1355,9 +1360,8 @@ static int tape_3590_crypt_error(struct tape_device *device,
                /* No connection to EKM */
                return tape_3590_erp_basic(device, request, irb, -ENOTCONN);
 
-       PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id);
-       PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc,
-               drv_rc, ekm_rc1, ekm_rc2);
+       dev_err (&device->cdev->dev, "The tape unit failed to obtain the "
+               "encryption key from EKM\n");
 
        return tape_3590_erp_basic(device, request, irb, -ENOKEY);
 }
@@ -1443,8 +1447,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
                 * print additional msg since default msg
                 * "device intervention" is not very meaningfull
                 */
-               PRINT_WARN("(%s): Tape operation when medium not loaded\n",
-                          dev_name(&device->cdev->dev));
                tape_med_state_set(device, MS_UNLOADED);
                tape_3590_schedule_work(device, TO_CRYPT_OFF);
                return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
@@ -1490,19 +1492,13 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
                return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
 
        case 0x6020:
-               PRINT_WARN("(%s): Cartridge of wrong type ?\n",
-                          dev_name(&device->cdev->dev));
                return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE);
 
        case 0x8011:
-               PRINT_WARN("(%s): Another host has reserved the tape device\n",
-                          dev_name(&device->cdev->dev));
                return tape_3590_erp_basic(device, request, irb, -EPERM);
        case 0x8013:
-               PRINT_WARN("(%s): Another host has privileged access to the "
-                          "tape device\n", dev_name(&device->cdev->dev));
-               PRINT_WARN("(%s): To solve the problem unload the current "
-                          "cartridge!\n", dev_name(&device->cdev->dev));
+               dev_warn (&device->cdev->dev, "A different host has privileged"
+                       " access to the tape unit\n");
                return tape_3590_erp_basic(device, request, irb, -EPERM);
        default:
                return tape_3590_erp_basic(device, request, irb, -EIO);
@@ -1552,9 +1548,7 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
        }
 
        DBF_EVENT(6, "xunknownirq\n");
-       PRINT_ERR("Unexpected interrupt.\n");
-       PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]);
-       tape_dump_sense(device, request, irb);
+       tape_dump_sense_dbf(device, request, irb);
        return TAPE_IO_STOP;
 }
 
@@ -1609,7 +1603,6 @@ tape_3590_setup_device(struct tape_device *device)
        if (rc)
                goto fail_rdc_data;
        if (rdc_data->data[31] == 0x13) {
-               PRINT_INFO("Device has crypto support\n");
                data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
                tape_3592_disable_crypt(device);
        } else {
index ae18baf59f06c19fea048c534bd362cfe97af225..f32e89e7c4f2e9f3f1aa54856996c446921e8a9a 100644 (file)
@@ -10,6 +10,8 @@
  *              Stefan Bader <shbader@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "tape"
+
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
@@ -23,8 +25,6 @@
 
 #include "tape.h"
 
-#define PRINTK_HEADER "TAPE_BLOCK: "
-
 #define TAPEBLOCK_MAX_SEC      100
 #define TAPEBLOCK_MIN_REQUEUE  3
 
@@ -279,8 +279,6 @@ tapeblock_cleanup_device(struct tape_device *device)
        tape_put_device(device);
 
        if (!device->blk_data.disk) {
-               PRINT_ERR("(%s): No gendisk to clean up!\n",
-                       dev_name(&device->cdev->dev));
                goto cleanup_queue;
        }
 
@@ -314,7 +312,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
        if (!device->blk_data.medium_changed)
                return 0;
 
-       PRINT_INFO("Detecting media size...\n");
+       dev_info(&device->cdev->dev, "Determining the size of the recorded "
+               "area...\n");
        rc = tape_mtop(device, MTFSFM, 1);
        if (rc)
                return rc;
@@ -341,7 +340,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
        device->bof = rc;
        nr_of_blks -= rc;
 
-       PRINT_INFO("Found %i blocks on media\n", nr_of_blks);
+       dev_info(&device->cdev->dev, "The size of the recorded area is %i "
+               "blocks\n", nr_of_blks);
        set_capacity(device->blk_data.disk,
                nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512));
 
@@ -376,8 +376,8 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
 
        if (device->required_tapemarks) {
                DBF_EVENT(2, "TBLOCK: missing tapemarks\n");
-               PRINT_ERR("TBLOCK: Refusing to open tape with missing"
-                       " end of file marks.\n");
+               dev_warn(&device->cdev->dev, "Opening the tape failed because"
+                       " of missing end-of-file marks\n");
                rc = -EPERM;
                goto put_device;
        }
@@ -452,7 +452,6 @@ tapeblock_ioctl(
                        rc = -EINVAL;
                        break;
                default:
-                       PRINT_WARN("invalid ioctl 0x%x\n", command);
                        rc = -EINVAL;
        }
 
@@ -474,7 +473,6 @@ tapeblock_init(void)
 
        if (tapeblock_major == 0)
                tapeblock_major = rc;
-       PRINT_INFO("tape gets major %d for block device\n", tapeblock_major);
        return 0;
 }
 
index be0ce2215c8de2d1214dd75d0330b850edc84885..31566c55adfe18b7140c127bc87284a5a4353053 100644 (file)
@@ -24,8 +24,6 @@
 #include "tape_std.h"
 #include "tape_class.h"
 
-#define PRINTK_HEADER "TAPE_CHAR: "
-
 #define TAPECHAR_MAJOR         0       /* get dynamic major */
 
 /*
@@ -102,8 +100,6 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
        if (block_size > MAX_BLOCKSIZE) {
                DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n",
                        block_size, MAX_BLOCKSIZE);
-               PRINT_ERR("Invalid blocksize (%zd> %d)\n",
-                       block_size, MAX_BLOCKSIZE);
                return -EINVAL;
        }
 
@@ -485,7 +481,6 @@ tapechar_init (void)
                return -1;
 
        tapechar_major = MAJOR(dev);
-       PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev));
 
        return 0;
 }
@@ -496,7 +491,5 @@ tapechar_init (void)
 void
 tapechar_exit(void)
 {
-       PRINT_INFO("tape releases major %d for character devices\n",
-               tapechar_major);
        unregister_chrdev_region(MKDEV(tapechar_major, 0), 256);
 }
index f9bb51fa7f5bf7bc3a47f4a40554c2571c4bcb8b..08c09d3503cfd5857de8b205d7f561a86f76dada 100644 (file)
@@ -11,6 +11,7 @@
  *              Stefan Bader <shbader@de.ibm.com>
  */
 
+#define KMSG_COMPONENT "tape"
 #include <linux/module.h>
 #include <linux/init.h>             // for kernel parameters
 #include <linux/kmod.h>             // for requesting modules
@@ -25,7 +26,6 @@
 #include "tape.h"
 #include "tape_std.h"
 
-#define PRINTK_HEADER "TAPE_CORE: "
 #define LONG_BUSY_TIMEOUT 180 /* seconds */
 
 static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
@@ -214,13 +214,13 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
        switch(newstate){
        case MS_UNLOADED:
                device->tape_generic_status |= GMT_DR_OPEN(~0);
-               PRINT_INFO("(%s): Tape is unloaded\n",
-                          dev_name(&device->cdev->dev));
+               dev_info(&device->cdev->dev, "The tape cartridge has been "
+                       "successfully unloaded\n");
                break;
        case MS_LOADED:
                device->tape_generic_status &= ~GMT_DR_OPEN(~0);
-               PRINT_INFO("(%s): Tape has been mounted\n",
-                          dev_name(&device->cdev->dev));
+               dev_info(&device->cdev->dev, "A tape cartridge has been "
+                       "mounted\n");
                break;
        default:
                // print nothing
@@ -333,7 +333,6 @@ tape_generic_online(struct tape_device *device,
        /* Let the discipline have a go at the device. */
        device->discipline = discipline;
        if (!try_module_get(discipline->owner)) {
-               PRINT_ERR("Cannot get module. Module gone.\n");
                return -EINVAL;
        }
 
@@ -391,7 +390,6 @@ int
 tape_generic_offline(struct tape_device *device)
 {
        if (!device) {
-               PRINT_ERR("tape_generic_offline: no such device\n");
                return -ENODEV;
        }
 
@@ -413,9 +411,6 @@ tape_generic_offline(struct tape_device *device)
                        DBF_EVENT(3, "(%08x): Set offline failed "
                                "- drive in use.\n",
                                device->cdev_id);
-                       PRINT_WARN("(%s): Set offline failed "
-                               "- drive in use.\n",
-                               dev_name(&device->cdev->dev));
                        spin_unlock_irq(get_ccwdev_lock(device->cdev));
                        return -EBUSY;
        }
@@ -435,14 +430,11 @@ tape_alloc_device(void)
        device = kzalloc(sizeof(struct tape_device), GFP_KERNEL);
        if (device == NULL) {
                DBF_EXCEPTION(2, "ti:no mem\n");
-               PRINT_INFO ("can't allocate memory for "
-                           "tape info structure\n");
                return ERR_PTR(-ENOMEM);
        }
        device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA);
        if (device->modeset_byte == NULL) {
                DBF_EXCEPTION(2, "ti:no mem\n");
-               PRINT_INFO("can't allocate memory for modeset byte\n");
                kfree(device);
                return ERR_PTR(-ENOMEM);
        }
@@ -490,7 +482,6 @@ tape_put_device(struct tape_device *device)
        } else {
                if (remain < 0) {
                        DBF_EVENT(4, "put device without reference\n");
-                       PRINT_ERR("put device without reference\n");
                } else {
                        DBF_EVENT(4, "tape_free_device(%p)\n", device);
                        kfree(device->modeset_byte);
@@ -538,8 +529,6 @@ tape_generic_probe(struct ccw_device *cdev)
        ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
        if (ret) {
                tape_put_device(device);
-               PRINT_ERR("probe failed for tape device %s\n",
-                         dev_name(&cdev->dev));
                return ret;
        }
        cdev->dev.driver_data = device;
@@ -547,7 +536,6 @@ tape_generic_probe(struct ccw_device *cdev)
        device->cdev = cdev;
        ccw_device_get_id(cdev, &dev_id);
        device->cdev_id = devid_to_int(&dev_id);
-       PRINT_INFO("tape device %s found\n", dev_name(&cdev->dev));
        return ret;
 }
 
@@ -584,7 +572,6 @@ tape_generic_remove(struct ccw_device *cdev)
 
        device = cdev->dev.driver_data;
        if (!device) {
-               PRINT_ERR("No device pointer in tape_generic_remove!\n");
                return;
        }
        DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev);
@@ -615,10 +602,8 @@ tape_generic_remove(struct ccw_device *cdev)
                         */
                        DBF_EVENT(3, "(%08x): Drive in use vanished!\n",
                                device->cdev_id);
-                       PRINT_WARN("(%s): Drive in use vanished - "
-                               "expect trouble!\n",
-                               dev_name(&device->cdev->dev));
-                       PRINT_WARN("State was %i\n", device->tape_state);
+                       dev_warn(&device->cdev->dev, "A tape unit was detached"
+                               " while in use\n");
                        tape_state_set(device, TS_NOT_OPER);
                        __tape_discard_requests(device);
                        spin_unlock_irq(get_ccwdev_lock(device->cdev));
@@ -639,8 +624,7 @@ tape_alloc_request(int cplength, int datasize)
 {
        struct tape_request *request;
 
-       if (datasize > PAGE_SIZE || (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
-               BUG();
+       BUG_ON(datasize > PAGE_SIZE || (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
 
        DBF_LH(6, "tape_alloc_request(%d, %d)\n", cplength, datasize);
 
@@ -797,8 +781,7 @@ static void tape_long_busy_timeout(unsigned long data)
        device = (struct tape_device *) data;
        spin_lock_irq(get_ccwdev_lock(device->cdev));
        request = list_entry(device->req_queue.next, struct tape_request, list);
-       if (request->status != TAPE_REQUEST_LONG_BUSY)
-               BUG();
+       BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY);
        DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
        __tape_start_next_request(device);
        device->lb_timeout.data = (unsigned long) tape_put_device(device);
@@ -829,30 +812,6 @@ __tape_end_request(
                __tape_start_next_request(device);
 }
 
-/*
- * Write sense data to console/dbf
- */
-void
-tape_dump_sense(struct tape_device* device, struct tape_request *request,
-               struct irb *irb)
-{
-       unsigned int *sptr;
-
-       PRINT_INFO("-------------------------------------------------\n");
-       PRINT_INFO("DSTAT : %02x  CSTAT: %02x   CPA: %04x\n",
-                  irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa);
-       PRINT_INFO("DEVICE: %s\n", dev_name(&device->cdev->dev));
-       if (request != NULL)
-               PRINT_INFO("OP    : %s\n", tape_op_verbose[request->op]);
-
-       sptr = (unsigned int *) irb->ecw;
-       PRINT_INFO("Sense data: %08X %08X %08X %08X \n",
-                  sptr[0], sptr[1], sptr[2], sptr[3]);
-       PRINT_INFO("Sense data: %08X %08X %08X %08X \n",
-                  sptr[4], sptr[5], sptr[6], sptr[7]);
-       PRINT_INFO("--------------------------------------------------\n");
-}
-
 /*
  * Write sense data to dbf
  */
@@ -1051,8 +1010,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 
        device = (struct tape_device *) cdev->dev.driver_data;
        if (device == NULL) {
-               PRINT_ERR("could not get device structure for %s "
-                         "in interrupt\n", dev_name(&cdev->dev));
                return;
        }
        request = (struct tape_request *) intparm;
@@ -1064,13 +1021,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                /* FIXME: What to do with the request? */
                switch (PTR_ERR(irb)) {
                        case -ETIMEDOUT:
-                               PRINT_WARN("(%s): Request timed out\n",
+                               DBF_LH(1, "(%s): Request timed out\n",
                                        dev_name(&cdev->dev));
                        case -EIO:
                                __tape_end_request(device, request, -EIO);
                                break;
                        default:
-                               PRINT_ERR("(%s): Unexpected i/o error %li\n",
+                               DBF_LH(1, "(%s): Unexpected i/o error %li\n",
                                        dev_name(&cdev->dev),
                                        PTR_ERR(irb));
                }
@@ -1182,8 +1139,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                default:
                        if (rc > 0) {
                                DBF_EVENT(6, "xunknownrc\n");
-                               PRINT_ERR("Invalid return code from discipline "
-                                       "interrupt function.\n");
                                __tape_end_request(device, request, -EIO);
                        } else {
                                __tape_end_request(device, request, rc);
@@ -1323,7 +1278,6 @@ EXPORT_SYMBOL(tape_state_set);
 EXPORT_SYMBOL(tape_med_state_set);
 EXPORT_SYMBOL(tape_alloc_request);
 EXPORT_SYMBOL(tape_free_request);
-EXPORT_SYMBOL(tape_dump_sense);
 EXPORT_SYMBOL(tape_dump_sense_dbf);
 EXPORT_SYMBOL(tape_do_io);
 EXPORT_SYMBOL(tape_do_io_async);
index 8a376af926a7407389d1643350afdf42814e726a..202f42132939009e54f4b32a53ddad7c3e280aaf 100644 (file)
@@ -20,8 +20,6 @@
 
 #include "tape.h"
 
-#define PRINTK_HEADER "TAPE_PROC: "
-
 static const char *tape_med_st_verbose[MS_SIZE] =
 {
        [MS_UNKNOWN] = "UNKNOWN ",
@@ -128,7 +126,6 @@ tape_proc_init(void)
                proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL,
                            &tape_proc_ops);
        if (tape_proc_devices == NULL) {
-               PRINT_WARN("tape: Cannot register procfs entry tapedevices\n");
                return;
        }
 }
index 5bd573d144d6d880a4e130469e6e937b163e5ffa..1a9420ba518d66cb767bba6d1b9d0e8cd4d3dc7b 100644 (file)
@@ -26,8 +26,6 @@
 #include "tape.h"
 #include "tape_std.h"
 
-#define PRINTK_HEADER "TAPE_STD: "
-
 /*
  * tape_std_assign
  */
@@ -39,16 +37,15 @@ tape_std_assign_timeout(unsigned long data)
        int rc;
 
        request = (struct tape_request *) data;
-       if ((device = request->device) == NULL)
-               BUG();
+       device = request->device;
+       BUG_ON(!device);
 
        DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
                        device->cdev_id);
        rc = tape_cancel_io(device, request);
        if(rc)
-               PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n",
+               DBF_EVENT(3, "(%s): Assign timeout: Cancel failed with rc = %i\n",
                        dev_name(&device->cdev->dev), rc);
-
 }
 
 int
@@ -82,8 +79,6 @@ tape_std_assign(struct tape_device *device)
        del_timer(&timeout);
 
        if (rc != 0) {
-               PRINT_WARN("%s: assign failed - device might be busy\n",
-                       dev_name(&device->cdev->dev));
                DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
                        device->cdev_id);
        } else {
@@ -105,8 +100,6 @@ tape_std_unassign (struct tape_device *device)
        if (device->tape_state == TS_NOT_OPER) {
                DBF_EVENT(3, "(%08x): Can't unassign device\n",
                        device->cdev_id);
-               PRINT_WARN("(%s): Can't unassign device - device gone\n",
-                       dev_name(&device->cdev->dev));
                return -EIO;
        }
 
@@ -120,8 +113,6 @@ tape_std_unassign (struct tape_device *device)
 
        if ((rc = tape_do_io(device, request)) != 0) {
                DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id);
-               PRINT_WARN("%s: Unassign failed\n",
-                          dev_name(&device->cdev->dev));
        } else {
                DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id);
        }
@@ -242,8 +233,6 @@ tape_std_mtsetblk(struct tape_device *device, int count)
        if (count > MAX_BLOCKSIZE) {
                DBF_EVENT(3, "Invalid block size (%d > %d) given.\n",
                        count, MAX_BLOCKSIZE);
-               PRINT_ERR("Invalid block size (%d > %d) given.\n",
-                       count, MAX_BLOCKSIZE);
                return -EINVAL;
        }
 
@@ -633,14 +622,6 @@ tape_std_mtcompression(struct tape_device *device, int mt_count)
 
        if (mt_count < 0 || mt_count > 1) {
                DBF_EXCEPTION(6, "xcom parm\n");
-               if (*device->modeset_byte & 0x08)
-                       PRINT_INFO("(%s) Compression is currently on\n",
-                                  dev_name(&device->cdev->dev));
-               else
-                       PRINT_INFO("(%s) Compression is currently off\n",
-                                  dev_name(&device->cdev->dev));
-               PRINT_INFO("Use 1 to switch compression on, 0 to "
-                          "switch it off\n");
                return -EINVAL;
        }
        request = tape_alloc_request(2, 0);
index eefc6611412e120fd3b5ad896ca3c0a426f9d4b0..1bbae433fbd85bd20856f0882324d5da037c6d1f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * For more information please refer to Documentation/s390/zfcpdump.txt
  *
- * Copyright IBM Corp. 2003,2007
+ * Copyright IBM Corp. 2003,2008
  * Author(s): Michael Holzheu
  */
 
@@ -24,6 +24,7 @@
 #include <asm/debug.h>
 #include <asm/processor.h>
 #include <asm/irqflags.h>
+#include <asm/checksum.h>
 #include "sclp.h"
 
 #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
@@ -48,12 +49,19 @@ struct sys_info {
        union save_area lc_mask;
 };
 
+struct ipib_info {
+       unsigned long   ipib;
+       u32             checksum;
+}  __attribute__((packed));
+
 static struct sys_info sys_info;
 static struct debug_info *zcore_dbf;
 static int hsa_available;
 static struct dentry *zcore_dir;
 static struct dentry *zcore_file;
 static struct dentry *zcore_memmap_file;
+static struct dentry *zcore_reipl_file;
+static struct ipl_parameter_block *ipl_block;
 
 /*
  * Copy memory from HSA to kernel or user memory (not reentrant):
@@ -527,6 +535,33 @@ static const struct file_operations zcore_memmap_fops = {
        .release        = zcore_memmap_release,
 };
 
+static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       if (ipl_block) {
+               diag308(DIAG308_SET, ipl_block);
+               diag308(DIAG308_IPL, NULL);
+       }
+       return count;
+}
+
+static int zcore_reipl_open(struct inode *inode, struct file *filp)
+{
+       return 0;
+}
+
+static int zcore_reipl_release(struct inode *inode, struct file *filp)
+{
+       return 0;
+}
+
+static const struct file_operations zcore_reipl_fops = {
+       .owner          = THIS_MODULE,
+       .write          = zcore_reipl_write,
+       .open           = zcore_reipl_open,
+       .release        = zcore_reipl_release,
+};
+
 
 static void __init set_s390_lc_mask(union save_area *map)
 {
@@ -645,6 +680,40 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr)
        return 0;
 }
 
+/*
+ * Provide IPL parameter information block from either HSA or memory
+ * for future reipl
+ */
+static int __init zcore_reipl_init(void)
+{
+       struct ipib_info ipib_info;
+       int rc;
+
+       rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info));
+       if (rc)
+               return rc;
+       if (ipib_info.ipib == 0)
+               return 0;
+       ipl_block = (void *) __get_free_page(GFP_KERNEL);
+       if (!ipl_block)
+               return -ENOMEM;
+       if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE)
+               rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
+       else
+               rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE);
+       if (rc) {
+               free_page((unsigned long) ipl_block);
+               return rc;
+       }
+       if (csum_partial(ipl_block, ipl_block->hdr.len, 0) !=
+           ipib_info.checksum) {
+               TRACE("Checksum does not match\n");
+               free_page((unsigned long) ipl_block);
+               ipl_block = NULL;
+       }
+       return 0;
+}
+
 static int __init zcore_init(void)
 {
        unsigned char arch;
@@ -690,6 +759,10 @@ static int __init zcore_init(void)
        if (rc)
                goto fail;
 
+       rc = zcore_reipl_init();
+       if (rc)
+               goto fail;
+
        zcore_dir = debugfs_create_dir("zcore" , NULL);
        if (!zcore_dir) {
                rc = -ENOMEM;
@@ -707,9 +780,17 @@ static int __init zcore_init(void)
                rc = -ENOMEM;
                goto fail_file;
        }
+       zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir,
+                                               NULL, &zcore_reipl_fops);
+       if (!zcore_reipl_file) {
+               rc = -ENOMEM;
+               goto fail_memmap_file;
+       }
        hsa_available = 1;
        return 0;
 
+fail_memmap_file:
+       debugfs_remove(zcore_memmap_file);
 fail_file:
        debugfs_remove(zcore_file);
 fail_dir:
@@ -723,10 +804,15 @@ static void __exit zcore_exit(void)
 {
        debug_unregister(zcore_dbf);
        sclp_sdias_exit();
+       free_page((unsigned long) ipl_block);
+       debugfs_remove(zcore_reipl_file);
+       debugfs_remove(zcore_memmap_file);
+       debugfs_remove(zcore_file);
+       debugfs_remove(zcore_dir);
        diag308(DIAG308_REL_HSA, NULL);
 }
 
-MODULE_AUTHOR("Copyright IBM Corp. 2003,2007");
+MODULE_AUTHOR("Copyright IBM Corp. 2003,2008");
 MODULE_DESCRIPTION("zcore module for zfcpdump support");
 MODULE_LICENSE("GPL");
 
index bd79bd1653963c785de07f8d890395f021d61470..adb3dd3015284c10abd075b2609a7aa40befa040 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \
-       fcx.o itcw.o
+       fcx.o itcw.o crw.o
 ccw_device-objs += device.o device_fsm.o device_ops.o
 ccw_device-objs += device_id.o device_pgid.o device_status.o
 obj-y += ccw_device.o cmf.o
index fe6cea15bbaff371fd9daa9926438bf01480f881..65d2e769dfa16123ff0a50593ef0797ff670e8f5 100644 (file)
@@ -34,8 +34,8 @@ struct airq_t {
        void *drv_data;
 };
 
-static union indicator_t indicators[MAX_ISC];
-static struct airq_t *airqs[MAX_ISC][NR_AIRQS];
+static union indicator_t indicators[MAX_ISC+1];
+static struct airq_t *airqs[MAX_ISC+1][NR_AIRQS];
 
 static int register_airq(struct airq_t *airq, u8 isc)
 {
@@ -133,6 +133,8 @@ void do_adapter_IO(u8 isc)
                while (word) {
                        if (word & INDICATOR_MASK) {
                                airq = airqs[isc][i];
+                               /* Make sure gcc reads from airqs only once. */
+                               barrier();
                                if (likely(airq))
                                        airq->handler(&indicators[isc].byte[i],
                                                      airq->drv_data);
index fe00be3675cd6757c7a84d6aec6f58e99947485c..6565f027791eb5fe8bb91616ac6218a170c91c54 100644 (file)
@@ -336,8 +336,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
                 size_t user_len, loff_t *offset)
 {
        char *buf;
-       size_t i;
-       ssize_t rc, ret;
+       ssize_t rc, ret, i;
 
        if (*offset)
                return -EINVAL;
index b91c1719b07563db660db3522b057bcd3373c49d..22ce765d537e9f0bccbca4c769131c07b3c03574 100644 (file)
@@ -315,16 +315,32 @@ error:
 }
 EXPORT_SYMBOL(ccwgroup_create_from_string);
 
-static int __init
-init_ccwgroup (void)
+static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
+                            void *data);
+
+static struct notifier_block ccwgroup_nb = {
+       .notifier_call = ccwgroup_notifier
+};
+
+static int __init init_ccwgroup(void)
 {
-       return bus_register (&ccwgroup_bus_type);
+       int ret;
+
+       ret = bus_register(&ccwgroup_bus_type);
+       if (ret)
+               return ret;
+
+       ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb);
+       if (ret)
+               bus_unregister(&ccwgroup_bus_type);
+
+       return ret;
 }
 
-static void __exit
-cleanup_ccwgroup (void)
+static void __exit cleanup_ccwgroup(void)
 {
-       bus_unregister (&ccwgroup_bus_type);
+       bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb);
+       bus_unregister(&ccwgroup_bus_type);
 }
 
 module_init(init_ccwgroup);
@@ -392,27 +408,28 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const
        unsigned long value;
        int ret;
 
-       gdev = to_ccwgroupdev(dev);
        if (!dev->driver)
-               return count;
+               return -ENODEV;
+
+       gdev = to_ccwgroupdev(dev);
+       gdrv = to_ccwgroupdrv(dev->driver);
 
-       gdrv = to_ccwgroupdrv (gdev->dev.driver);
        if (!try_module_get(gdrv->owner))
                return -EINVAL;
 
        ret = strict_strtoul(buf, 0, &value);
        if (ret)
                goto out;
-       ret = count;
+
        if (value == 1)
-               ccwgroup_set_online(gdev);
+               ret = ccwgroup_set_online(gdev);
        else if (value == 0)
-               ccwgroup_set_offline(gdev);
+               ret = ccwgroup_set_offline(gdev);
        else
                ret = -EINVAL;
 out:
        module_put(gdrv->owner);
-       return ret;
+       return (ret == 0) ? count : ret;
 }
 
 static ssize_t
@@ -454,13 +471,18 @@ ccwgroup_remove (struct device *dev)
        struct ccwgroup_device *gdev;
        struct ccwgroup_driver *gdrv;
 
+       device_remove_file(dev, &dev_attr_online);
+       device_remove_file(dev, &dev_attr_ungroup);
+
+       if (!dev->driver)
+               return 0;
+
        gdev = to_ccwgroupdev(dev);
        gdrv = to_ccwgroupdrv(dev->driver);
 
-       device_remove_file(dev, &dev_attr_online);
-
-       if (gdrv && gdrv->remove)
+       if (gdrv->remove)
                gdrv->remove(gdev);
+
        return 0;
 }
 
@@ -469,9 +491,13 @@ static void ccwgroup_shutdown(struct device *dev)
        struct ccwgroup_device *gdev;
        struct ccwgroup_driver *gdrv;
 
+       if (!dev->driver)
+               return;
+
        gdev = to_ccwgroupdev(dev);
        gdrv = to_ccwgroupdrv(dev->driver);
-       if (gdrv && gdrv->shutdown)
+
+       if (gdrv->shutdown)
                gdrv->shutdown(gdev);
 }
 
@@ -484,6 +510,19 @@ static struct bus_type ccwgroup_bus_type = {
        .shutdown = ccwgroup_shutdown,
 };
 
+
+static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
+                            void *data)
+{
+       struct device *dev = data;
+
+       if (action == BUS_NOTIFY_UNBIND_DRIVER)
+               device_schedule_callback(dev, ccwgroup_ungroup_callback);
+
+       return NOTIFY_OK;
+}
+
+
 /**
  * ccwgroup_driver_register() - register a ccw group driver
  * @cdriver: driver to be registered
index 1246f61a5338afadca17a9debd0ce4217f8af336..3e5f304ad88fea3d10598c2e88223472f8a4d113 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/errno.h>
 #include <asm/chpid.h>
 #include <asm/sclp.h>
+#include <asm/crw.h>
 
-#include "../s390mach.h"
 #include "cio.h"
 #include "css.h"
 #include "ioasm.h"
@@ -706,12 +706,12 @@ static int __init chp_init(void)
        struct chp_id chpid;
        int ret;
 
-       ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw);
+       ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw);
        if (ret)
                return ret;
        chp_wq = create_singlethread_workqueue("cio_chp");
        if (!chp_wq) {
-               s390_unregister_crw_handler(CRW_RSC_CPATH);
+               crw_unregister_handler(CRW_RSC_CPATH);
                return -ENOMEM;
        }
        INIT_WORK(&cfg_work, cfg_func);
index ebab6ea4659b783ed37e8b87d1332c8fed864517..883f16f96f2286ffaa8b617cef0227b239b61799 100644 (file)
@@ -19,8 +19,8 @@
 #include <asm/cio.h>
 #include <asm/chpid.h>
 #include <asm/chsc.h>
+#include <asm/crw.h>
 
-#include "../s390mach.h"
 #include "css.h"
 #include "cio.h"
 #include "cio_debug.h"
@@ -589,6 +589,7 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
        case 0x0102:
        case 0x0103:
                ret = -EINVAL;
+               break;
        default:
                ret = chsc_error_from_response(secm_area->response.code);
        }
@@ -820,7 +821,7 @@ int __init chsc_alloc_sei_area(void)
                              "chsc machine checks!\n");
                return -ENOMEM;
        }
-       ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw);
+       ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw);
        if (ret)
                kfree(sei_page);
        return ret;
@@ -828,7 +829,7 @@ int __init chsc_alloc_sei_area(void)
 
 void __init chsc_free_sei_area(void)
 {
-       s390_unregister_crw_handler(CRW_RSC_CSS);
+       crw_unregister_handler(CRW_RSC_CSS);
        kfree(sei_page);
 }
 
index 659f8a791656f472a22c18a99c14e45211185c97..2aebb9823044765427ceb806118b921276b94dbb 100644 (file)
@@ -30,6 +30,8 @@
 #include <asm/isc.h>
 #include <asm/cpu.h>
 #include <asm/fcx.h>
+#include <asm/nmi.h>
+#include <asm/crw.h>
 #include "cio.h"
 #include "css.h"
 #include "chsc.h"
@@ -38,7 +40,6 @@
 #include "blacklist.h"
 #include "cio_debug.h"
 #include "chp.h"
-#include "../s390mach.h"
 
 debug_info_t *cio_debug_msg_id;
 debug_info_t *cio_debug_trace_id;
@@ -471,6 +472,7 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
 int cio_disable_subchannel(struct subchannel *sch)
 {
        char dbf_txt[15];
+       int retry;
        int ret;
 
        CIO_TRACE_EVENT (2, "dissch");
@@ -481,16 +483,17 @@ int cio_disable_subchannel(struct subchannel *sch)
        if (cio_update_schib(sch))
                return -ENODEV;
 
-       if (scsw_actl(&sch->schib.scsw) != 0)
-               /*
-                * the disable function must not be called while there are
-                *  requests pending for completion !
-                */
-               return -EBUSY;
-
        sch->config.ena = 0;
-       ret = cio_commit_config(sch);
 
+       for (retry = 0; retry < 3; retry++) {
+               ret = cio_commit_config(sch);
+               if (ret == -EBUSY) {
+                       struct irb irb;
+                       if (tsch(sch->schid, &irb) != 0)
+                               break;
+               } else
+                       break;
+       }
        sprintf (dbf_txt, "ret:%d", ret);
        CIO_TRACE_EVENT (2, dbf_txt);
        return ret;
diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c
new file mode 100644 (file)
index 0000000..d157665
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *   Channel report handling code
+ *
+ *    Copyright IBM Corp. 2000,2009
+ *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *              Cornelia Huck <cornelia.huck@de.ibm.com>,
+ *              Heiko Carstens <heiko.carstens@de.ibm.com>,
+ */
+
+#include <linux/semaphore.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+#include <asm/crw.h>
+
+static struct semaphore crw_semaphore;
+static DEFINE_MUTEX(crw_handler_mutex);
+static crw_handler_t crw_handlers[NR_RSCS];
+
+/**
+ * crw_register_handler() - register a channel report word handler
+ * @rsc: reporting source code to handle
+ * @handler: handler to be registered
+ *
+ * Returns %0 on success and a negative error value otherwise.
+ */
+int crw_register_handler(int rsc, crw_handler_t handler)
+{
+       int rc = 0;
+
+       if ((rsc < 0) || (rsc >= NR_RSCS))
+               return -EINVAL;
+       mutex_lock(&crw_handler_mutex);
+       if (crw_handlers[rsc])
+               rc = -EBUSY;
+       else
+               crw_handlers[rsc] = handler;
+       mutex_unlock(&crw_handler_mutex);
+       return rc;
+}
+
+/**
+ * crw_unregister_handler() - unregister a channel report word handler
+ * @rsc: reporting source code to handle
+ */
+void crw_unregister_handler(int rsc)
+{
+       if ((rsc < 0) || (rsc >= NR_RSCS))
+               return;
+       mutex_lock(&crw_handler_mutex);
+       crw_handlers[rsc] = NULL;
+       mutex_unlock(&crw_handler_mutex);
+}
+
+/*
+ * Retrieve CRWs and call function to handle event.
+ */
+static int crw_collect_info(void *unused)
+{
+       struct crw crw[2];
+       int ccode;
+       unsigned int chain;
+       int ignore;
+
+repeat:
+       ignore = down_interruptible(&crw_semaphore);
+       chain = 0;
+       while (1) {
+               crw_handler_t handler;
+
+               if (unlikely(chain > 1)) {
+                       struct crw tmp_crw;
+
+                       printk(KERN_WARNING"%s: Code does not support more "
+                              "than two chained crws; please report to "
+                              "linux390@de.ibm.com!\n", __func__);
+                       ccode = stcrw(&tmp_crw);
+                       printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+                              "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+                              __func__, tmp_crw.slct, tmp_crw.oflw,
+                              tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+                              tmp_crw.erc, tmp_crw.rsid);
+                       printk(KERN_WARNING"%s: This was crw number %x in the "
+                              "chain\n", __func__, chain);
+                       if (ccode != 0)
+                               break;
+                       chain = tmp_crw.chn ? chain + 1 : 0;
+                       continue;
+               }
+               ccode = stcrw(&crw[chain]);
+               if (ccode != 0)
+                       break;
+               printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
+                      "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+                      crw[chain].slct, crw[chain].oflw, crw[chain].chn,
+                      crw[chain].rsc, crw[chain].anc, crw[chain].erc,
+                      crw[chain].rsid);
+               /* Check for overflows. */
+               if (crw[chain].oflw) {
+                       int i;
+
+                       pr_debug("%s: crw overflow detected!\n", __func__);
+                       mutex_lock(&crw_handler_mutex);
+                       for (i = 0; i < NR_RSCS; i++) {
+                               if (crw_handlers[i])
+                                       crw_handlers[i](NULL, NULL, 1);
+                       }
+                       mutex_unlock(&crw_handler_mutex);
+                       chain = 0;
+                       continue;
+               }
+               if (crw[0].chn && !chain) {
+                       chain++;
+                       continue;
+               }
+               mutex_lock(&crw_handler_mutex);
+               handler = crw_handlers[crw[chain].rsc];
+               if (handler)
+                       handler(&crw[0], chain ? &crw[1] : NULL, 0);
+               mutex_unlock(&crw_handler_mutex);
+               /* chain is always 0 or 1 here. */
+               chain = crw[chain].chn ? chain + 1 : 0;
+       }
+       goto repeat;
+       return 0;
+}
+
+void crw_handle_channel_report(void)
+{
+       up(&crw_semaphore);
+}
+
+/*
+ * Separate initcall needed for semaphore initialization since
+ * crw_handle_channel_report might be called before crw_machine_check_init.
+ */
+static int __init crw_init_semaphore(void)
+{
+       init_MUTEX_LOCKED(&crw_semaphore);
+       return 0;
+}
+pure_initcall(crw_init_semaphore);
+
+/*
+ * Machine checks for the channel subsystem must be enabled
+ * after the channel subsystem is initialized
+ */
+static int __init crw_machine_check_init(void)
+{
+       struct task_struct *task;
+
+       task = kthread_run(crw_collect_info, NULL, "kmcheck");
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       ctl_set_bit(14, 28);    /* enable channel report MCH */
+       return 0;
+}
+device_initcall(crw_machine_check_init);
index 427d11d88069c24cc4f2c77170aa36f6f6d95733..0085d89017924c13d0b1ab0686cd3bb7571ba190 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/list.h>
 #include <linux/reboot.h>
 #include <asm/isc.h>
+#include <asm/crw.h>
 
-#include "../s390mach.h"
 #include "css.h"
 #include "cio.h"
 #include "cio_debug.h"
@@ -83,6 +83,25 @@ static int call_fn_unknown_sch(struct subchannel_id schid, void *data)
        return rc;
 }
 
+static int call_fn_all_sch(struct subchannel_id schid, void *data)
+{
+       struct cb_data *cb = data;
+       struct subchannel *sch;
+       int rc = 0;
+
+       sch = get_subchannel_by_schid(schid);
+       if (sch) {
+               if (cb->fn_known_sch)
+                       rc = cb->fn_known_sch(sch, cb->data);
+               put_device(&sch->dev);
+       } else {
+               if (cb->fn_unknown_sch)
+                       rc = cb->fn_unknown_sch(schid, cb->data);
+       }
+
+       return rc;
+}
+
 int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
                               int (*fn_unknown)(struct subchannel_id,
                               void *), void *data)
@@ -90,13 +109,17 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
        struct cb_data cb;
        int rc;
 
-       cb.set = idset_sch_new();
-       if (!cb.set)
-               return -ENOMEM;
-       idset_fill(cb.set);
        cb.data = data;
        cb.fn_known_sch = fn_known;
        cb.fn_unknown_sch = fn_unknown;
+
+       cb.set = idset_sch_new();
+       if (!cb.set)
+               /* fall back to brute force scanning in case of oom */
+               return for_each_subchannel(call_fn_all_sch, &cb);
+
+       idset_fill(cb.set);
+
        /* Process registered subchannels. */
        rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch);
        if (rc)
@@ -510,6 +533,17 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data)
        return ret;
 }
 
+static void reprobe_after_idle(struct work_struct *unused)
+{
+       /* Make sure initial subchannel scan is done. */
+       wait_event(ccw_device_init_wq,
+                  atomic_read(&ccw_device_init_count) == 0);
+       if (need_reprobe)
+               css_schedule_reprobe();
+}
+
+static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle);
+
 /* Work function used to reprobe all unregistered subchannels. */
 static void reprobe_all(struct work_struct *unused)
 {
@@ -517,10 +551,12 @@ static void reprobe_all(struct work_struct *unused)
 
        CIO_MSG_EVENT(4, "reprobe start\n");
 
-       need_reprobe = 0;
        /* Make sure initial subchannel scan is done. */
-       wait_event(ccw_device_init_wq,
-                  atomic_read(&ccw_device_init_count) == 0);
+       if (atomic_read(&ccw_device_init_count) != 0) {
+               queue_work(ccw_device_work, &reprobe_idle_work);
+               return;
+       }
+       need_reprobe = 0;
        ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL);
 
        CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
@@ -619,7 +655,7 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
                css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
        } else {
 #ifdef CONFIG_SMP
-               css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id();
+               css->global_pgid.pgid_high.cpu_addr = stap();
 #else
                css->global_pgid.pgid_high.cpu_addr = 0;
 #endif
@@ -765,7 +801,7 @@ init_channel_subsystem (void)
        if (ret)
                goto out;
 
-       ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw);
+       ret = crw_register_handler(CRW_RSC_SCH, css_process_crw);
        if (ret)
                goto out;
 
@@ -845,7 +881,7 @@ out_unregister:
 out_bus:
        bus_unregister(&css_bus_type);
 out:
-       s390_unregister_crw_handler(CRW_RSC_CSS);
+       crw_unregister_handler(CRW_RSC_CSS);
        chsc_free_sei_area();
        kfree(slow_subchannel_set);
        pr_alert("The CSS device driver initialization failed with "
index e28f8ae534539c4014b095409ed51017504a0868..c4d2f667a2f685a8c887ca82d2e3346efb783125 100644 (file)
@@ -457,12 +457,13 @@ int ccw_device_set_online(struct ccw_device *cdev)
        return (ret == 0) ? -ENODEV : ret;
 }
 
-static void online_store_handle_offline(struct ccw_device *cdev)
+static int online_store_handle_offline(struct ccw_device *cdev)
 {
        if (cdev->private->state == DEV_STATE_DISCONNECTED)
                ccw_device_remove_disconnected(cdev);
-       else if (cdev->drv && cdev->drv->set_offline)
-               ccw_device_set_offline(cdev);
+       else if (cdev->online && cdev->drv && cdev->drv->set_offline)
+               return ccw_device_set_offline(cdev);
+       return 0;
 }
 
 static int online_store_recog_and_online(struct ccw_device *cdev)
@@ -530,13 +531,10 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
                goto out;
        switch (i) {
        case 0:
-               online_store_handle_offline(cdev);
-               ret = count;
+               ret = online_store_handle_offline(cdev);
                break;
        case 1:
                ret = online_store_handle_online(cdev, force);
-               if (!ret)
-                       ret = count;
                break;
        default:
                ret = -EINVAL;
@@ -545,7 +543,7 @@ out:
        if (cdev->drv)
                module_put(cdev->drv->owner);
        atomic_set(&cdev->private->onoff, 0);
-       return ret;
+       return (ret < 0) ? ret : count;
 }
 
 static ssize_t
@@ -681,35 +679,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
        return dev ? to_ccwdev(dev) : NULL;
 }
 
-static void
-ccw_device_add_changed(struct work_struct *work)
-{
-       struct ccw_device_private *priv;
-       struct ccw_device *cdev;
-
-       priv = container_of(work, struct ccw_device_private, kick_work);
-       cdev = priv->cdev;
-       if (device_add(&cdev->dev)) {
-               put_device(&cdev->dev);
-               return;
-       }
-       set_bit(1, &cdev->private->registered);
-}
-
-void ccw_device_do_unreg_rereg(struct work_struct *work)
+void ccw_device_do_unbind_bind(struct work_struct *work)
 {
        struct ccw_device_private *priv;
        struct ccw_device *cdev;
        struct subchannel *sch;
+       int ret;
 
        priv = container_of(work, struct ccw_device_private, kick_work);
        cdev = priv->cdev;
        sch = to_subchannel(cdev->dev.parent);
 
-       ccw_device_unregister(cdev);
-       PREPARE_WORK(&cdev->private->kick_work,
-                    ccw_device_add_changed);
-       queue_work(ccw_device_work, &cdev->private->kick_work);
+       if (test_bit(1, &cdev->private->registered)) {
+               device_release_driver(&cdev->dev);
+               ret = device_attach(&cdev->dev);
+               WARN_ON(ret == -ENODEV);
+       }
 }
 
 static void
@@ -1035,8 +1020,6 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
 void
 io_subchannel_recog_done(struct ccw_device *cdev)
 {
-       struct subchannel *sch;
-
        if (css_init_done == 0) {
                cdev->private->flags.recog_done = 1;
                return;
@@ -1047,7 +1030,6 @@ io_subchannel_recog_done(struct ccw_device *cdev)
                /* Remove device found not operational. */
                if (!get_device(&cdev->dev))
                        break;
-               sch = to_subchannel(cdev->dev.parent);
                PREPARE_WORK(&cdev->private->kick_work,
                             ccw_device_call_sch_unregister);
                queue_work(slow_path_wq, &cdev->private->kick_work);
index 0f2e63ea48deee03511be167208aa5d2742b4d09..85e01846ca658ca1ea6154985d9b142687937d6d 100644 (file)
@@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch);
 
 int ccw_device_cancel_halt_clear(struct ccw_device *);
 
-void ccw_device_do_unreg_rereg(struct work_struct *);
+void ccw_device_do_unbind_bind(struct work_struct *);
 void ccw_device_move_to_orphanage(struct work_struct *);
 int ccw_device_is_orphan(struct ccw_device *);
 
index 8df5eaafc5ab6a4c4518f5eacaa3b22e680e5af0..87b4bfca080f86436691f5b08fcb539e37482c74 100644 (file)
@@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev)
            cdev->id.dev_type != cdev->private->senseid.dev_type ||
            cdev->id.dev_model != cdev->private->senseid.dev_model) {
                PREPARE_WORK(&cdev->private->kick_work,
-                            ccw_device_do_unreg_rereg);
+                            ccw_device_do_unbind_bind);
                queue_work(ccw_device_work, &cdev->private->kick_work);
                return 0;
        }
@@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev)
        }
        /* Driver doesn't want device back. */
        ccw_device_set_notoper(cdev);
-       PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg);
+       PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind);
        queue_work(ccw_device_work, &cdev->private->kick_work);
 }
 
@@ -728,7 +728,7 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev,
 {
        struct subchannel *sch;
 
-       cdev->private->state = DEV_STATE_NOT_OPER;
+       ccw_device_set_notoper(cdev);
        sch = to_subchannel(cdev->dev.parent);
        css_schedule_eval(sch->schid);
 }
@@ -1052,7 +1052,7 @@ ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event)
        sch = to_subchannel(cdev->dev.parent);
        /*
         * An interrupt in state offline means a previous disable was not
-        * successful. Try again.
+        * successful - should not happen, but we try to disable again.
         */
        cio_disable_subchannel(sch);
 }
index eabcc42d63df17ca5bfc9afd89a1b6211b92f61a..151754d54745a3565fde4dca29a00f3de6b6a208 100644 (file)
@@ -680,7 +680,7 @@ int ccw_device_tm_intrg(struct ccw_device *cdev)
        if (cdev->private->state != DEV_STATE_ONLINE)
                return -EIO;
        if (!scsw_is_tm(&sch->schib.scsw) ||
-           !(scsw_actl(&sch->schib.scsw) | SCSW_ACTL_START_PEND))
+           !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_START_PEND))
                return -EINVAL;
        return cio_tm_intrg(sch);
 }
index 42f2b09631b6caa947ac66f0c0c285a9f4baa653..13bcb8114388b9ef31d9cd2faf40f19bb1c8c9d0 100644 (file)
@@ -186,6 +186,9 @@ struct qdio_input_q {
        /* input buffer acknowledgement flag */
        int polling;
 
+       /* first ACK'ed buffer */
+       int ack_start;
+
        /* how much sbals are acknowledged with qebsm */
        int ack_count;
 
@@ -234,7 +237,7 @@ struct qdio_q {
        int first_to_check;
 
        /* first_to_check of the last time */
-       int last_move_ftc;
+       int last_move;
 
        /* beginning position for calling the program */
        int first_to_kick;
@@ -244,7 +247,6 @@ struct qdio_q {
 
        struct qdio_irq *irq_ptr;
        struct tasklet_struct tasklet;
-       spinlock_t lock;
 
        /* error condition during a data transfer */
        unsigned int qdio_error;
@@ -354,7 +356,7 @@ int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state,
                  int auto_ack);
 void qdio_check_outbound_after_thinint(struct qdio_q *q);
 int qdio_inbound_q_moved(struct qdio_q *q);
-void qdio_kick_inbound_handler(struct qdio_q *q);
+void qdio_kick_handler(struct qdio_q *q);
 void qdio_stop_polling(struct qdio_q *q);
 int qdio_siga_sync_q(struct qdio_q *q);
 
index da7afb04e71ff8003c0b6139d169590a0b1caf2e..e3434b34f86cbc0a09c27e601fbfdba9f5b3a135 100644 (file)
@@ -63,8 +63,9 @@ static int qstat_show(struct seq_file *m, void *v)
        seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci);
        seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used));
        seq_printf(m, "ftc: %d\n", q->first_to_check);
-       seq_printf(m, "last_move_ftc: %d\n", q->last_move_ftc);
+       seq_printf(m, "last_move: %d\n", q->last_move);
        seq_printf(m, "polling: %d\n", q->u.in.polling);
+       seq_printf(m, "ack start: %d\n", q->u.in.ack_start);
        seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
        seq_printf(m, "slsb buffer states:\n");
        seq_printf(m, "|0      |8      |16     |24     |32     |40     |48     |56  63|\n");
index 10cb0f8726e5a72a264e4b62a2cbb9c3e32b65b1..9e8a2914259bf1656eb22fe6f01b1cbdf600ae01 100644 (file)
@@ -380,11 +380,11 @@ inline void qdio_stop_polling(struct qdio_q *q)
 
        /* show the card that we are not polling anymore */
        if (is_qebsm(q)) {
-               set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT,
+               set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
                               q->u.in.ack_count);
                q->u.in.ack_count = 0;
        } else
-               set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT);
+               set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT);
 }
 
 static void announce_buffer_error(struct qdio_q *q, int count)
@@ -419,15 +419,15 @@ static inline void inbound_primed(struct qdio_q *q, int count)
                if (!q->u.in.polling) {
                        q->u.in.polling = 1;
                        q->u.in.ack_count = count;
-                       q->last_move_ftc = q->first_to_check;
+                       q->u.in.ack_start = q->first_to_check;
                        return;
                }
 
                /* delete the previous ACK's */
-               set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT,
+               set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
                               q->u.in.ack_count);
                q->u.in.ack_count = count;
-               q->last_move_ftc = q->first_to_check;
+               q->u.in.ack_start = q->first_to_check;
                return;
        }
 
@@ -439,14 +439,13 @@ static inline void inbound_primed(struct qdio_q *q, int count)
        if (q->u.in.polling) {
                /* reset the previous ACK but first set the new one */
                set_buf_state(q, new, SLSB_P_INPUT_ACK);
-               set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT);
-       }
-       else {
+               set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT);
+       } else {
                q->u.in.polling = 1;
-               set_buf_state(q, q->first_to_check, SLSB_P_INPUT_ACK);
+               set_buf_state(q, new, SLSB_P_INPUT_ACK);
        }
 
-       q->last_move_ftc = new;
+       q->u.in.ack_start = new;
        count--;
        if (!count)
                return;
@@ -455,7 +454,7 @@ static inline void inbound_primed(struct qdio_q *q, int count)
         * Need to change all PRIMED buffers to NOT_INIT, otherwise
         * we're loosing initiative in the thinint code.
         */
-       set_buf_states(q, next_buf(q->first_to_check), SLSB_P_INPUT_NOT_INIT,
+       set_buf_states(q, q->first_to_check, SLSB_P_INPUT_NOT_INIT,
                       count);
 }
 
@@ -523,7 +522,8 @@ int qdio_inbound_q_moved(struct qdio_q *q)
 
        bufnr = get_inbound_buffer_frontier(q);
 
-       if ((bufnr != q->last_move_ftc) || q->qdio_error) {
+       if ((bufnr != q->last_move) || q->qdio_error) {
+               q->last_move = bufnr;
                if (!need_siga_sync(q) && !pci_out_supported(q))
                        q->u.in.timestamp = get_usecs();
 
@@ -570,29 +570,30 @@ static int qdio_inbound_q_done(struct qdio_q *q)
        }
 }
 
-void qdio_kick_inbound_handler(struct qdio_q *q)
+void qdio_kick_handler(struct qdio_q *q)
 {
-       int count, start, end;
-
-       qdio_perf_stat_inc(&perf_stats.inbound_handler);
-
-       start = q->first_to_kick;
-       end = q->first_to_check;
-       if (end >= start)
-               count = end - start;
-       else
-               count = end + QDIO_MAX_BUFFERS_PER_Q - start;
-
-       DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count);
+       int start = q->first_to_kick;
+       int end = q->first_to_check;
+       int count;
 
        if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
                return;
 
-       q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr,
-                  start, count, q->irq_ptr->int_parm);
+       count = sub_buf(end, start);
+
+       if (q->is_input_q) {
+               qdio_perf_stat_inc(&perf_stats.inbound_handler);
+               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count);
+       } else {
+               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: nr:%1d", q->nr);
+               DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count);
+       }
+
+       q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
+                  q->irq_ptr->int_parm);
 
        /* for the next time */
-       q->first_to_kick = q->first_to_check;
+       q->first_to_kick = end;
        q->qdio_error = 0;
 }
 
@@ -603,7 +604,7 @@ again:
        if (!qdio_inbound_q_moved(q))
                return;
 
-       qdio_kick_inbound_handler(q);
+       qdio_kick_handler(q);
 
        if (!qdio_inbound_q_done(q))
                /* means poll time is not yet over */
@@ -698,21 +699,21 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q)
 
        bufnr = get_outbound_buffer_frontier(q);
 
-       if ((bufnr != q->last_move_ftc) || q->qdio_error) {
-               q->last_move_ftc = bufnr;
+       if ((bufnr != q->last_move) || q->qdio_error) {
+               q->last_move = bufnr;
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr);
                return 1;
        } else
                return 0;
 }
 
-static void qdio_kick_outbound_q(struct qdio_q *q)
+static int qdio_kick_outbound_q(struct qdio_q *q)
 {
        unsigned int busy_bit;
        int cc;
 
        if (!need_siga_out(q))
-               return;
+               return 0;
 
        DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr);
        qdio_perf_stat_inc(&perf_stats.siga_out);
@@ -724,75 +725,37 @@ static void qdio_kick_outbound_q(struct qdio_q *q)
        case 2:
                if (busy_bit) {
                        DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr);
-                       q->qdio_error = cc | QDIO_ERROR_SIGA_BUSY;
-               } else {
-                       DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d",
-                                     q->nr);
-                       q->qdio_error = cc;
-               }
+                       cc |= QDIO_ERROR_SIGA_BUSY;
+               } else
+                       DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr);
                break;
        case 1:
        case 3:
                DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc);
-               q->qdio_error = cc;
                break;
        }
-}
-
-static void qdio_kick_outbound_handler(struct qdio_q *q)
-{
-       int start, end, count;
-
-       start = q->first_to_kick;
-       end = q->last_move_ftc;
-       if (end >= start)
-               count = end - start;
-       else
-               count = end + QDIO_MAX_BUFFERS_PER_Q - start;
-
-       DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kickouth: %1d", q->nr);
-       DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count);
-
-       if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
-               return;
-
-       q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
-                  q->irq_ptr->int_parm);
-
-       /* for the next time: */
-       q->first_to_kick = q->last_move_ftc;
-       q->qdio_error = 0;
+       return cc;
 }
 
 static void __qdio_outbound_processing(struct qdio_q *q)
 {
-       unsigned long flags;
-
        qdio_perf_stat_inc(&perf_stats.tasklet_outbound);
-       spin_lock_irqsave(&q->lock, flags);
-
        BUG_ON(atomic_read(&q->nr_buf_used) < 0);
 
        if (qdio_outbound_q_moved(q))
-               qdio_kick_outbound_handler(q);
-
-       spin_unlock_irqrestore(&q->lock, flags);
+               qdio_kick_handler(q);
 
-       if (queue_type(q) == QDIO_ZFCP_QFMT) {
+       if (queue_type(q) == QDIO_ZFCP_QFMT)
                if (!pci_out_supported(q) && !qdio_outbound_q_done(q))
-                       tasklet_schedule(&q->tasklet);
-               return;
-       }
+                       goto sched;
 
        /* bail out for HiperSockets unicast queues */
        if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q))
                return;
 
        if ((queue_type(q) == QDIO_IQDIO_QFMT) &&
-           (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) {
-               tasklet_schedule(&q->tasklet);
-               return;
-       }
+           (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL)
+               goto sched;
 
        if (q->u.out.pci_out_enabled)
                return;
@@ -810,6 +773,12 @@ static void __qdio_outbound_processing(struct qdio_q *q)
                        qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer);
                }
        }
+       return;
+
+sched:
+       if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
+               return;
+       tasklet_schedule(&q->tasklet);
 }
 
 /* outbound tasklet */
@@ -822,6 +791,9 @@ void qdio_outbound_processing(unsigned long data)
 void qdio_outbound_timer(unsigned long data)
 {
        struct qdio_q *q = (struct qdio_q *)data;
+
+       if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
+               return;
        tasklet_schedule(&q->tasklet);
 }
 
@@ -863,6 +835,9 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
        int i;
        struct qdio_q *q;
 
+       if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
+               return;
+
        qdio_perf_stat_inc(&perf_stats.pci_int);
 
        for_each_input_queue(irq_ptr, q, i)
@@ -1065,8 +1040,9 @@ EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc);
  * @cdev: associated ccw device
  * @how: use halt or clear to shutdown
  *
- * This function calls qdio_shutdown() for @cdev with method @how
- * and on success qdio_free() for @cdev.
+ * This function calls qdio_shutdown() for @cdev with method @how.
+ * and qdio_free(). The qdio_free() return value is ignored since
+ * !irq_ptr is already checked.
  */
 int qdio_cleanup(struct ccw_device *cdev, int how)
 {
@@ -1077,8 +1053,8 @@ int qdio_cleanup(struct ccw_device *cdev, int how)
                return -ENODEV;
 
        rc = qdio_shutdown(cdev, how);
-       if (rc == 0)
-               rc = qdio_free(cdev);
+
+       qdio_free(cdev);
        return rc;
 }
 EXPORT_SYMBOL_GPL(qdio_cleanup);
@@ -1090,11 +1066,11 @@ static void qdio_shutdown_queues(struct ccw_device *cdev)
        int i;
 
        for_each_input_queue(irq_ptr, q, i)
-               tasklet_disable(&q->tasklet);
+               tasklet_kill(&q->tasklet);
 
        for_each_output_queue(irq_ptr, q, i) {
-               tasklet_disable(&q->tasklet);
                del_timer(&q->u.out.timer);
+               tasklet_kill(&q->tasklet);
        }
 }
 
@@ -1112,6 +1088,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
        if (!irq_ptr)
                return -ENODEV;
 
+       BUG_ON(irqs_disabled());
        DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no);
 
        mutex_lock(&irq_ptr->setup_mutex);
@@ -1124,6 +1101,12 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
                return 0;
        }
 
+       /*
+        * Indicate that the device is going down. Scheduling the queue
+        * tasklets is forbidden from here on.
+        */
+       qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
+
        tiqdio_remove_input_queues(irq_ptr);
        qdio_shutdown_queues(cdev);
        qdio_shutdown_debug_entries(irq_ptr, cdev);
@@ -1403,9 +1386,8 @@ int qdio_activate(struct ccw_device *cdev)
        switch (irq_ptr->state) {
        case QDIO_IRQ_STATE_STOPPED:
        case QDIO_IRQ_STATE_ERR:
-               mutex_unlock(&irq_ptr->setup_mutex);
-               qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
-               return -EIO;
+               rc = -EIO;
+               break;
        default:
                qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ACTIVE);
                rc = 0;
@@ -1442,10 +1424,10 @@ static inline int buf_in_between(int bufnr, int start, int count)
  * @bufnr: first buffer to process
  * @count: how many buffers are emptied
  */
-static void handle_inbound(struct qdio_q *q, unsigned int callflags,
-                          int bufnr, int count)
+static int handle_inbound(struct qdio_q *q, unsigned int callflags,
+                         int bufnr, int count)
 {
-       int used, cc, diff;
+       int used, diff;
 
        if (!q->u.in.polling)
                goto set;
@@ -1456,19 +1438,18 @@ static void handle_inbound(struct qdio_q *q, unsigned int callflags,
                q->u.in.polling = 0;
                q->u.in.ack_count = 0;
                goto set;
-       } else if (buf_in_between(q->last_move_ftc, bufnr, count)) {
+       } else if (buf_in_between(q->u.in.ack_start, bufnr, count)) {
                if (is_qebsm(q)) {
-                       /* partial overwrite, just update last_move_ftc */
+                       /* partial overwrite, just update ack_start */
                        diff = add_buf(bufnr, count);
-                       diff = sub_buf(diff, q->last_move_ftc);
+                       diff = sub_buf(diff, q->u.in.ack_start);
                        q->u.in.ack_count -= diff;
                        if (q->u.in.ack_count <= 0) {
                                q->u.in.polling = 0;
                                q->u.in.ack_count = 0;
-                               /* TODO: must we set last_move_ftc to something meaningful? */
                                goto set;
                        }
-                       q->last_move_ftc = add_buf(q->last_move_ftc, diff);
+                       q->u.in.ack_start = add_buf(q->u.in.ack_start, diff);
                }
                else
                        /* the only ACK will be deleted, so stop polling */
@@ -1483,13 +1464,11 @@ set:
 
        /* no need to signal as long as the adapter had free buffers */
        if (used)
-               return;
+               return 0;
 
-       if (need_siga_in(q)) {
-               cc = qdio_siga_input(q);
-               if (cc)
-                       q->qdio_error = cc;
-       }
+       if (need_siga_in(q))
+               return qdio_siga_input(q);
+       return 0;
 }
 
 /**
@@ -1499,11 +1478,11 @@ set:
  * @bufnr: first buffer to process
  * @count: how many buffers are filled
  */
-static void handle_outbound(struct qdio_q *q, unsigned int callflags,
-                           int bufnr, int count)
+static int handle_outbound(struct qdio_q *q, unsigned int callflags,
+                          int bufnr, int count)
 {
        unsigned char state;
-       int used;
+       int used, rc = 0;
 
        qdio_perf_stat_inc(&perf_stats.outbound_handler);
 
@@ -1518,27 +1497,26 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags,
 
        if (queue_type(q) == QDIO_IQDIO_QFMT) {
                if (multicast_outbound(q))
-                       qdio_kick_outbound_q(q);
+                       rc = qdio_kick_outbound_q(q);
                else
                        if ((q->irq_ptr->ssqd_desc.mmwc > 1) &&
                            (count > 1) &&
                            (count <= q->irq_ptr->ssqd_desc.mmwc)) {
                                /* exploit enhanced SIGA */
                                q->u.out.use_enh_siga = 1;
-                               qdio_kick_outbound_q(q);
+                               rc = qdio_kick_outbound_q(q);
                        } else {
                                /*
                                * One siga-w per buffer required for unicast
                                * HiperSockets.
                                */
                                q->u.out.use_enh_siga = 0;
-                               while (count--)
-                                       qdio_kick_outbound_q(q);
+                               while (count--) {
+                                       rc = qdio_kick_outbound_q(q);
+                                       if (rc)
+                                               goto out;
+                               }
                        }
-
-               /* report CC=2 conditions synchronously */
-               if (q->qdio_error)
-                       __qdio_outbound_processing(q);
                goto out;
        }
 
@@ -1550,14 +1528,14 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags,
        /* try to fast requeue buffers */
        get_buf_state(q, prev_buf(bufnr), &state, 0);
        if (state != SLSB_CU_OUTPUT_PRIMED)
-               qdio_kick_outbound_q(q);
+               rc = qdio_kick_outbound_q(q);
        else {
                DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req");
                qdio_perf_stat_inc(&perf_stats.fast_requeue);
        }
 out:
-       /* Fixme: could wait forever if called from process context */
        tasklet_schedule(&q->tasklet);
+       return rc;
 }
 
 /**
@@ -1596,14 +1574,12 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
                return -EBUSY;
 
        if (callflags & QDIO_FLAG_SYNC_INPUT)
-               handle_inbound(irq_ptr->input_qs[q_nr], callflags, bufnr,
-                              count);
+               return handle_inbound(irq_ptr->input_qs[q_nr],
+                                     callflags, bufnr, count);
        else if (callflags & QDIO_FLAG_SYNC_OUTPUT)
-               handle_outbound(irq_ptr->output_qs[q_nr], callflags, bufnr,
-                               count);
-       else
-               return -EINVAL;
-       return 0;
+               return handle_outbound(irq_ptr->output_qs[q_nr],
+                                      callflags, bufnr, count);
+       return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(do_QDIO);
 
index c08356b95bf5f9d2f41ef93e77ecd1b360781908..18d54fc21ce90b43b9e43418a4b3a47e9e6e15ae 100644 (file)
@@ -117,7 +117,6 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
        q->mask = 1 << (31 - i);
        q->nr = i;
        q->handler = handler;
-       spin_lock_init(&q->lock);
 }
 
 static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
index 8e90e147b746834c6af2c87da10fbdb8c3fc2f93..c655d011a78dac28ef5768a2aa0317d761b4e06a 100644 (file)
@@ -31,6 +31,7 @@
 
 /* list of thin interrupt input queues */
 static LIST_HEAD(tiq_list);
+DEFINE_MUTEX(tiq_list_lock);
 
 /* adapter local summary indicator */
 static unsigned char *tiqdio_alsi;
@@ -95,12 +96,11 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr)
        if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync)
                css_qdio_omit_svs = 1;
 
-       for_each_input_queue(irq_ptr, q, i) {
+       mutex_lock(&tiq_list_lock);
+       for_each_input_queue(irq_ptr, q, i)
                list_add_rcu(&q->entry, &tiq_list);
-               synchronize_rcu();
-       }
+       mutex_unlock(&tiq_list_lock);
        xchg(irq_ptr->dsci, 1);
-       tasklet_schedule(&tiqdio_tasklet);
 }
 
 /*
@@ -118,7 +118,10 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
                /* if establish triggered an error */
                if (!q || !q->entry.prev || !q->entry.next)
                        continue;
+
+               mutex_lock(&tiq_list_lock);
                list_del_rcu(&q->entry);
+               mutex_unlock(&tiq_list_lock);
                synchronize_rcu();
        }
 }
@@ -155,15 +158,15 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
         */
        qdio_check_outbound_after_thinint(q);
 
-again:
        if (!qdio_inbound_q_moved(q))
                return;
 
-       qdio_kick_inbound_handler(q);
+       qdio_kick_handler(q);
 
        if (!tiqdio_inbound_q_done(q)) {
                qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop);
-               goto again;
+               if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
+                       tasklet_schedule(&q->tasklet);
        }
 
        qdio_stop_polling(q);
@@ -173,7 +176,8 @@ again:
         */
        if (!tiqdio_inbound_q_done(q)) {
                qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2);
-               goto again;
+               if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
+                       tasklet_schedule(&q->tasklet);
        }
 }
 
@@ -366,10 +370,11 @@ void qdio_shutdown_thinint(struct qdio_irq *irq_ptr)
 
 void __exit tiqdio_unregister_thinints(void)
 {
-       tasklet_disable(&tiqdio_tasklet);
+       WARN_ON(!list_empty(&tiq_list));
 
        if (tiqdio_alsi) {
                s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC);
                isc_unregister(QDIO_AIRQ_ISC);
        }
+       tasklet_kill(&tiqdio_tasklet);
 }
index cb22b97944b8513ad553a68f133eca9ba28728f1..65b6a96afe6b10d336d3d95e7b7de026f88547ab 100644 (file)
@@ -128,8 +128,7 @@ static void __zcrypt_increase_preference(struct zcrypt_device *zdev)
        if (l == zdev->list.prev)
                return;
        /* Move zdev behind l */
-       list_del(&zdev->list);
-       list_add(&zdev->list, l);
+       list_move(&zdev->list, l);
 }
 
 /**
@@ -157,8 +156,7 @@ static void __zcrypt_decrease_preference(struct zcrypt_device *zdev)
        if (l == zdev->list.next)
                return;
        /* Move zdev before l */
-       list_del(&zdev->list);
-       list_add_tail(&zdev->list, l);
+       list_move_tail(&zdev->list, l);
 }
 
 static void zcrypt_device_release(struct kref *kref)
index e7a1e22e77acf82425b8a60c5d25426f83c6aca4..c20d4790258e247c9638f61a928bf4f578c163c8 100644 (file)
@@ -781,8 +781,7 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
                /* Signal pending. */
                ap_cancel_message(zdev->ap_dev, &ap_msg);
 out_free:
-       memset(ap_msg.message, 0x0, ap_msg.length);
-       kfree(ap_msg.message);
+       kzfree(ap_msg.message);
        return rc;
 }
 
diff --git a/drivers/s390/ebcdic.c b/drivers/s390/ebcdic.c
deleted file mode 100644 (file)
index 99c98da..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- *  arch/s390/kernel/ebcdic.c
- *    ECBDIC -> ASCII, ASCII -> ECBDIC conversion tables.
- *
- *  S390 version
- *    Copyright (C) 1998 IBM Corporation
- *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
- */
-
-#include <asm/types.h>
-
-/*
- * ASCII -> EBCDIC
- */
-__u8 _ascebc[256] =
-{
- /*00  NL    SH    SX    EX    ET    NQ    AK    BL */
-     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
- /*08  BS    HT    LF    VT    FF    CR    SO    SI */
-     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- /*10  DL    D1    D2    D3    D4    NK    SN    EB */
-     0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26,
- /*18  CN    EM    SB    EC    FS    GS    RS    US */
-     0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
- /*20  SP     !     "     #     $     %     &     ' */
-     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
- /*28   (     )     *     +     ,     -    .      / */
-     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
- /*30   0     1     2     3     4     5     6     7 */
-     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
- /*38   8     9     :     ;     <     =     >     ? */
-     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
- /*40   @     A     B     C     D     E     F     G */
-     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
- /*48   H     I     J     K     L     M     N     O */
-     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
- /*50   P     Q     R     S     T     U     V     W */
-     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
- /*58   X     Y     Z     [     \     ]     ^     _ */
-     0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
- /*60   `     a     b     c     d     e     f     g */
-     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- /*68   h     i     j     k     l     m     n     o */
-     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
- /*70   p     q     r     s     t     u     v     w */
-     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
- /*78   x     y     z     {     |     }     ~    DL */
-     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
-     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
-};
-
-/*
- * EBCDIC -> ASCII
- */
-__u8 _ebcasc[256] =
-{
- /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
-          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
- /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
-          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
-                                  -ENP  ->LF             */
-          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
- /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
-                                                    -IUS */
-          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
-                                  -INP                   */
-          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
- /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
-                       -SW                               */ 
-          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
- /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
-          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
- /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
-          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
- /* 0x40    SP   RSP           \81ä              ----       */
-          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
- /* 0x48                       .     <     (     +     | */
-          0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
- /* 0x50     &                                      ---- */
-          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
- /* 0x58           \81ß     !     $     *     )     ;       */
-          0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
- /* 0x60     -     /  ----     \81Ä  ----  ----  ----       */
-          0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
- /* 0x68              ----     ,     %     _     >     ? */ 
-          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
- /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
-          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- /* 0x78     *     `     :     #     @     '     =     " */
-          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
- /* 0x80     *     a     b     c     d     e     f     g */
-          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
- /* 0x88     h     i              ----  ----  ----       */
-          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
- /* 0x90     \81°     j     k     l     m     n     o     p */
-          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
- /* 0x98     q     r                    ----        ---- */
-          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
- /* 0xA0           ~     s     t     u     v     w     x */
-          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- /* 0xA8     y     z              ----  ----  ----  ---- */
-          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
- /* 0xB0     ^                    ----     \81§  ----       */
-          0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
- /* 0xB8        ----     [     ]  ----  ----  ----  ---- */
-          0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
- /* 0xC0     {     A     B     C     D     E     F     G */
-          0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- /* 0xC8     H     I  ----           \81ö              ---- */
-          0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
- /* 0xD0     }     J     K     L     M     N     O     P */
-          0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
- /* 0xD8     Q     R  ----           \81ü                   */
-          0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
- /* 0xE0     \           S     T     U     V     W     X */
-          0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- /* 0xE8     Y     Z        ----     \81Ö  ----  ----  ---- */
-          0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
- /* 0xF0     0     1     2     3     4     5     6     7 */
-          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- /* 0xF8     8     9  ----  ----     \81Ãœ  ----  ----  ---- */
-          0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
-};
-
-/*
- * EBCDIC (capitals) -> ASCII (small case)
- */
-__u8 _ebcasc_reduce_case[256] =
-{
- /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
-          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
-
- /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
-          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-
- /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
-                                  -ENP  ->LF             */
-          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
-
- /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
-                                                    -IUS */
-          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-
- /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
-                                  -INP                   */
-          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
-
- /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
-                       -SW                               */ 
-          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
-
- /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
-          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
-
- /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
-          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
-
- /* 0x40    SP   RSP           \81ä              ----       */
-          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
-
- /* 0x48                       .     <     (     +     | */
-          0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
-
- /* 0x50     &                                      ---- */
-          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
-
- /* 0x58           \81ß     !     $     *     )     ;       */
-          0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
-
- /* 0x60     -     /  ----     \81Ä  ----  ----  ----       */
-          0x2D, 0x2F, 0x07, 0x84, 0x07, 0x07, 0x07, 0x8F,
-
- /* 0x68              ----     ,     %     _     >     ? */ 
-          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-
- /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
-          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-
- /* 0x78     *     `     :     #     @     '     =     " */
-          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-
- /* 0x80     *     a     b     c     d     e     f     g */
-          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-
- /* 0x88     h     i              ----  ----  ----       */
-          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
-
- /* 0x90     \81°     j     k     l     m     n     o     p */
-          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-
- /* 0x98     q     r                    ----        ---- */
-          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
-
- /* 0xA0           ~     s     t     u     v     w     x */
-          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-
- /* 0xA8     y     z              ----  ----  ----  ---- */
-          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
-
- /* 0xB0     ^                    ----     \81§  ----       */
-          0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
-
- /* 0xB8        ----     [     ]  ----  ----  ----  ---- */
-          0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
-
- /* 0xC0     {     A     B     C     D     E     F     G */
-          0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-
- /* 0xC8     H     I  ----           \81ö              ---- */
-          0x68, 0x69, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
-
- /* 0xD0     }     J     K     L     M     N     O     P */
-          0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-
- /* 0xD8     Q     R  ----           \81ü                   */
-          0x71, 0x72, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
-
- /* 0xE0     \           S     T     U     V     W     X */
-          0x5C, 0xF6, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-
- /* 0xE8     Y     Z        ----     \81Ö  ----  ----  ---- */
-          0x79, 0x7A, 0xFD, 0x07, 0x94, 0x07, 0x07, 0x07,
-
- /* 0xF0     0     1     2     3     4     5     6     7 */
-          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-
- /* 0xF8     8     9  ----  ----     \81Ãœ  ----  ----  ---- */
-          0x38, 0x39, 0x07, 0x07, 0x81, 0x07, 0x07, 0x07
-};
index 6fec3cfcf978de999b34fda2640c7adda7e0a2e3..c827d69b5a912c83244afd3cdd1eeb98b630b7e9 100644 (file)
@@ -2680,40 +2680,21 @@ static int qeth_handle_send_error(struct qeth_card *card,
                struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err)
 {
        int sbalf15 = buffer->buffer->element[15].flags & 0xff;
-       int cc = qdio_err & 3;
 
        QETH_DBF_TEXT(TRACE, 6, "hdsnderr");
        qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr");
-       switch (cc) {
-       case 0:
-               if (qdio_err) {
-                       QETH_DBF_TEXT(TRACE, 1, "lnkfail");
-                       QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
-                       QETH_DBF_TEXT_(TRACE, 1, "%04x %02x",
-                                      (u16)qdio_err, (u8)sbalf15);
-                       return QETH_SEND_ERROR_LINK_FAILURE;
-               }
+
+       if (!qdio_err)
                return QETH_SEND_ERROR_NONE;
-       case 2:
-               if (qdio_err & QDIO_ERROR_SIGA_BUSY) {
-                       QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B");
-                       QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
-                       return QETH_SEND_ERROR_KICK_IT;
-               }
-               if ((sbalf15 >= 15) && (sbalf15 <= 31))
-                       return QETH_SEND_ERROR_RETRY;
-               return QETH_SEND_ERROR_LINK_FAILURE;
-               /* look at qdio_error and sbalf 15 */
-       case 1:
-               QETH_DBF_TEXT(TRACE, 1, "SIGAcc1");
-               QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
-               return QETH_SEND_ERROR_LINK_FAILURE;
-       case 3:
-       default:
-               QETH_DBF_TEXT(TRACE, 1, "SIGAcc3");
-               QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
-               return QETH_SEND_ERROR_KICK_IT;
-       }
+
+       if ((sbalf15 >= 15) && (sbalf15 <= 31))
+               return QETH_SEND_ERROR_RETRY;
+
+       QETH_DBF_TEXT(TRACE, 1, "lnkfail");
+       QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
+       QETH_DBF_TEXT_(TRACE, 1, "%04x %02x",
+                      (u16)qdio_err, (u8)sbalf15);
+       return QETH_SEND_ERROR_LINK_FAILURE;
 }
 
 /*
@@ -2849,10 +2830,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
                        qeth_get_micros() -
                        queue->card->perf_stats.outbound_do_qdio_start_time;
        if (rc) {
+               queue->card->stats.tx_errors += count;
+               /* ignore temporary SIGA errors without busy condition */
+               if (rc == QDIO_ERROR_SIGA_TARGET)
+                       return;
                QETH_DBF_TEXT(TRACE, 2, "flushbuf");
                QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
                QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card));
-               queue->card->stats.tx_errors += count;
+
                /* this must not happen under normal circumstances. if it
                 * happens something is really wrong -> recover */
                qeth_schedule_recovery(queue->card);
@@ -2927,13 +2912,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
        }
        for (i = first_element; i < (first_element + count); ++i) {
                buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
-               /*we only handle the KICK_IT error by doing a recovery */
-               if (qeth_handle_send_error(card, buffer, qdio_error)
-                               == QETH_SEND_ERROR_KICK_IT){
-                       netif_stop_queue(card->dev);
-                       qeth_schedule_recovery(card);
-                       return;
-               }
+               qeth_handle_send_error(card, buffer, qdio_error);
                qeth_clear_output_buffer(queue, buffer);
        }
        atomic_sub(count, &queue->used_buffers);
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
deleted file mode 100644 (file)
index d39f8b6..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  drivers/s390/s390mach.h
- *   S/390 data definitions for machine check processing
- *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
-#ifndef __s390mach_h
-#define __s390mach_h
-
-#include <asm/types.h>
-
-struct mci {
-       __u32   sd              :  1; /* 00 system damage */
-       __u32   pd              :  1; /* 01 instruction-processing damage */
-       __u32   sr              :  1; /* 02 system recovery */
-       __u32   to_be_defined_1 :  1; /* 03 */
-       __u32   cd              :  1; /* 04 timing-facility damage */
-       __u32   ed              :  1; /* 05 external damage */
-       __u32   to_be_defined_2 :  1; /* 06 */
-       __u32   dg              :  1; /* 07 degradation */
-       __u32   w               :  1; /* 08 warning pending */
-       __u32   cp              :  1; /* 09 channel-report pending */
-       __u32   sp              :  1; /* 10 service-processor damage */
-       __u32   ck              :  1; /* 11 channel-subsystem damage */
-       __u32   to_be_defined_3 :  2; /* 12-13 */
-       __u32   b               :  1; /* 14 backed up */
-       __u32   to_be_defined_4 :  1; /* 15 */
-       __u32   se              :  1; /* 16 storage error uncorrected */
-       __u32   sc              :  1; /* 17 storage error corrected */
-       __u32   ke              :  1; /* 18 storage-key error uncorrected */
-       __u32   ds              :  1; /* 19 storage degradation */
-       __u32   wp              :  1; /* 20 psw mwp validity */
-       __u32   ms              :  1; /* 21 psw mask and key validity */
-       __u32   pm              :  1; /* 22 psw program mask and cc validity */
-       __u32   ia              :  1; /* 23 psw instruction address validity */
-       __u32   fa              :  1; /* 24 failing storage address validity */
-       __u32   to_be_defined_5 :  1; /* 25 */
-       __u32   ec              :  1; /* 26 external damage code validity */
-       __u32   fp              :  1; /* 27 floating point register validity */
-       __u32   gr              :  1; /* 28 general register validity */
-       __u32   cr              :  1; /* 29 control register validity */
-       __u32   to_be_defined_6 :  1; /* 30 */
-       __u32   st              :  1; /* 31 storage logical validity */
-       __u32   ie              :  1; /* 32 indirect storage error */
-       __u32   ar              :  1; /* 33 access register validity */
-       __u32   da              :  1; /* 34 delayed access exception */
-       __u32   to_be_defined_7 :  7; /* 35-41 */
-       __u32   pr              :  1; /* 42 tod programmable register validity */
-       __u32   fc              :  1; /* 43 fp control register validity */
-       __u32   ap              :  1; /* 44 ancillary report */
-       __u32   to_be_defined_8 :  1; /* 45 */
-       __u32   ct              :  1; /* 46 cpu timer validity */
-       __u32   cc              :  1; /* 47 clock comparator validity */
-       __u32   to_be_defined_9 : 16; /* 47-63 */
-};
-
-/*
- * Channel Report Word
- */
-struct crw {
-       __u32 res1    :  1;   /* reserved zero */
-       __u32 slct    :  1;   /* solicited */
-       __u32 oflw    :  1;   /* overflow */
-       __u32 chn     :  1;   /* chained */
-       __u32 rsc     :  4;   /* reporting source code */
-       __u32 anc     :  1;   /* ancillary report */
-       __u32 res2    :  1;   /* reserved zero */
-       __u32 erc     :  6;   /* error-recovery code */
-       __u32 rsid    : 16;   /* reporting-source ID */
-} __attribute__ ((packed));
-
-typedef void (*crw_handler_t)(struct crw *, struct crw *, int);
-
-extern int s390_register_crw_handler(int rsc, crw_handler_t handler);
-extern void s390_unregister_crw_handler(int rsc);
-
-#define NR_RSCS 16
-
-#define CRW_RSC_MONITOR  0x2  /* monitoring facility */
-#define CRW_RSC_SCH      0x3  /* subchannel */
-#define CRW_RSC_CPATH    0x4  /* channel path */
-#define CRW_RSC_CONFIG   0x9  /* configuration-alert facility */
-#define CRW_RSC_CSS      0xB  /* channel subsystem */
-
-#define CRW_ERC_EVENT    0x00 /* event information pending */
-#define CRW_ERC_AVAIL    0x01 /* available */
-#define CRW_ERC_INIT     0x02 /* initialized */
-#define CRW_ERC_TERROR   0x03 /* temporary error */
-#define CRW_ERC_IPARM    0x04 /* installed parm initialized */
-#define CRW_ERC_TERM     0x05 /* terminal */
-#define CRW_ERC_PERRN    0x06 /* perm. error, fac. not init */
-#define CRW_ERC_PERRI    0x07 /* perm. error, facility init */
-#define CRW_ERC_PMOD     0x08 /* installed parameters modified */
-
-static inline int stcrw(struct crw *pcrw )
-{
-       int ccode;
-
-       __asm__ __volatile__(
-               "stcrw 0(%2)\n\t"
-               "ipm %0\n\t"
-               "srl %0,28\n\t"
-               : "=d" (ccode), "=m" (*pcrw)
-               : "a" (pcrw)
-               : "cc" );
-       return ccode;
-}
-
-#define ED_ETR_SYNC    12      /* External damage ETR sync check */
-#define ED_ETR_SWITCH  13      /* External damage ETR switch to local */
-
-#define ED_STP_SYNC    7       /* External damage STP sync check */
-#define ED_STP_ISLAND  6       /* External damage STP island check */
-
-struct pt_regs;
-
-void s390_handle_mcck(void);
-void s390_do_machine_check(struct pt_regs *regs);
-#endif /* __s390mach */
index 1e064c4a4f86017ed8fa8832fee08c2224cd09b6..46297683cd34bbaf4b0396172159ab21cd575baa 100644 (file)
  * compute the block number from a
  * cyl-cyl-head-head structure
  */
-static inline int
+static sector_t
 cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
-        return ptr->cc * geo->heads * geo->sectors +
-              ptr->hh * geo->sectors;
+
+       sector_t cyl;
+       __u16 head;
+
+       /*decode cylinder and heads for large volumes */
+       cyl = ptr->hh & 0xFFF0;
+       cyl <<= 12;
+       cyl |= ptr->cc;
+       head = ptr->hh & 0x000F;
+       return cyl * geo->heads * geo->sectors +
+              head * geo->sectors;
 }
 
 /*
  * compute the block number from a
  * cyl-cyl-head-head-block structure
  */
-static inline int
+static sector_t
 cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
-        return ptr->cc * geo->heads * geo->sectors +
-               ptr->hh * geo->sectors +
+
+       sector_t cyl;
+       __u16 head;
+
+       /*decode cylinder and heads for large volumes */
+       cyl = ptr->hh & 0xFFF0;
+       cyl <<= 12;
+       cyl |= ptr->cc;
+       head = ptr->hh & 0x000F;
+       return  cyl * geo->heads * geo->sectors +
+               head * geo->sectors +
                ptr->b;
 }
 
@@ -43,14 +61,15 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
 int
 ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-       int blocksize, offset, size,res;
-       loff_t i_size;
+       int blocksize, res;
+       loff_t i_size, offset, size, fmt_size;
        dasd_information2_t *info;
        struct hd_geometry *geo;
        char type[5] = {0,};
        char name[7] = {0,};
        union label_t {
-               struct vtoc_volume_label vol;
+               struct vtoc_volume_label_cdl vol;
+               struct vtoc_volume_label_ldl lnx;
                struct vtoc_cms_label cms;
        } *label;
        unsigned char *data;
@@ -85,14 +104,16 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
        if (data == NULL)
                goto out_readerr;
 
-       strncpy (type, data, 4);
-       if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
-               strncpy(name, data + 8, 6);
-       else
-               strncpy(name, data + 4, 6);
        memcpy(label, data, sizeof(union label_t));
        put_dev_sector(sect);
 
+       if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
+               strncpy(type, label->vol.vollbl, 4);
+               strncpy(name, label->vol.volid, 6);
+       } else {
+               strncpy(type, label->lnx.vollbl, 4);
+               strncpy(name, label->lnx.volid, 6);
+       }
        EBCASC(type, 4);
        EBCASC(name, 6);
 
@@ -110,36 +131,54 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
                        /*
                         * VM style CMS1 labeled disk
                         */
+                       blocksize = label->cms.block_size;
                        if (label->cms.disk_offset != 0) {
                                printk("CMS1/%8s(MDSK):", name);
                                /* disk is reserved minidisk */
-                               blocksize = label->cms.block_size;
                                offset = label->cms.disk_offset;
                                size = (label->cms.block_count - 1)
                                        * (blocksize >> 9);
                        } else {
                                printk("CMS1/%8s:", name);
                                offset = (info->label_block + 1);
-                               size = i_size >> 9;
+                               size = label->cms.block_count
+                                       * (blocksize >> 9);
                        }
+                       put_partition(state, 1, offset*(blocksize >> 9),
+                                     size-offset*(blocksize >> 9));
                } else {
-                       /*
-                        * Old style LNX1 or unlabeled disk
-                        */
-                       if (strncmp(type, "LNX1", 4) == 0)
-                               printk ("LNX1/%8s:", name);
-                       else
+                       if (strncmp(type, "LNX1", 4) == 0) {
+                               printk("LNX1/%8s:", name);
+                               if (label->lnx.ldl_version == 0xf2) {
+                                       fmt_size = label->lnx.formatted_blocks
+                                               * (blocksize >> 9);
+                               } else if (!strcmp(info->type, "ECKD")) {
+                                       /* formated w/o large volume support */
+                                       fmt_size = geo->cylinders * geo->heads
+                                             * geo->sectors * (blocksize >> 9);
+                               } else {
+                                       /* old label and no usable disk geometry
+                                        * (e.g. DIAG) */
+                                       fmt_size = i_size >> 9;
+                               }
+                               size = i_size >> 9;
+                               if (fmt_size < size)
+                                       size = fmt_size;
+                               offset = (info->label_block + 1);
+                       } else {
+                               /* unlabeled disk */
                                printk("(nonl)");
-                       offset = (info->label_block + 1);
-                       size = i_size >> 9;
-               }
-               put_partition(state, 1, offset*(blocksize >> 9),
+                               size = i_size >> 9;
+                               offset = (info->label_block + 1);
+                       }
+                       put_partition(state, 1, offset*(blocksize >> 9),
                                      size-offset*(blocksize >> 9));
+               }
        } else if (info->format == DASD_FORMAT_CDL) {
                /*
                 * New style CDL formatted disk
                 */
-               unsigned int blk;
+               sector_t blk;
                int counter;
 
                /*
@@ -166,7 +205,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
                                /* skip FMT4 / FMT5 / FMT7 labels */
                                if (f1.DS1FMTID == _ascebc['4']
                                    || f1.DS1FMTID == _ascebc['5']
-                                   || f1.DS1FMTID == _ascebc['7']) {
+                                   || f1.DS1FMTID == _ascebc['7']
+                                   || f1.DS1FMTID == _ascebc['9']) {
                                        blk++;
                                        data = read_dev_sector(bdev, blk *
                                                               (blocksize/512),
@@ -174,8 +214,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
                                        continue;
                                }
 
-                               /* only FMT1 valid at this point */
-                               if (f1.DS1FMTID != _ascebc['1'])
+                               /* only FMT1 and 8 labels valid at this point */
+                               if (f1.DS1FMTID != _ascebc['1'] &&
+                                   f1.DS1FMTID != _ascebc['8'])
                                        break;
 
                                /* OK, we got valid partition data */