diff options
99 files changed, 4059 insertions, 2917 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1a29ff3df3c5..954b23cecfd1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -830,6 +830,9 @@ and is between 256 and 4096 characters. It is defined in the file | |||
830 | 830 | ||
831 | hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC) | 831 | hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC) |
832 | terminal devices. Valid values: 0..8 | 832 | terminal devices. Valid values: 0..8 |
833 | hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs. | ||
834 | If specified, z/VM IUCV HVC accepts connections | ||
835 | from listed z/VM user IDs only. | ||
833 | 836 | ||
834 | i8042.debug [HW] Toggle i8042 debug mode | 837 | i8042.debug [HW] Toggle i8042 debug mode |
835 | i8042.direct [HW] Put keyboard port into non-translated mode | 838 | i8042.direct [HW] Put keyboard port into non-translated mode |
diff --git a/MAINTAINERS b/MAINTAINERS index bc919b645f37..4dacdfcdbe6e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3745,6 +3745,15 @@ L: linux-s390@vger.kernel.org | |||
3745 | W: http://www.ibm.com/developerworks/linux/linux390/ | 3745 | W: http://www.ibm.com/developerworks/linux/linux390/ |
3746 | S: Supported | 3746 | S: Supported |
3747 | 3747 | ||
3748 | S390 ZCRYPT DRIVER | ||
3749 | P: Felix Beck | ||
3750 | M: felix.beck@de.ibm.com | ||
3751 | P: Ralph Wuerthner | ||
3752 | M: ralph.wuerthner@de.ibm.com | ||
3753 | M: linux390@de.ibm.com | ||
3754 | L: linux-s390@vger.kernel.org | ||
3755 | S: Supported | ||
3756 | |||
3748 | S390 ZFCP DRIVER | 3757 | S390 ZFCP DRIVER |
3749 | P: Christof Schmitt | 3758 | P: Christof Schmitt |
3750 | M: christof.schmitt@de.ibm.com | 3759 | M: christof.schmitt@de.ibm.com |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 6b0a3538dc63..2a8af5e16345 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -343,13 +343,6 @@ source "mm/Kconfig" | |||
343 | 343 | ||
344 | comment "I/O subsystem configuration" | 344 | comment "I/O subsystem configuration" |
345 | 345 | ||
346 | config MACHCHK_WARNING | ||
347 | bool "Process warning machine checks" | ||
348 | help | ||
349 | Select this option if you want the machine check handler on IBM S/390 or | ||
350 | zSeries to process warning machine checks (e.g. on power failures). | ||
351 | If unsure, say "Y". | ||
352 | |||
353 | config QDIO | 346 | config QDIO |
354 | tristate "QDIO support" | 347 | tristate "QDIO support" |
355 | ---help--- | 348 | ---help--- |
@@ -521,7 +514,7 @@ config APPLDATA_OS | |||
521 | 514 | ||
522 | config APPLDATA_NET_SUM | 515 | config APPLDATA_NET_SUM |
523 | tristate "Monitor overall network statistics" | 516 | tristate "Monitor overall network statistics" |
524 | depends on APPLDATA_BASE | 517 | depends on APPLDATA_BASE && NET |
525 | help | 518 | help |
526 | This provides network related data to the Linux - VM Monitor Stream, | 519 | This provides network related data to the Linux - VM Monitor Stream, |
527 | currently there is only a total sum of network I/O statistics, no | 520 | currently there is only a total sum of network I/O statistics, no |
@@ -552,7 +545,7 @@ config KEXEC | |||
552 | but is independent of hardware/microcode support. | 545 | but is independent of hardware/microcode support. |
553 | 546 | ||
554 | config ZFCPDUMP | 547 | config ZFCPDUMP |
555 | tristate "zfcpdump support" | 548 | bool "zfcpdump support" |
556 | select SMP | 549 | select SMP |
557 | default n | 550 | default n |
558 | help | 551 | help |
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index eca724d229ec..b49c00ce65e9 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c | |||
@@ -201,8 +201,7 @@ out_free: | |||
201 | static void __exit prng_exit(void) | 201 | static void __exit prng_exit(void) |
202 | { | 202 | { |
203 | /* wipe me */ | 203 | /* wipe me */ |
204 | memset(p->buf, 0, prng_chunk_size); | 204 | kzfree(p->buf); |
205 | kfree(p->buf); | ||
206 | kfree(p); | 205 | kfree(p); |
207 | 206 | ||
208 | misc_deregister(&prng_dev); | 207 | misc_deregister(&prng_dev); |
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 8e9243ae0c19..b30606f6d523 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h | |||
@@ -57,7 +57,7 @@ | |||
57 | * with operation of the form "set_bit(bitnr, flags)". | 57 | * with operation of the form "set_bit(bitnr, flags)". |
58 | */ | 58 | */ |
59 | 59 | ||
60 | /* bitmap tables from arch/S390/kernel/bitmap.S */ | 60 | /* bitmap tables from arch/s390/kernel/bitmap.c */ |
61 | extern const char _oi_bitmap[]; | 61 | extern const char _oi_bitmap[]; |
62 | extern const char _ni_bitmap[]; | 62 | extern const char _ni_bitmap[]; |
63 | extern const char _zb_findmap[]; | 63 | extern const char _zb_findmap[]; |
@@ -525,16 +525,16 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr, | |||
525 | static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) | 525 | static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) |
526 | { | 526 | { |
527 | #ifdef __s390x__ | 527 | #ifdef __s390x__ |
528 | if (likely((word & 0xffffffff) == 0xffffffff)) { | 528 | if ((word & 0xffffffff) == 0xffffffff) { |
529 | word >>= 32; | 529 | word >>= 32; |
530 | nr += 32; | 530 | nr += 32; |
531 | } | 531 | } |
532 | #endif | 532 | #endif |
533 | if (likely((word & 0xffff) == 0xffff)) { | 533 | if ((word & 0xffff) == 0xffff) { |
534 | word >>= 16; | 534 | word >>= 16; |
535 | nr += 16; | 535 | nr += 16; |
536 | } | 536 | } |
537 | if (likely((word & 0xff) == 0xff)) { | 537 | if ((word & 0xff) == 0xff) { |
538 | word >>= 8; | 538 | word >>= 8; |
539 | nr += 8; | 539 | nr += 8; |
540 | } | 540 | } |
@@ -549,16 +549,16 @@ static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) | |||
549 | static inline unsigned long __ffs_word(unsigned long nr, unsigned long word) | 549 | static inline unsigned long __ffs_word(unsigned long nr, unsigned long word) |
550 | { | 550 | { |
551 | #ifdef __s390x__ | 551 | #ifdef __s390x__ |
552 | if (likely((word & 0xffffffff) == 0)) { | 552 | if ((word & 0xffffffff) == 0) { |
553 | word >>= 32; | 553 | word >>= 32; |
554 | nr += 32; | 554 | nr += 32; |
555 | } | 555 | } |
556 | #endif | 556 | #endif |
557 | if (likely((word & 0xffff) == 0)) { | 557 | if ((word & 0xffff) == 0) { |
558 | word >>= 16; | 558 | word >>= 16; |
559 | nr += 16; | 559 | nr += 16; |
560 | } | 560 | } |
561 | if (likely((word & 0xff) == 0)) { | 561 | if ((word & 0xff) == 0) { |
562 | word >>= 8; | 562 | word >>= 8; |
563 | nr += 8; | 563 | nr += 8; |
564 | } | 564 | } |
diff --git a/arch/s390/include/asm/crw.h b/arch/s390/include/asm/crw.h new file mode 100644 index 000000000000..2185a6d619d3 --- /dev/null +++ b/arch/s390/include/asm/crw.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Data definitions for channel report processing | ||
3 | * Copyright IBM Corp. 2000,2009 | ||
4 | * Author(s): Ingo Adlung <adlung@de.ibm.com>, | ||
5 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, | ||
6 | * Cornelia Huck <cornelia.huck@de.ibm.com>, | ||
7 | * Heiko Carstens <heiko.carstens@de.ibm.com>, | ||
8 | */ | ||
9 | |||
10 | #ifndef _ASM_S390_CRW_H | ||
11 | #define _ASM_S390_CRW_H | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | |||
15 | /* | ||
16 | * Channel Report Word | ||
17 | */ | ||
18 | struct crw { | ||
19 | __u32 res1 : 1; /* reserved zero */ | ||
20 | __u32 slct : 1; /* solicited */ | ||
21 | __u32 oflw : 1; /* overflow */ | ||
22 | __u32 chn : 1; /* chained */ | ||
23 | __u32 rsc : 4; /* reporting source code */ | ||
24 | __u32 anc : 1; /* ancillary report */ | ||
25 | __u32 res2 : 1; /* reserved zero */ | ||
26 | __u32 erc : 6; /* error-recovery code */ | ||
27 | __u32 rsid : 16; /* reporting-source ID */ | ||
28 | } __attribute__ ((packed)); | ||
29 | |||
30 | typedef void (*crw_handler_t)(struct crw *, struct crw *, int); | ||
31 | |||
32 | extern int crw_register_handler(int rsc, crw_handler_t handler); | ||
33 | extern void crw_unregister_handler(int rsc); | ||
34 | extern void crw_handle_channel_report(void); | ||
35 | |||
36 | #define NR_RSCS 16 | ||
37 | |||
38 | #define CRW_RSC_MONITOR 0x2 /* monitoring facility */ | ||
39 | #define CRW_RSC_SCH 0x3 /* subchannel */ | ||
40 | #define CRW_RSC_CPATH 0x4 /* channel path */ | ||
41 | #define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */ | ||
42 | #define CRW_RSC_CSS 0xB /* channel subsystem */ | ||
43 | |||
44 | #define CRW_ERC_EVENT 0x00 /* event information pending */ | ||
45 | #define CRW_ERC_AVAIL 0x01 /* available */ | ||
46 | #define CRW_ERC_INIT 0x02 /* initialized */ | ||
47 | #define CRW_ERC_TERROR 0x03 /* temporary error */ | ||
48 | #define CRW_ERC_IPARM 0x04 /* installed parm initialized */ | ||
49 | #define CRW_ERC_TERM 0x05 /* terminal */ | ||
50 | #define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */ | ||
51 | #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ | ||
52 | #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ | ||
53 | |||
54 | static inline int stcrw(struct crw *pcrw) | ||
55 | { | ||
56 | int ccode; | ||
57 | |||
58 | asm volatile( | ||
59 | " stcrw 0(%2)\n" | ||
60 | " ipm %0\n" | ||
61 | " srl %0,28\n" | ||
62 | : "=d" (ccode), "=m" (*pcrw) | ||
63 | : "a" (pcrw) | ||
64 | : "cc" ); | ||
65 | return ccode; | ||
66 | } | ||
67 | |||
68 | #endif /* _ASM_S390_CRW_H */ | ||
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h index e2db6f16d9c8..218bce81ec70 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/asm/dasd.h | |||
@@ -162,15 +162,15 @@ typedef struct dasd_profile_info_t { | |||
162 | unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */ | 162 | unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */ |
163 | } dasd_profile_info_t; | 163 | } dasd_profile_info_t; |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * struct format_data_t | 166 | * struct format_data_t |
167 | * represents all data necessary to format a dasd | 167 | * represents all data necessary to format a dasd |
168 | */ | 168 | */ |
169 | typedef struct format_data_t { | 169 | typedef struct format_data_t { |
170 | int start_unit; /* from track */ | 170 | unsigned int start_unit; /* from track */ |
171 | int stop_unit; /* to track */ | 171 | unsigned int stop_unit; /* to track */ |
172 | int blksize; /* sectorsize */ | 172 | unsigned int blksize; /* sectorsize */ |
173 | int intensity; | 173 | unsigned int intensity; |
174 | } format_data_t; | 174 | } format_data_t; |
175 | 175 | ||
176 | /* | 176 | /* |
diff --git a/arch/s390/include/asm/idals.h b/arch/s390/include/asm/idals.h index e82c10efe65a..aae276d00383 100644 --- a/arch/s390/include/asm/idals.h +++ b/arch/s390/include/asm/idals.h | |||
@@ -44,24 +44,18 @@ idal_is_needed(void *vaddr, unsigned int length) | |||
44 | /* | 44 | /* |
45 | * Return the number of idal words needed for an address/length pair. | 45 | * Return the number of idal words needed for an address/length pair. |
46 | */ | 46 | */ |
47 | static inline unsigned int | 47 | static inline unsigned int idal_nr_words(void *vaddr, unsigned int length) |
48 | idal_nr_words(void *vaddr, unsigned int length) | ||
49 | { | 48 | { |
50 | #ifdef __s390x__ | 49 | return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length + |
51 | if (idal_is_needed(vaddr, length)) | 50 | (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG; |
52 | return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length + | ||
53 | (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG; | ||
54 | #endif | ||
55 | return 0; | ||
56 | } | 51 | } |
57 | 52 | ||
58 | /* | 53 | /* |
59 | * Create the list of idal words for an address/length pair. | 54 | * Create the list of idal words for an address/length pair. |
60 | */ | 55 | */ |
61 | static inline unsigned long * | 56 | static inline unsigned long *idal_create_words(unsigned long *idaws, |
62 | idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length) | 57 | void *vaddr, unsigned int length) |
63 | { | 58 | { |
64 | #ifdef __s390x__ | ||
65 | unsigned long paddr; | 59 | unsigned long paddr; |
66 | unsigned int cidaw; | 60 | unsigned int cidaw; |
67 | 61 | ||
@@ -74,7 +68,6 @@ idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length) | |||
74 | paddr += IDA_BLOCK_SIZE; | 68 | paddr += IDA_BLOCK_SIZE; |
75 | *idaws++ = paddr; | 69 | *idaws++ = paddr; |
76 | } | 70 | } |
77 | #endif | ||
78 | return idaws; | 71 | return idaws; |
79 | } | 72 | } |
80 | 73 | ||
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index f3720defdd16..b349f1c7fdfa 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
@@ -11,129 +11,118 @@ | |||
11 | #ifndef _ASM_S390_LOWCORE_H | 11 | #ifndef _ASM_S390_LOWCORE_H |
12 | #define _ASM_S390_LOWCORE_H | 12 | #define _ASM_S390_LOWCORE_H |
13 | 13 | ||
14 | #ifndef __s390x__ | 14 | #define __LC_IPL_PARMBLOCK_PTR 0x0014 |
15 | #define __LC_EXT_OLD_PSW 0x018 | 15 | #define __LC_EXT_PARAMS 0x0080 |
16 | #define __LC_SVC_OLD_PSW 0x020 | 16 | #define __LC_CPU_ADDRESS 0x0084 |
17 | #define __LC_PGM_OLD_PSW 0x028 | 17 | #define __LC_EXT_INT_CODE 0x0086 |
18 | #define __LC_MCK_OLD_PSW 0x030 | ||
19 | #define __LC_IO_OLD_PSW 0x038 | ||
20 | #define __LC_EXT_NEW_PSW 0x058 | ||
21 | #define __LC_SVC_NEW_PSW 0x060 | ||
22 | #define __LC_PGM_NEW_PSW 0x068 | ||
23 | #define __LC_MCK_NEW_PSW 0x070 | ||
24 | #define __LC_IO_NEW_PSW 0x078 | ||
25 | #else /* !__s390x__ */ | ||
26 | #define __LC_EXT_OLD_PSW 0x0130 | ||
27 | #define __LC_SVC_OLD_PSW 0x0140 | ||
28 | #define __LC_PGM_OLD_PSW 0x0150 | ||
29 | #define __LC_MCK_OLD_PSW 0x0160 | ||
30 | #define __LC_IO_OLD_PSW 0x0170 | ||
31 | #define __LC_EXT_NEW_PSW 0x01b0 | ||
32 | #define __LC_SVC_NEW_PSW 0x01c0 | ||
33 | #define __LC_PGM_NEW_PSW 0x01d0 | ||
34 | #define __LC_MCK_NEW_PSW 0x01e0 | ||
35 | #define __LC_IO_NEW_PSW 0x01f0 | ||
36 | #endif /* !__s390x__ */ | ||
37 | |||
38 | #define __LC_IPL_PARMBLOCK_PTR 0x014 | ||
39 | #define __LC_EXT_PARAMS 0x080 | ||
40 | #define __LC_CPU_ADDRESS 0x084 | ||
41 | #define __LC_EXT_INT_CODE 0x086 | ||
42 | |||
43 | #define __LC_SVC_ILC 0x088 | ||
44 | #define __LC_SVC_INT_CODE 0x08A | ||
45 | #define __LC_PGM_ILC 0x08C | ||
46 | #define __LC_PGM_INT_CODE 0x08E | ||
47 | 18 | ||
48 | #define __LC_PER_ATMID 0x096 | 19 | #define __LC_SVC_ILC 0x0088 |
49 | #define __LC_PER_ADDRESS 0x098 | 20 | #define __LC_SVC_INT_CODE 0x008a |
50 | #define __LC_PER_ACCESS_ID 0x0A1 | 21 | #define __LC_PGM_ILC 0x008c |
51 | #define __LC_AR_MODE_ID 0x0A3 | 22 | #define __LC_PGM_INT_CODE 0x008e |
52 | 23 | ||
53 | #define __LC_SUBCHANNEL_ID 0x0B8 | 24 | #define __LC_PER_ATMID 0x0096 |
54 | #define __LC_SUBCHANNEL_NR 0x0BA | 25 | #define __LC_PER_ADDRESS 0x0098 |
55 | #define __LC_IO_INT_PARM 0x0BC | 26 | #define __LC_PER_ACCESS_ID 0x00a1 |
56 | #define __LC_IO_INT_WORD 0x0C0 | 27 | #define __LC_AR_MODE_ID 0x00a3 |
57 | #define __LC_MCCK_CODE 0x0E8 | ||
58 | 28 | ||
59 | #define __LC_LAST_BREAK 0x110 | 29 | #define __LC_SUBCHANNEL_ID 0x00b8 |
60 | 30 | #define __LC_SUBCHANNEL_NR 0x00ba | |
61 | #define __LC_RETURN_PSW 0x200 | 31 | #define __LC_IO_INT_PARM 0x00bc |
62 | 32 | #define __LC_IO_INT_WORD 0x00c0 | |
63 | #define __LC_SAVE_AREA 0xC00 | 33 | #define __LC_MCCK_CODE 0x00e8 |
64 | |||
65 | #ifndef __s390x__ | ||
66 | #define __LC_IRB 0x208 | ||
67 | #define __LC_SYNC_ENTER_TIMER 0x248 | ||
68 | #define __LC_ASYNC_ENTER_TIMER 0x250 | ||
69 | #define __LC_EXIT_TIMER 0x258 | ||
70 | #define __LC_USER_TIMER 0x260 | ||
71 | #define __LC_SYSTEM_TIMER 0x268 | ||
72 | #define __LC_STEAL_TIMER 0x270 | ||
73 | #define __LC_LAST_UPDATE_TIMER 0x278 | ||
74 | #define __LC_LAST_UPDATE_CLOCK 0x280 | ||
75 | #define __LC_RETURN_MCCK_PSW 0x288 | ||
76 | #define __LC_KERNEL_STACK 0xC40 | ||
77 | #define __LC_THREAD_INFO 0xC44 | ||
78 | #define __LC_ASYNC_STACK 0xC48 | ||
79 | #define __LC_KERNEL_ASCE 0xC4C | ||
80 | #define __LC_USER_ASCE 0xC50 | ||
81 | #define __LC_PANIC_STACK 0xC54 | ||
82 | #define __LC_CPUID 0xC60 | ||
83 | #define __LC_CPUADDR 0xC68 | ||
84 | #define __LC_IPLDEV 0xC7C | ||
85 | #define __LC_CURRENT 0xC90 | ||
86 | #define __LC_INT_CLOCK 0xC98 | ||
87 | #else /* __s390x__ */ | ||
88 | #define __LC_IRB 0x210 | ||
89 | #define __LC_SYNC_ENTER_TIMER 0x250 | ||
90 | #define __LC_ASYNC_ENTER_TIMER 0x258 | ||
91 | #define __LC_EXIT_TIMER 0x260 | ||
92 | #define __LC_USER_TIMER 0x268 | ||
93 | #define __LC_SYSTEM_TIMER 0x270 | ||
94 | #define __LC_STEAL_TIMER 0x278 | ||
95 | #define __LC_LAST_UPDATE_TIMER 0x280 | ||
96 | #define __LC_LAST_UPDATE_CLOCK 0x288 | ||
97 | #define __LC_RETURN_MCCK_PSW 0x290 | ||
98 | #define __LC_KERNEL_STACK 0xD40 | ||
99 | #define __LC_THREAD_INFO 0xD48 | ||
100 | #define __LC_ASYNC_STACK 0xD50 | ||
101 | #define __LC_KERNEL_ASCE 0xD58 | ||
102 | #define __LC_USER_ASCE 0xD60 | ||
103 | #define __LC_PANIC_STACK 0xD68 | ||
104 | #define __LC_CPUID 0xD80 | ||
105 | #define __LC_CPUADDR 0xD88 | ||
106 | #define __LC_IPLDEV 0xDB8 | ||
107 | #define __LC_CURRENT 0xDD8 | ||
108 | #define __LC_INT_CLOCK 0xDE8 | ||
109 | #define __LC_VDSO_PER_CPU 0xE38 | ||
110 | #endif /* __s390x__ */ | ||
111 | 34 | ||
112 | #define __LC_PASTE 0xE40 | 35 | #define __LC_DUMP_REIPL 0x0e00 |
113 | 36 | ||
114 | #define __LC_PANIC_MAGIC 0xE00 | ||
115 | #ifndef __s390x__ | 37 | #ifndef __s390x__ |
116 | #define __LC_PFAULT_INTPARM 0x080 | 38 | #define __LC_EXT_OLD_PSW 0x0018 |
117 | #define __LC_CPU_TIMER_SAVE_AREA 0x0D8 | 39 | #define __LC_SVC_OLD_PSW 0x0020 |
118 | #define __LC_CLOCK_COMP_SAVE_AREA 0x0E0 | 40 | #define __LC_PGM_OLD_PSW 0x0028 |
119 | #define __LC_PSW_SAVE_AREA 0x100 | 41 | #define __LC_MCK_OLD_PSW 0x0030 |
120 | #define __LC_PREFIX_SAVE_AREA 0x108 | 42 | #define __LC_IO_OLD_PSW 0x0038 |
121 | #define __LC_AREGS_SAVE_AREA 0x120 | 43 | #define __LC_EXT_NEW_PSW 0x0058 |
122 | #define __LC_FPREGS_SAVE_AREA 0x160 | 44 | #define __LC_SVC_NEW_PSW 0x0060 |
123 | #define __LC_GPREGS_SAVE_AREA 0x180 | 45 | #define __LC_PGM_NEW_PSW 0x0068 |
124 | #define __LC_CREGS_SAVE_AREA 0x1C0 | 46 | #define __LC_MCK_NEW_PSW 0x0070 |
47 | #define __LC_IO_NEW_PSW 0x0078 | ||
48 | #define __LC_SAVE_AREA 0x0200 | ||
49 | #define __LC_RETURN_PSW 0x0240 | ||
50 | #define __LC_RETURN_MCCK_PSW 0x0248 | ||
51 | #define __LC_SYNC_ENTER_TIMER 0x0250 | ||
52 | #define __LC_ASYNC_ENTER_TIMER 0x0258 | ||
53 | #define __LC_EXIT_TIMER 0x0260 | ||
54 | #define __LC_USER_TIMER 0x0268 | ||
55 | #define __LC_SYSTEM_TIMER 0x0270 | ||
56 | #define __LC_STEAL_TIMER 0x0278 | ||
57 | #define __LC_LAST_UPDATE_TIMER 0x0280 | ||
58 | #define __LC_LAST_UPDATE_CLOCK 0x0288 | ||
59 | #define __LC_CURRENT 0x0290 | ||
60 | #define __LC_THREAD_INFO 0x0294 | ||
61 | #define __LC_KERNEL_STACK 0x0298 | ||
62 | #define __LC_ASYNC_STACK 0x029c | ||
63 | #define __LC_PANIC_STACK 0x02a0 | ||
64 | #define __LC_KERNEL_ASCE 0x02a4 | ||
65 | #define __LC_USER_ASCE 0x02a8 | ||
66 | #define __LC_USER_EXEC_ASCE 0x02ac | ||
67 | #define __LC_CPUID 0x02b0 | ||
68 | #define __LC_INT_CLOCK 0x02c8 | ||
69 | #define __LC_IRB 0x0300 | ||
70 | #define __LC_PFAULT_INTPARM 0x0080 | ||
71 | #define __LC_CPU_TIMER_SAVE_AREA 0x00d8 | ||
72 | #define __LC_CLOCK_COMP_SAVE_AREA 0x00e0 | ||
73 | #define __LC_PSW_SAVE_AREA 0x0100 | ||
74 | #define __LC_PREFIX_SAVE_AREA 0x0108 | ||
75 | #define __LC_AREGS_SAVE_AREA 0x0120 | ||
76 | #define __LC_FPREGS_SAVE_AREA 0x0160 | ||
77 | #define __LC_GPREGS_SAVE_AREA 0x0180 | ||
78 | #define __LC_CREGS_SAVE_AREA 0x01c0 | ||
125 | #else /* __s390x__ */ | 79 | #else /* __s390x__ */ |
126 | #define __LC_PFAULT_INTPARM 0x11B8 | 80 | #define __LC_LAST_BREAK 0x0110 |
81 | #define __LC_EXT_OLD_PSW 0x0130 | ||
82 | #define __LC_SVC_OLD_PSW 0x0140 | ||
83 | #define __LC_PGM_OLD_PSW 0x0150 | ||
84 | #define __LC_MCK_OLD_PSW 0x0160 | ||
85 | #define __LC_IO_OLD_PSW 0x0170 | ||
86 | #define __LC_EXT_NEW_PSW 0x01b0 | ||
87 | #define __LC_SVC_NEW_PSW 0x01c0 | ||
88 | #define __LC_PGM_NEW_PSW 0x01d0 | ||
89 | #define __LC_MCK_NEW_PSW 0x01e0 | ||
90 | #define __LC_IO_NEW_PSW 0x01f0 | ||
91 | #define __LC_SAVE_AREA 0x0200 | ||
92 | #define __LC_RETURN_PSW 0x0280 | ||
93 | #define __LC_RETURN_MCCK_PSW 0x0290 | ||
94 | #define __LC_SYNC_ENTER_TIMER 0x02a0 | ||
95 | #define __LC_ASYNC_ENTER_TIMER 0x02a8 | ||
96 | #define __LC_EXIT_TIMER 0x02b0 | ||
97 | #define __LC_USER_TIMER 0x02b8 | ||
98 | #define __LC_SYSTEM_TIMER 0x02c0 | ||
99 | #define __LC_STEAL_TIMER 0x02c8 | ||
100 | #define __LC_LAST_UPDATE_TIMER 0x02d0 | ||
101 | #define __LC_LAST_UPDATE_CLOCK 0x02d8 | ||
102 | #define __LC_CURRENT 0x02e0 | ||
103 | #define __LC_THREAD_INFO 0x02e8 | ||
104 | #define __LC_KERNEL_STACK 0x02f0 | ||
105 | #define __LC_ASYNC_STACK 0x02f8 | ||
106 | #define __LC_PANIC_STACK 0x0300 | ||
107 | #define __LC_KERNEL_ASCE 0x0308 | ||
108 | #define __LC_USER_ASCE 0x0310 | ||
109 | #define __LC_USER_EXEC_ASCE 0x0318 | ||
110 | #define __LC_CPUID 0x0320 | ||
111 | #define __LC_INT_CLOCK 0x0340 | ||
112 | #define __LC_VDSO_PER_CPU 0x0350 | ||
113 | #define __LC_IRB 0x0380 | ||
114 | #define __LC_PASTE 0x03c0 | ||
115 | #define __LC_PFAULT_INTPARM 0x11b8 | ||
127 | #define __LC_FPREGS_SAVE_AREA 0x1200 | 116 | #define __LC_FPREGS_SAVE_AREA 0x1200 |
128 | #define __LC_GPREGS_SAVE_AREA 0x1280 | 117 | #define __LC_GPREGS_SAVE_AREA 0x1280 |
129 | #define __LC_PSW_SAVE_AREA 0x1300 | 118 | #define __LC_PSW_SAVE_AREA 0x1300 |
130 | #define __LC_PREFIX_SAVE_AREA 0x1318 | 119 | #define __LC_PREFIX_SAVE_AREA 0x1318 |
131 | #define __LC_FP_CREG_SAVE_AREA 0x131C | 120 | #define __LC_FP_CREG_SAVE_AREA 0x131c |
132 | #define __LC_TODREG_SAVE_AREA 0x1324 | 121 | #define __LC_TODREG_SAVE_AREA 0x1324 |
133 | #define __LC_CPU_TIMER_SAVE_AREA 0x1328 | 122 | #define __LC_CPU_TIMER_SAVE_AREA 0x1328 |
134 | #define __LC_CLOCK_COMP_SAVE_AREA 0x1331 | 123 | #define __LC_CLOCK_COMP_SAVE_AREA 0x1331 |
135 | #define __LC_AREGS_SAVE_AREA 0x1340 | 124 | #define __LC_AREGS_SAVE_AREA 0x1340 |
136 | #define __LC_CREGS_SAVE_AREA 0x1380 | 125 | #define __LC_CREGS_SAVE_AREA 0x1380 |
137 | #endif /* __s390x__ */ | 126 | #endif /* __s390x__ */ |
138 | 127 | ||
139 | #ifndef __ASSEMBLY__ | 128 | #ifndef __ASSEMBLY__ |
@@ -198,222 +187,240 @@ union save_area { | |||
198 | struct _lowcore | 187 | struct _lowcore |
199 | { | 188 | { |
200 | #ifndef __s390x__ | 189 | #ifndef __s390x__ |
201 | /* prefix area: defined by architecture */ | 190 | /* 0x0000 - 0x01ff: defined by architecture */ |
202 | psw_t restart_psw; /* 0x000 */ | 191 | psw_t restart_psw; /* 0x0000 */ |
203 | __u32 ccw2[4]; /* 0x008 */ | 192 | __u32 ccw2[4]; /* 0x0008 */ |
204 | psw_t external_old_psw; /* 0x018 */ | 193 | psw_t external_old_psw; /* 0x0018 */ |
205 | psw_t svc_old_psw; /* 0x020 */ | 194 | psw_t svc_old_psw; /* 0x0020 */ |
206 | psw_t program_old_psw; /* 0x028 */ | 195 | psw_t program_old_psw; /* 0x0028 */ |
207 | psw_t mcck_old_psw; /* 0x030 */ | 196 | psw_t mcck_old_psw; /* 0x0030 */ |
208 | psw_t io_old_psw; /* 0x038 */ | 197 | psw_t io_old_psw; /* 0x0038 */ |
209 | __u8 pad1[0x58-0x40]; /* 0x040 */ | 198 | __u8 pad_0x0040[0x0058-0x0040]; /* 0x0040 */ |
210 | psw_t external_new_psw; /* 0x058 */ | 199 | psw_t external_new_psw; /* 0x0058 */ |
211 | psw_t svc_new_psw; /* 0x060 */ | 200 | psw_t svc_new_psw; /* 0x0060 */ |
212 | psw_t program_new_psw; /* 0x068 */ | 201 | psw_t program_new_psw; /* 0x0068 */ |
213 | psw_t mcck_new_psw; /* 0x070 */ | 202 | psw_t mcck_new_psw; /* 0x0070 */ |
214 | psw_t io_new_psw; /* 0x078 */ | 203 | psw_t io_new_psw; /* 0x0078 */ |
215 | __u32 ext_params; /* 0x080 */ | 204 | __u32 ext_params; /* 0x0080 */ |
216 | __u16 cpu_addr; /* 0x084 */ | 205 | __u16 cpu_addr; /* 0x0084 */ |
217 | __u16 ext_int_code; /* 0x086 */ | 206 | __u16 ext_int_code; /* 0x0086 */ |
218 | __u16 svc_ilc; /* 0x088 */ | 207 | __u16 svc_ilc; /* 0x0088 */ |
219 | __u16 svc_code; /* 0x08a */ | 208 | __u16 svc_code; /* 0x008a */ |
220 | __u16 pgm_ilc; /* 0x08c */ | 209 | __u16 pgm_ilc; /* 0x008c */ |
221 | __u16 pgm_code; /* 0x08e */ | 210 | __u16 pgm_code; /* 0x008e */ |
222 | __u32 trans_exc_code; /* 0x090 */ | 211 | __u32 trans_exc_code; /* 0x0090 */ |
223 | __u16 mon_class_num; /* 0x094 */ | 212 | __u16 mon_class_num; /* 0x0094 */ |
224 | __u16 per_perc_atmid; /* 0x096 */ | 213 | __u16 per_perc_atmid; /* 0x0096 */ |
225 | __u32 per_address; /* 0x098 */ | 214 | __u32 per_address; /* 0x0098 */ |
226 | __u32 monitor_code; /* 0x09c */ | 215 | __u32 monitor_code; /* 0x009c */ |
227 | __u8 exc_access_id; /* 0x0a0 */ | 216 | __u8 exc_access_id; /* 0x00a0 */ |
228 | __u8 per_access_id; /* 0x0a1 */ | 217 | __u8 per_access_id; /* 0x00a1 */ |
229 | __u8 pad2[0xB8-0xA2]; /* 0x0a2 */ | 218 | __u8 pad_0x00a2[0x00b8-0x00a2]; /* 0x00a2 */ |
230 | __u16 subchannel_id; /* 0x0b8 */ | 219 | __u16 subchannel_id; /* 0x00b8 */ |
231 | __u16 subchannel_nr; /* 0x0ba */ | 220 | __u16 subchannel_nr; /* 0x00ba */ |
232 | __u32 io_int_parm; /* 0x0bc */ | 221 | __u32 io_int_parm; /* 0x00bc */ |
233 | __u32 io_int_word; /* 0x0c0 */ | 222 | __u32 io_int_word; /* 0x00c0 */ |
234 | __u8 pad3[0xc8-0xc4]; /* 0x0c4 */ | 223 | __u8 pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */ |
235 | __u32 stfl_fac_list; /* 0x0c8 */ | 224 | __u32 stfl_fac_list; /* 0x00c8 */ |
236 | __u8 pad4[0xd4-0xcc]; /* 0x0cc */ | 225 | __u8 pad_0x00cc[0x00d4-0x00cc]; /* 0x00cc */ |
237 | __u32 extended_save_area_addr; /* 0x0d4 */ | 226 | __u32 extended_save_area_addr; /* 0x00d4 */ |
238 | __u32 cpu_timer_save_area[2]; /* 0x0d8 */ | 227 | __u32 cpu_timer_save_area[2]; /* 0x00d8 */ |
239 | __u32 clock_comp_save_area[2]; /* 0x0e0 */ | 228 | __u32 clock_comp_save_area[2]; /* 0x00e0 */ |
240 | __u32 mcck_interruption_code[2]; /* 0x0e8 */ | 229 | __u32 mcck_interruption_code[2]; /* 0x00e8 */ |
241 | __u8 pad5[0xf4-0xf0]; /* 0x0f0 */ | 230 | __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ |
242 | __u32 external_damage_code; /* 0x0f4 */ | 231 | __u32 external_damage_code; /* 0x00f4 */ |
243 | __u32 failing_storage_address; /* 0x0f8 */ | 232 | __u32 failing_storage_address; /* 0x00f8 */ |
244 | __u8 pad6[0x100-0xfc]; /* 0x0fc */ | 233 | __u8 pad_0x00fc[0x0100-0x00fc]; /* 0x00fc */ |
245 | __u32 st_status_fixed_logout[4];/* 0x100 */ | 234 | __u32 st_status_fixed_logout[4]; /* 0x0100 */ |
246 | __u8 pad7[0x120-0x110]; /* 0x110 */ | 235 | __u8 pad_0x0110[0x0120-0x0110]; /* 0x0110 */ |
247 | __u32 access_regs_save_area[16];/* 0x120 */ | 236 | |
248 | __u32 floating_pt_save_area[8]; /* 0x160 */ | 237 | /* CPU register save area: defined by architecture */ |
249 | __u32 gpregs_save_area[16]; /* 0x180 */ | 238 | __u32 access_regs_save_area[16]; /* 0x0120 */ |
250 | __u32 cregs_save_area[16]; /* 0x1c0 */ | 239 | __u32 floating_pt_save_area[8]; /* 0x0160 */ |
251 | 240 | __u32 gpregs_save_area[16]; /* 0x0180 */ | |
252 | psw_t return_psw; /* 0x200 */ | 241 | __u32 cregs_save_area[16]; /* 0x01c0 */ |
253 | __u8 irb[64]; /* 0x208 */ | 242 | |
254 | __u64 sync_enter_timer; /* 0x248 */ | 243 | /* Return psws. */ |
255 | __u64 async_enter_timer; /* 0x250 */ | 244 | __u32 save_area[16]; /* 0x0200 */ |
256 | __u64 exit_timer; /* 0x258 */ | 245 | psw_t return_psw; /* 0x0240 */ |
257 | __u64 user_timer; /* 0x260 */ | 246 | psw_t return_mcck_psw; /* 0x0248 */ |
258 | __u64 system_timer; /* 0x268 */ | 247 | |
259 | __u64 steal_timer; /* 0x270 */ | 248 | /* CPU time accounting values */ |
260 | __u64 last_update_timer; /* 0x278 */ | 249 | __u64 sync_enter_timer; /* 0x0250 */ |
261 | __u64 last_update_clock; /* 0x280 */ | 250 | __u64 async_enter_timer; /* 0x0258 */ |
262 | psw_t return_mcck_psw; /* 0x288 */ | 251 | __u64 exit_timer; /* 0x0260 */ |
263 | __u8 pad8[0xc00-0x290]; /* 0x290 */ | 252 | __u64 user_timer; /* 0x0268 */ |
264 | 253 | __u64 system_timer; /* 0x0270 */ | |
265 | /* System info area */ | 254 | __u64 steal_timer; /* 0x0278 */ |
266 | __u32 save_area[16]; /* 0xc00 */ | 255 | __u64 last_update_timer; /* 0x0280 */ |
267 | __u32 kernel_stack; /* 0xc40 */ | 256 | __u64 last_update_clock; /* 0x0288 */ |
268 | __u32 thread_info; /* 0xc44 */ | 257 | |
269 | __u32 async_stack; /* 0xc48 */ | 258 | /* Current process. */ |
270 | __u32 kernel_asce; /* 0xc4c */ | 259 | __u32 current_task; /* 0x0290 */ |
271 | __u32 user_asce; /* 0xc50 */ | 260 | __u32 thread_info; /* 0x0294 */ |
272 | __u32 panic_stack; /* 0xc54 */ | 261 | __u32 kernel_stack; /* 0x0298 */ |
273 | __u32 user_exec_asce; /* 0xc58 */ | 262 | |
274 | __u8 pad10[0xc60-0xc5c]; /* 0xc5c */ | 263 | /* Interrupt and panic stack. */ |
275 | /* entry.S sensitive area start */ | 264 | __u32 async_stack; /* 0x029c */ |
276 | struct cpuinfo_S390 cpu_data; /* 0xc60 */ | 265 | __u32 panic_stack; /* 0x02a0 */ |
277 | __u32 ipl_device; /* 0xc7c */ | 266 | |
278 | /* entry.S sensitive area end */ | 267 | /* Address space pointer. */ |
279 | 268 | __u32 kernel_asce; /* 0x02a4 */ | |
280 | /* SMP info area: defined by DJB */ | 269 | __u32 user_asce; /* 0x02a8 */ |
281 | __u64 clock_comparator; /* 0xc80 */ | 270 | __u32 user_exec_asce; /* 0x02ac */ |
282 | __u32 ext_call_fast; /* 0xc88 */ | 271 | |
283 | __u32 percpu_offset; /* 0xc8c */ | 272 | /* SMP info area */ |
284 | __u32 current_task; /* 0xc90 */ | 273 | cpuid_t cpu_id; /* 0x02b0 */ |
285 | __u32 softirq_pending; /* 0xc94 */ | 274 | __u32 cpu_nr; /* 0x02b8 */ |
286 | __u64 int_clock; /* 0xc98 */ | 275 | __u32 softirq_pending; /* 0x02bc */ |
287 | __u8 pad11[0xe00-0xca0]; /* 0xca0 */ | 276 | __u32 percpu_offset; /* 0x02c0 */ |
288 | 277 | __u32 ext_call_fast; /* 0x02c4 */ | |
289 | /* 0xe00 is used as indicator for dump tools */ | 278 | __u64 int_clock; /* 0x02c8 */ |
290 | /* whether the kernel died with panic() or not */ | 279 | __u64 clock_comparator; /* 0x02d0 */ |
291 | __u32 panic_magic; /* 0xe00 */ | 280 | __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */ |
292 | 281 | ||
293 | /* Align to the top 1k of prefix area */ | 282 | /* Interrupt response block */ |
294 | __u8 pad12[0x1000-0xe04]; /* 0xe04 */ | 283 | __u8 irb[64]; /* 0x0300 */ |
284 | |||
285 | __u8 pad_0x0400[0x0e00-0x0400]; /* 0x0400 */ | ||
286 | |||
287 | /* | ||
288 | * 0xe00 contains the address of the IPL Parameter Information | ||
289 | * block. Dump tools need IPIB for IPL after dump. | ||
290 | * Note: do not change the position of any fields in 0x0e00-0x0f00 | ||
291 | */ | ||
292 | __u32 ipib; /* 0x0e00 */ | ||
293 | __u32 ipib_checksum; /* 0x0e04 */ | ||
294 | |||
295 | /* Align to the top 1k of prefix area */ | ||
296 | __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ | ||
295 | #else /* !__s390x__ */ | 297 | #else /* !__s390x__ */ |
296 | /* prefix area: defined by architecture */ | 298 | /* 0x0000 - 0x01ff: defined by architecture */ |
297 | __u32 ccw1[2]; /* 0x000 */ | 299 | __u32 ccw1[2]; /* 0x0000 */ |
298 | __u32 ccw2[4]; /* 0x008 */ | 300 | __u32 ccw2[4]; /* 0x0008 */ |
299 | __u8 pad1[0x80-0x18]; /* 0x018 */ | 301 | __u8 pad_0x0018[0x0080-0x0018]; /* 0x0018 */ |
300 | __u32 ext_params; /* 0x080 */ | 302 | __u32 ext_params; /* 0x0080 */ |
301 | __u16 cpu_addr; /* 0x084 */ | 303 | __u16 cpu_addr; /* 0x0084 */ |
302 | __u16 ext_int_code; /* 0x086 */ | 304 | __u16 ext_int_code; /* 0x0086 */ |
303 | __u16 svc_ilc; /* 0x088 */ | 305 | __u16 svc_ilc; /* 0x0088 */ |
304 | __u16 svc_code; /* 0x08a */ | 306 | __u16 svc_code; /* 0x008a */ |
305 | __u16 pgm_ilc; /* 0x08c */ | 307 | __u16 pgm_ilc; /* 0x008c */ |
306 | __u16 pgm_code; /* 0x08e */ | 308 | __u16 pgm_code; /* 0x008e */ |
307 | __u32 data_exc_code; /* 0x090 */ | 309 | __u32 data_exc_code; /* 0x0090 */ |
308 | __u16 mon_class_num; /* 0x094 */ | 310 | __u16 mon_class_num; /* 0x0094 */ |
309 | __u16 per_perc_atmid; /* 0x096 */ | 311 | __u16 per_perc_atmid; /* 0x0096 */ |
310 | addr_t per_address; /* 0x098 */ | 312 | addr_t per_address; /* 0x0098 */ |
311 | __u8 exc_access_id; /* 0x0a0 */ | 313 | __u8 exc_access_id; /* 0x00a0 */ |
312 | __u8 per_access_id; /* 0x0a1 */ | 314 | __u8 per_access_id; /* 0x00a1 */ |
313 | __u8 op_access_id; /* 0x0a2 */ | 315 | __u8 op_access_id; /* 0x00a2 */ |
314 | __u8 ar_access_id; /* 0x0a3 */ | 316 | __u8 ar_access_id; /* 0x00a3 */ |
315 | __u8 pad2[0xA8-0xA4]; /* 0x0a4 */ | 317 | __u8 pad_0x00a4[0x00a8-0x00a4]; /* 0x00a4 */ |
316 | addr_t trans_exc_code; /* 0x0A0 */ | 318 | addr_t trans_exc_code; /* 0x00a8 */ |
317 | addr_t monitor_code; /* 0x09c */ | 319 | addr_t monitor_code; /* 0x00b0 */ |
318 | __u16 subchannel_id; /* 0x0b8 */ | 320 | __u16 subchannel_id; /* 0x00b8 */ |
319 | __u16 subchannel_nr; /* 0x0ba */ | 321 | __u16 subchannel_nr; /* 0x00ba */ |
320 | __u32 io_int_parm; /* 0x0bc */ | 322 | __u32 io_int_parm; /* 0x00bc */ |
321 | __u32 io_int_word; /* 0x0c0 */ | 323 | __u32 io_int_word; /* 0x00c0 */ |
322 | __u8 pad3[0xc8-0xc4]; /* 0x0c4 */ | 324 | __u8 pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */ |
323 | __u32 stfl_fac_list; /* 0x0c8 */ | 325 | __u32 stfl_fac_list; /* 0x00c8 */ |
324 | __u8 pad4[0xe8-0xcc]; /* 0x0cc */ | 326 | __u8 pad_0x00cc[0x00e8-0x00cc]; /* 0x00cc */ |
325 | __u32 mcck_interruption_code[2]; /* 0x0e8 */ | 327 | __u32 mcck_interruption_code[2]; /* 0x00e8 */ |
326 | __u8 pad5[0xf4-0xf0]; /* 0x0f0 */ | 328 | __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ |
327 | __u32 external_damage_code; /* 0x0f4 */ | 329 | __u32 external_damage_code; /* 0x00f4 */ |
328 | addr_t failing_storage_address; /* 0x0f8 */ | 330 | addr_t failing_storage_address; /* 0x00f8 */ |
329 | __u8 pad6[0x120-0x100]; /* 0x100 */ | 331 | __u8 pad_0x0100[0x0120-0x0100]; /* 0x0100 */ |
330 | psw_t restart_old_psw; /* 0x120 */ | 332 | psw_t restart_old_psw; /* 0x0120 */ |
331 | psw_t external_old_psw; /* 0x130 */ | 333 | psw_t external_old_psw; /* 0x0130 */ |
332 | psw_t svc_old_psw; /* 0x140 */ | 334 | psw_t svc_old_psw; /* 0x0140 */ |
333 | psw_t program_old_psw; /* 0x150 */ | 335 | psw_t program_old_psw; /* 0x0150 */ |
334 | psw_t mcck_old_psw; /* 0x160 */ | 336 | psw_t mcck_old_psw; /* 0x0160 */ |
335 | psw_t io_old_psw; /* 0x170 */ | 337 | psw_t io_old_psw; /* 0x0170 */ |
336 | __u8 pad7[0x1a0-0x180]; /* 0x180 */ | 338 | __u8 pad_0x0180[0x01a0-0x0180]; /* 0x0180 */ |
337 | psw_t restart_psw; /* 0x1a0 */ | 339 | psw_t restart_psw; /* 0x01a0 */ |
338 | psw_t external_new_psw; /* 0x1b0 */ | 340 | psw_t external_new_psw; /* 0x01b0 */ |
339 | psw_t svc_new_psw; /* 0x1c0 */ | 341 | psw_t svc_new_psw; /* 0x01c0 */ |
340 | psw_t program_new_psw; /* 0x1d0 */ | 342 | psw_t program_new_psw; /* 0x01d0 */ |
341 | psw_t mcck_new_psw; /* 0x1e0 */ | 343 | psw_t mcck_new_psw; /* 0x01e0 */ |
342 | psw_t io_new_psw; /* 0x1f0 */ | 344 | psw_t io_new_psw; /* 0x01f0 */ |
343 | psw_t return_psw; /* 0x200 */ | 345 | |
344 | __u8 irb[64]; /* 0x210 */ | 346 | /* Entry/exit save area & return psws. */ |
345 | __u64 sync_enter_timer; /* 0x250 */ | 347 | __u64 save_area[16]; /* 0x0200 */ |
346 | __u64 async_enter_timer; /* 0x258 */ | 348 | psw_t return_psw; /* 0x0280 */ |
347 | __u64 exit_timer; /* 0x260 */ | 349 | psw_t return_mcck_psw; /* 0x0290 */ |
348 | __u64 user_timer; /* 0x268 */ | 350 | |
349 | __u64 system_timer; /* 0x270 */ | 351 | /* CPU accounting and timing values. */ |
350 | __u64 steal_timer; /* 0x278 */ | 352 | __u64 sync_enter_timer; /* 0x02a0 */ |
351 | __u64 last_update_timer; /* 0x280 */ | 353 | __u64 async_enter_timer; /* 0x02a8 */ |
352 | __u64 last_update_clock; /* 0x288 */ | 354 | __u64 exit_timer; /* 0x02b0 */ |
353 | psw_t return_mcck_psw; /* 0x290 */ | 355 | __u64 user_timer; /* 0x02b8 */ |
354 | __u8 pad8[0xc00-0x2a0]; /* 0x2a0 */ | 356 | __u64 system_timer; /* 0x02c0 */ |
355 | /* System info area */ | 357 | __u64 steal_timer; /* 0x02c8 */ |
356 | __u64 save_area[16]; /* 0xc00 */ | 358 | __u64 last_update_timer; /* 0x02d0 */ |
357 | __u8 pad9[0xd40-0xc80]; /* 0xc80 */ | 359 | __u64 last_update_clock; /* 0x02d8 */ |
358 | __u64 kernel_stack; /* 0xd40 */ | 360 | |
359 | __u64 thread_info; /* 0xd48 */ | 361 | /* Current process. */ |
360 | __u64 async_stack; /* 0xd50 */ | 362 | __u64 current_task; /* 0x02e0 */ |
361 | __u64 kernel_asce; /* 0xd58 */ | 363 | __u64 thread_info; /* 0x02e8 */ |
362 | __u64 user_asce; /* 0xd60 */ | 364 | __u64 kernel_stack; /* 0x02f0 */ |
363 | __u64 panic_stack; /* 0xd68 */ | 365 | |
364 | __u64 user_exec_asce; /* 0xd70 */ | 366 | /* Interrupt and panic stack. */ |
365 | __u8 pad10[0xd80-0xd78]; /* 0xd78 */ | 367 | __u64 async_stack; /* 0x02f8 */ |
366 | /* entry.S sensitive area start */ | 368 | __u64 panic_stack; /* 0x0300 */ |
367 | struct cpuinfo_S390 cpu_data; /* 0xd80 */ | 369 | |
368 | __u32 ipl_device; /* 0xdb8 */ | 370 | /* Address space pointer. */ |
369 | __u32 pad11; /* 0xdbc */ | 371 | __u64 kernel_asce; /* 0x0308 */ |
370 | /* entry.S sensitive area end */ | 372 | __u64 user_asce; /* 0x0310 */ |
371 | 373 | __u64 user_exec_asce; /* 0x0318 */ | |
372 | /* SMP info area: defined by DJB */ | 374 | |
373 | __u64 clock_comparator; /* 0xdc0 */ | 375 | /* SMP info area */ |
374 | __u64 ext_call_fast; /* 0xdc8 */ | 376 | cpuid_t cpu_id; /* 0x0320 */ |
375 | __u64 percpu_offset; /* 0xdd0 */ | 377 | __u32 cpu_nr; /* 0x0328 */ |
376 | __u64 current_task; /* 0xdd8 */ | 378 | __u32 softirq_pending; /* 0x032c */ |
377 | __u32 softirq_pending; /* 0xde0 */ | 379 | __u64 percpu_offset; /* 0x0330 */ |
378 | __u32 pad_0x0de4; /* 0xde4 */ | 380 | __u64 ext_call_fast; /* 0x0338 */ |
379 | __u64 int_clock; /* 0xde8 */ | 381 | __u64 int_clock; /* 0x0340 */ |
380 | __u8 pad12[0xe00-0xdf0]; /* 0xdf0 */ | 382 | __u64 clock_comparator; /* 0x0348 */ |
381 | 383 | __u64 vdso_per_cpu_data; /* 0x0350 */ | |
382 | /* 0xe00 is used as indicator for dump tools */ | 384 | __u8 pad_0x0358[0x0380-0x0358]; /* 0x0358 */ |
383 | /* whether the kernel died with panic() or not */ | 385 | |
384 | __u32 panic_magic; /* 0xe00 */ | 386 | /* Interrupt response block. */ |
387 | __u8 irb[64]; /* 0x0380 */ | ||
385 | 388 | ||
386 | /* Per cpu primary space access list */ | 389 | /* Per cpu primary space access list */ |
387 | __u8 pad_0xe04[0xe38-0xe04]; /* 0xe04 */ | 390 | __u32 paste[16]; /* 0x03c0 */ |
388 | __u64 vdso_per_cpu_data; /* 0xe38 */ | 391 | |
389 | __u32 paste[16]; /* 0xe40 */ | 392 | __u8 pad_0x0400[0x0e00-0x0400]; /* 0x0400 */ |
390 | 393 | ||
391 | __u8 pad13[0x11b8-0xe80]; /* 0xe80 */ | 394 | /* |
392 | 395 | * 0xe00 contains the address of the IPL Parameter Information | |
393 | /* 64 bit extparam used for pfault, diag 250 etc */ | 396 | * block. Dump tools need IPIB for IPL after dump. |
394 | __u64 ext_params2; /* 0x11B8 */ | 397 | * Note: do not change the position of any fields in 0x0e00-0x0f00 |
395 | 398 | */ | |
396 | __u8 pad14[0x1200-0x11C0]; /* 0x11C0 */ | 399 | __u64 ipib; /* 0x0e00 */ |
397 | 400 | __u32 ipib_checksum; /* 0x0e08 */ | |
398 | /* System info area */ | 401 | __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */ |
399 | 402 | ||
400 | __u64 floating_pt_save_area[16]; /* 0x1200 */ | 403 | /* 64 bit extparam used for pfault/diag 250: defined by architecture */ |
401 | __u64 gpregs_save_area[16]; /* 0x1280 */ | 404 | __u64 ext_params2; /* 0x11B8 */ |
402 | __u32 st_status_fixed_logout[4]; /* 0x1300 */ | 405 | __u8 pad_0x11c0[0x1200-0x11C0]; /* 0x11C0 */ |
403 | __u8 pad15[0x1318-0x1310]; /* 0x1310 */ | 406 | |
404 | __u32 prefixreg_save_area; /* 0x1318 */ | 407 | /* CPU register save area: defined by architecture */ |
405 | __u32 fpt_creg_save_area; /* 0x131c */ | 408 | __u64 floating_pt_save_area[16]; /* 0x1200 */ |
406 | __u8 pad16[0x1324-0x1320]; /* 0x1320 */ | 409 | __u64 gpregs_save_area[16]; /* 0x1280 */ |
407 | __u32 tod_progreg_save_area; /* 0x1324 */ | 410 | __u32 st_status_fixed_logout[4]; /* 0x1300 */ |
408 | __u32 cpu_timer_save_area[2]; /* 0x1328 */ | 411 | __u8 pad_0x1310[0x1318-0x1310]; /* 0x1310 */ |
409 | __u32 clock_comp_save_area[2]; /* 0x1330 */ | 412 | __u32 prefixreg_save_area; /* 0x1318 */ |
410 | __u8 pad17[0x1340-0x1338]; /* 0x1338 */ | 413 | __u32 fpt_creg_save_area; /* 0x131c */ |
411 | __u32 access_regs_save_area[16]; /* 0x1340 */ | 414 | __u8 pad_0x1320[0x1324-0x1320]; /* 0x1320 */ |
412 | __u64 cregs_save_area[16]; /* 0x1380 */ | 415 | __u32 tod_progreg_save_area; /* 0x1324 */ |
416 | __u32 cpu_timer_save_area[2]; /* 0x1328 */ | ||
417 | __u32 clock_comp_save_area[2]; /* 0x1330 */ | ||
418 | __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */ | ||
419 | __u32 access_regs_save_area[16]; /* 0x1340 */ | ||
420 | __u64 cregs_save_area[16]; /* 0x1380 */ | ||
413 | 421 | ||
414 | /* align to the top of the prefix area */ | 422 | /* align to the top of the prefix area */ |
415 | 423 | __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */ | |
416 | __u8 pad18[0x2000-0x1400]; /* 0x1400 */ | ||
417 | #endif /* !__s390x__ */ | 424 | #endif /* !__s390x__ */ |
418 | } __attribute__((packed)); /* End structure*/ | 425 | } __attribute__((packed)); /* End structure*/ |
419 | 426 | ||
@@ -433,8 +440,6 @@ static inline __u32 store_prefix(void) | |||
433 | return address; | 440 | return address; |
434 | } | 441 | } |
435 | 442 | ||
436 | #define __PANIC_MAGIC 0xDEADC0DE | ||
437 | |||
438 | #endif | 443 | #endif |
439 | 444 | ||
440 | #endif | 445 | #endif |
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 28ec870655af..fc7edd6f41b6 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h | |||
@@ -74,7 +74,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) | |||
74 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 74 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
75 | struct task_struct *tsk) | 75 | struct task_struct *tsk) |
76 | { | 76 | { |
77 | cpu_set(smp_processor_id(), next->cpu_vm_mask); | 77 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); |
78 | update_mm(next, tsk); | 78 | update_mm(next, tsk); |
79 | } | 79 | } |
80 | 80 | ||
diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h new file mode 100644 index 000000000000..f4b60441adca --- /dev/null +++ b/arch/s390/include/asm/nmi.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Machine check handler definitions | ||
3 | * | ||
4 | * Copyright IBM Corp. 2000,2009 | ||
5 | * Author(s): Ingo Adlung <adlung@de.ibm.com>, | ||
6 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, | ||
7 | * Cornelia Huck <cornelia.huck@de.ibm.com>, | ||
8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, | ||
9 | */ | ||
10 | |||
11 | #ifndef _ASM_S390_NMI_H | ||
12 | #define _ASM_S390_NMI_H | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | |||
16 | struct mci { | ||
17 | __u32 sd : 1; /* 00 system damage */ | ||
18 | __u32 pd : 1; /* 01 instruction-processing damage */ | ||
19 | __u32 sr : 1; /* 02 system recovery */ | ||
20 | __u32 : 1; /* 03 */ | ||
21 | __u32 cd : 1; /* 04 timing-facility damage */ | ||
22 | __u32 ed : 1; /* 05 external damage */ | ||
23 | __u32 : 1; /* 06 */ | ||
24 | __u32 dg : 1; /* 07 degradation */ | ||
25 | __u32 w : 1; /* 08 warning pending */ | ||
26 | __u32 cp : 1; /* 09 channel-report pending */ | ||
27 | __u32 sp : 1; /* 10 service-processor damage */ | ||
28 | __u32 ck : 1; /* 11 channel-subsystem damage */ | ||
29 | __u32 : 2; /* 12-13 */ | ||
30 | __u32 b : 1; /* 14 backed up */ | ||
31 | __u32 : 1; /* 15 */ | ||
32 | __u32 se : 1; /* 16 storage error uncorrected */ | ||
33 | __u32 sc : 1; /* 17 storage error corrected */ | ||
34 | __u32 ke : 1; /* 18 storage-key error uncorrected */ | ||
35 | __u32 ds : 1; /* 19 storage degradation */ | ||
36 | __u32 wp : 1; /* 20 psw mwp validity */ | ||
37 | __u32 ms : 1; /* 21 psw mask and key validity */ | ||
38 | __u32 pm : 1; /* 22 psw program mask and cc validity */ | ||
39 | __u32 ia : 1; /* 23 psw instruction address validity */ | ||
40 | __u32 fa : 1; /* 24 failing storage address validity */ | ||
41 | __u32 : 1; /* 25 */ | ||
42 | __u32 ec : 1; /* 26 external damage code validity */ | ||
43 | __u32 fp : 1; /* 27 floating point register validity */ | ||
44 | __u32 gr : 1; /* 28 general register validity */ | ||
45 | __u32 cr : 1; /* 29 control register validity */ | ||
46 | __u32 : 1; /* 30 */ | ||
47 | __u32 st : 1; /* 31 storage logical validity */ | ||
48 | __u32 ie : 1; /* 32 indirect storage error */ | ||
49 | __u32 ar : 1; /* 33 access register validity */ | ||
50 | __u32 da : 1; /* 34 delayed access exception */ | ||
51 | __u32 : 7; /* 35-41 */ | ||
52 | __u32 pr : 1; /* 42 tod programmable register validity */ | ||
53 | __u32 fc : 1; /* 43 fp control register validity */ | ||
54 | __u32 ap : 1; /* 44 ancillary report */ | ||
55 | __u32 : 1; /* 45 */ | ||
56 | __u32 ct : 1; /* 46 cpu timer validity */ | ||
57 | __u32 cc : 1; /* 47 clock comparator validity */ | ||
58 | __u32 : 16; /* 47-63 */ | ||
59 | }; | ||
60 | |||
61 | struct pt_regs; | ||
62 | |||
63 | extern void s390_handle_mcck(void); | ||
64 | extern void s390_do_machine_check(struct pt_regs *regs); | ||
65 | |||
66 | #endif /* _ASM_S390_NMI_H */ | ||
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index db4523fe38ac..61862b3ac794 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -42,22 +42,8 @@ static inline void get_cpu_id(cpuid_t *ptr) | |||
42 | asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); | 42 | asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); |
43 | } | 43 | } |
44 | 44 | ||
45 | struct cpuinfo_S390 | ||
46 | { | ||
47 | cpuid_t cpu_id; | ||
48 | __u16 cpu_addr; | ||
49 | __u16 cpu_nr; | ||
50 | unsigned long loops_per_jiffy; | ||
51 | unsigned long *pgd_quick; | ||
52 | #ifdef __s390x__ | ||
53 | unsigned long *pmd_quick; | ||
54 | #endif /* __s390x__ */ | ||
55 | unsigned long *pte_quick; | ||
56 | unsigned long pgtable_cache_sz; | ||
57 | }; | ||
58 | |||
59 | extern void s390_adjust_jiffies(void); | 45 | extern void s390_adjust_jiffies(void); |
60 | extern void print_cpu_info(struct cpuinfo_S390 *); | 46 | extern void print_cpu_info(void); |
61 | extern int get_cpu_capability(unsigned int *); | 47 | extern int get_cpu_capability(unsigned int *); |
62 | 48 | ||
63 | /* | 49 | /* |
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 8920025c3c02..f1b051630c50 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
@@ -172,6 +172,8 @@ | |||
172 | #define NUM_CRS 16 | 172 | #define NUM_CRS 16 |
173 | #define NUM_ACRS 16 | 173 | #define NUM_ACRS 16 |
174 | 174 | ||
175 | #define NUM_CR_WORDS 3 | ||
176 | |||
175 | #define FPR_SIZE 8 | 177 | #define FPR_SIZE 8 |
176 | #define FPC_SIZE 4 | 178 | #define FPC_SIZE 4 |
177 | #define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */ | 179 | #define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */ |
@@ -334,7 +336,7 @@ struct pt_regs | |||
334 | */ | 336 | */ |
335 | typedef struct | 337 | typedef struct |
336 | { | 338 | { |
337 | unsigned long cr[3]; | 339 | unsigned long cr[NUM_CR_WORDS]; |
338 | } per_cr_words; | 340 | } per_cr_words; |
339 | 341 | ||
340 | #define PER_EM_MASK 0xE8000000UL | 342 | #define PER_EM_MASK 0xE8000000UL |
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 27fc1746de15..402d6dcf0d26 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h | |||
@@ -314,6 +314,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, | |||
314 | int, int, unsigned long); | 314 | int, int, unsigned long); |
315 | 315 | ||
316 | /* qdio errors reported to the upper-layer program */ | 316 | /* qdio errors reported to the upper-layer program */ |
317 | #define QDIO_ERROR_SIGA_TARGET 0x02 | ||
317 | #define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10 | 318 | #define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10 |
318 | #define QDIO_ERROR_SIGA_BUSY 0x20 | 319 | #define QDIO_ERROR_SIGA_BUSY 0x20 |
319 | #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 | 320 | #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 |
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index 024b91e06239..2009158a4502 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h | |||
@@ -50,12 +50,7 @@ extern void machine_power_off_smp(void); | |||
50 | 50 | ||
51 | #define PROC_CHANGE_PENALTY 20 /* Schedule penalty */ | 51 | #define PROC_CHANGE_PENALTY 20 /* Schedule penalty */ |
52 | 52 | ||
53 | #define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr) | 53 | #define raw_smp_processor_id() (S390_lowcore.cpu_nr) |
54 | |||
55 | static inline __u16 hard_smp_processor_id(void) | ||
56 | { | ||
57 | return stap(); | ||
58 | } | ||
59 | 54 | ||
60 | /* | 55 | /* |
61 | * returns 1 if cpu is in stopped/check stopped state or not operational | 56 | * returns 1 if cpu is in stopped/check stopped state or not operational |
diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h index d074673a6d9b..cd0241db5a46 100644 --- a/arch/s390/include/asm/string.h +++ b/arch/s390/include/asm/string.h | |||
@@ -100,6 +100,7 @@ static inline char *strcat(char *dst, const char *src) | |||
100 | 100 | ||
101 | static inline char *strcpy(char *dst, const char *src) | 101 | static inline char *strcpy(char *dst, const char *src) |
102 | { | 102 | { |
103 | #if __GNUC__ < 4 | ||
103 | register int r0 asm("0") = 0; | 104 | register int r0 asm("0") = 0; |
104 | char *ret = dst; | 105 | char *ret = dst; |
105 | 106 | ||
@@ -109,10 +110,14 @@ static inline char *strcpy(char *dst, const char *src) | |||
109 | : "+&a" (dst), "+&a" (src) : "d" (r0) | 110 | : "+&a" (dst), "+&a" (src) : "d" (r0) |
110 | : "cc", "memory"); | 111 | : "cc", "memory"); |
111 | return ret; | 112 | return ret; |
113 | #else | ||
114 | return __builtin_strcpy(dst, src); | ||
115 | #endif | ||
112 | } | 116 | } |
113 | 117 | ||
114 | static inline size_t strlen(const char *s) | 118 | static inline size_t strlen(const char *s) |
115 | { | 119 | { |
120 | #if __GNUC__ < 4 | ||
116 | register unsigned long r0 asm("0") = 0; | 121 | register unsigned long r0 asm("0") = 0; |
117 | const char *tmp = s; | 122 | const char *tmp = s; |
118 | 123 | ||
@@ -121,6 +126,9 @@ static inline size_t strlen(const char *s) | |||
121 | " jo 0b" | 126 | " jo 0b" |
122 | : "+d" (r0), "+a" (tmp) : : "cc"); | 127 | : "+d" (r0), "+a" (tmp) : : "cc"); |
123 | return r0 - (unsigned long) s; | 128 | return r0 - (unsigned long) s; |
129 | #else | ||
130 | return __builtin_strlen(s); | ||
131 | #endif | ||
124 | } | 132 | } |
125 | 133 | ||
126 | static inline size_t strnlen(const char * s, size_t n) | 134 | 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) | |||
135 | : "+a" (end), "+a" (tmp) : "d" (r0) : "cc"); | 143 | : "+a" (end), "+a" (tmp) : "d" (r0) : "cc"); |
136 | return end - s; | 144 | return end - s; |
137 | } | 145 | } |
138 | 146 | #else /* IN_ARCH_STRING_C */ | |
147 | void *memchr(const void * s, int c, size_t n); | ||
148 | void *memscan(void *s, int c, size_t n); | ||
149 | char *strcat(char *dst, const char *src); | ||
150 | char *strcpy(char *dst, const char *src); | ||
151 | size_t strlen(const char *s); | ||
152 | size_t strnlen(const char * s, size_t n); | ||
139 | #endif /* !IN_ARCH_STRING_C */ | 153 | #endif /* !IN_ARCH_STRING_C */ |
140 | 154 | ||
141 | #endif /* __KERNEL__ */ | 155 | #endif /* __KERNEL__ */ |
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index ad93212d9e16..9d70057d828c 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h | |||
@@ -100,6 +100,7 @@ struct sysinfo_3_2_2 { | |||
100 | char reserved_1[24]; | 100 | char reserved_1[24]; |
101 | 101 | ||
102 | } vm[8]; | 102 | } vm[8]; |
103 | char reserved_544[3552]; | ||
103 | }; | 104 | }; |
104 | 105 | ||
105 | static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) | 106 | static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) |
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index d60394b9745e..304cffa623e1 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h | |||
@@ -51,7 +51,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm) | |||
51 | * If the process only ran on the local cpu, do a local flush. | 51 | * If the process only ran on the local cpu, do a local flush. |
52 | */ | 52 | */ |
53 | local_cpumask = cpumask_of_cpu(smp_processor_id()); | 53 | local_cpumask = cpumask_of_cpu(smp_processor_id()); |
54 | if (cpus_equal(mm->cpu_vm_mask, local_cpumask)) | 54 | if (cpumask_equal(mm_cpumask(mm), &local_cpumask)) |
55 | __tlb_flush_local(); | 55 | __tlb_flush_local(); |
56 | else | 56 | else |
57 | __tlb_flush_global(); | 57 | __tlb_flush_global(); |
@@ -73,7 +73,7 @@ static inline void __tlb_flush_idte(unsigned long asce) | |||
73 | 73 | ||
74 | static inline void __tlb_flush_mm(struct mm_struct * mm) | 74 | static inline void __tlb_flush_mm(struct mm_struct * mm) |
75 | { | 75 | { |
76 | if (unlikely(cpus_empty(mm->cpu_vm_mask))) | 76 | if (unlikely(cpumask_empty(mm_cpumask(mm)))) |
77 | return; | 77 | return; |
78 | /* | 78 | /* |
79 | * If the machine has IDTE we prefer to do a per mm flush | 79 | * If the machine has IDTE we prefer to do a per mm flush |
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index c979c3b56ab0..5e0ad618dc45 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h | |||
@@ -5,7 +5,6 @@ | |||
5 | 5 | ||
6 | #define mc_capable() (1) | 6 | #define mc_capable() (1) |
7 | 7 | ||
8 | cpumask_t cpu_coregroup_map(unsigned int cpu); | ||
9 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu); | 8 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu); |
10 | 9 | ||
11 | extern cpumask_t cpu_core_map[NR_CPUS]; | 10 | extern cpumask_t cpu_core_map[NR_CPUS]; |
diff --git a/arch/s390/include/asm/vtoc.h b/arch/s390/include/asm/vtoc.h index 3a5267d90d29..8406a2b3157a 100644 --- a/arch/s390/include/asm/vtoc.h +++ b/arch/s390/include/asm/vtoc.h | |||
@@ -39,7 +39,7 @@ struct vtoc_labeldate | |||
39 | __u16 day; | 39 | __u16 day; |
40 | } __attribute__ ((packed)); | 40 | } __attribute__ ((packed)); |
41 | 41 | ||
42 | struct vtoc_volume_label | 42 | struct vtoc_volume_label_cdl |
43 | { | 43 | { |
44 | char volkey[4]; /* volume key = volume label */ | 44 | char volkey[4]; /* volume key = volume label */ |
45 | char vollbl[4]; /* volume label */ | 45 | char vollbl[4]; /* volume label */ |
@@ -56,6 +56,14 @@ struct vtoc_volume_label | |||
56 | char res3[29]; /* reserved */ | 56 | char res3[29]; /* reserved */ |
57 | } __attribute__ ((packed)); | 57 | } __attribute__ ((packed)); |
58 | 58 | ||
59 | struct vtoc_volume_label_ldl { | ||
60 | char vollbl[4]; /* volume label */ | ||
61 | char volid[6]; /* volume identifier */ | ||
62 | char res3[69]; /* reserved */ | ||
63 | char ldl_version; /* version number, valid for ldl format */ | ||
64 | __u64 formatted_blocks; /* valid when ldl_version >= f2 */ | ||
65 | } __attribute__ ((packed)); | ||
66 | |||
59 | struct vtoc_extent | 67 | struct vtoc_extent |
60 | { | 68 | { |
61 | __u8 typeind; /* extent type indicator */ | 69 | __u8 typeind; /* extent type indicator */ |
@@ -140,7 +148,11 @@ struct vtoc_format4_label | |||
140 | char res2[10]; /* reserved */ | 148 | char res2[10]; /* reserved */ |
141 | __u8 DS4EFLVL; /* extended free-space management level */ | 149 | __u8 DS4EFLVL; /* extended free-space management level */ |
142 | struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */ | 150 | struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */ |
143 | char res3[9]; /* reserved */ | 151 | char res3; /* reserved */ |
152 | __u32 DS4DCYL; /* number of logical cyls */ | ||
153 | char res4[2]; /* reserved */ | ||
154 | __u8 DS4DEVF2; /* device flags */ | ||
155 | char res5; /* reserved */ | ||
144 | } __attribute__ ((packed)); | 156 | } __attribute__ ((packed)); |
145 | 157 | ||
146 | struct vtoc_ds5ext | 158 | struct vtoc_ds5ext |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 3edc6c6f258b..228e3105ded7 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -17,10 +17,12 @@ CFLAGS_smp.o := -Wno-nonnull | |||
17 | # | 17 | # |
18 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | 18 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' |
19 | 19 | ||
20 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | ||
21 | |||
20 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ | 22 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ |
21 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 23 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ |
22 | s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ | 24 | s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ |
23 | vdso.o vtime.o | 25 | vdso.o vtime.o sysinfo.o nmi.o |
24 | 26 | ||
25 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) | 27 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) |
26 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) | 28 | 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 index dfb41f946e23..000000000000 --- a/arch/s390/kernel/bitmap.S +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | * arch/s390/kernel/bitmap.S | ||
3 | * Bitmaps for set_bit, clear_bit, test_and_set_bit, ... | ||
4 | * See include/asm-s390/{bitops.h|posix_types.h} for details | ||
5 | * | ||
6 | * S390 version | ||
7 | * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
8 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | ||
9 | */ | ||
10 | |||
11 | .globl _oi_bitmap | ||
12 | _oi_bitmap: | ||
13 | .byte 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 | ||
14 | |||
15 | .globl _ni_bitmap | ||
16 | _ni_bitmap: | ||
17 | .byte 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F | ||
18 | |||
19 | .globl _zb_findmap | ||
20 | _zb_findmap: | ||
21 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
22 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 | ||
23 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
24 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6 | ||
25 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
26 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 | ||
27 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
28 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7 | ||
29 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
30 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 | ||
31 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
32 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6 | ||
33 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
34 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5 | ||
35 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 | ||
36 | .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 | ||
37 | |||
38 | .globl _sb_findmap | ||
39 | _sb_findmap: | ||
40 | .byte 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
41 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
42 | .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
43 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
44 | .byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
45 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
46 | .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
47 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
48 | .byte 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
49 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
50 | .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
51 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
52 | .byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
53 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
54 | .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
55 | .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 | ||
56 | |||
diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c new file mode 100644 index 000000000000..3ae4757b006a --- /dev/null +++ b/arch/s390/kernel/bitmap.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * Bitmaps for set_bit, clear_bit, test_and_set_bit, ... | ||
3 | * See include/asm/{bitops.h|posix_types.h} for details | ||
4 | * | ||
5 | * Copyright IBM Corp. 1999,2009 | ||
6 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, | ||
7 | */ | ||
8 | |||
9 | #include <linux/bitops.h> | ||
10 | #include <linux/module.h> | ||
11 | |||
12 | const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; | ||
13 | EXPORT_SYMBOL(_oi_bitmap); | ||
14 | |||
15 | const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; | ||
16 | EXPORT_SYMBOL(_ni_bitmap); | ||
17 | |||
18 | const char _zb_findmap[] = { | ||
19 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
20 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
21 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
22 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, | ||
23 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
24 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
25 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
26 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7, | ||
27 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
28 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
29 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
30 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, | ||
31 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
32 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, | ||
33 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, | ||
34 | 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 }; | ||
35 | EXPORT_SYMBOL(_zb_findmap); | ||
36 | |||
37 | const char _sb_findmap[] = { | ||
38 | 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
39 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
40 | 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
41 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
42 | 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
43 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
44 | 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
45 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
46 | 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
47 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
48 | 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
49 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
50 | 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
51 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
52 | 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, | ||
53 | 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 }; | ||
54 | EXPORT_SYMBOL(_sb_findmap); | ||
diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h index a2be3a978d5c..123dd660d7fb 100644 --- a/arch/s390/kernel/compat_ptrace.h +++ b/arch/s390/kernel/compat_ptrace.h | |||
@@ -1,10 +1,11 @@ | |||
1 | #ifndef _PTRACE32_H | 1 | #ifndef _PTRACE32_H |
2 | #define _PTRACE32_H | 2 | #define _PTRACE32_H |
3 | 3 | ||
4 | #include <asm/ptrace.h> /* needed for NUM_CR_WORDS */ | ||
4 | #include "compat_linux.h" /* needed for psw_compat_t */ | 5 | #include "compat_linux.h" /* needed for psw_compat_t */ |
5 | 6 | ||
6 | typedef struct { | 7 | typedef struct { |
7 | __u32 cr[3]; | 8 | __u32 cr[NUM_CR_WORDS]; |
8 | } per_cr_words32; | 9 | } per_cr_words32; |
9 | 10 | ||
10 | typedef struct { | 11 | typedef struct { |
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index ba03fc0a3a56..be8bceaf37d9 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
@@ -603,7 +603,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length, | |||
603 | static int | 603 | static int |
604 | debug_open(struct inode *inode, struct file *file) | 604 | debug_open(struct inode *inode, struct file *file) |
605 | { | 605 | { |
606 | int i = 0, rc = 0; | 606 | int i, rc = 0; |
607 | file_private_info_t *p_info; | 607 | file_private_info_t *p_info; |
608 | debug_info_t *debug_info, *debug_info_snapshot; | 608 | debug_info_t *debug_info, *debug_info_snapshot; |
609 | 609 | ||
@@ -642,8 +642,7 @@ found: | |||
642 | p_info = kmalloc(sizeof(file_private_info_t), | 642 | p_info = kmalloc(sizeof(file_private_info_t), |
643 | GFP_KERNEL); | 643 | GFP_KERNEL); |
644 | if(!p_info){ | 644 | if(!p_info){ |
645 | if(debug_info_snapshot) | 645 | debug_info_free(debug_info_snapshot); |
646 | debug_info_free(debug_info_snapshot); | ||
647 | rc = -ENOMEM; | 646 | rc = -ENOMEM; |
648 | goto out; | 647 | goto out; |
649 | } | 648 | } |
@@ -698,8 +697,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area, | |||
698 | if ((uid != 0) || (gid != 0)) | 697 | if ((uid != 0) || (gid != 0)) |
699 | pr_warning("Root becomes the owner of all s390dbf files " | 698 | pr_warning("Root becomes the owner of all s390dbf files " |
700 | "in sysfs\n"); | 699 | "in sysfs\n"); |
701 | if (!initialized) | 700 | BUG_ON(!initialized); |
702 | BUG(); | ||
703 | mutex_lock(&debug_mutex); | 701 | mutex_lock(&debug_mutex); |
704 | 702 | ||
705 | /* create new debug_info */ | 703 | /* create new debug_info */ |
@@ -1156,7 +1154,6 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view) | |||
1156 | else { | 1154 | else { |
1157 | debugfs_remove(id->debugfs_entries[i]); | 1155 | debugfs_remove(id->debugfs_entries[i]); |
1158 | id->views[i] = NULL; | 1156 | id->views[i] = NULL; |
1159 | rc = 0; | ||
1160 | } | 1157 | } |
1161 | spin_unlock_irqrestore(&id->lock, flags); | 1158 | spin_unlock_irqrestore(&id->lock, flags); |
1162 | out: | 1159 | out: |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 2a2ca268b1dd..4d221c81c849 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * Heiko Carstens <heiko.carstens@de.ibm.com> | 6 | * Heiko Carstens <heiko.carstens@de.ibm.com> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/compiler.h> | ||
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
10 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
11 | #include <linux/string.h> | 12 | #include <linux/string.h> |
@@ -20,6 +21,7 @@ | |||
20 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
21 | #include <asm/sections.h> | 22 | #include <asm/sections.h> |
22 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
24 | #include <asm/sysinfo.h> | ||
23 | #include <asm/cpcmd.h> | 25 | #include <asm/cpcmd.h> |
24 | #include <asm/sclp.h> | 26 | #include <asm/sclp.h> |
25 | #include "entry.h" | 27 | #include "entry.h" |
@@ -173,19 +175,21 @@ static noinline __init void init_kernel_storage_key(void) | |||
173 | page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); | 175 | page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); |
174 | } | 176 | } |
175 | 177 | ||
178 | static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); | ||
179 | |||
176 | static noinline __init void detect_machine_type(void) | 180 | static noinline __init void detect_machine_type(void) |
177 | { | 181 | { |
178 | struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; | 182 | /* No VM information? Looks like LPAR */ |
179 | 183 | if (stsi(&vmms, 3, 2, 2) == -ENOSYS) | |
180 | get_cpu_id(&S390_lowcore.cpu_data.cpu_id); | 184 | return; |
181 | 185 | if (!vmms.count) | |
182 | /* Running under z/VM ? */ | 186 | return; |
183 | if (cpuinfo->cpu_id.version == 0xff) | ||
184 | machine_flags |= MACHINE_FLAG_VM; | ||
185 | 187 | ||
186 | /* Running under KVM ? */ | 188 | /* Running under KVM? If not we assume z/VM */ |
187 | if (cpuinfo->cpu_id.version == 0xfe) | 189 | if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3)) |
188 | machine_flags |= MACHINE_FLAG_KVM; | 190 | machine_flags |= MACHINE_FLAG_KVM; |
191 | else | ||
192 | machine_flags |= MACHINE_FLAG_VM; | ||
189 | } | 193 | } |
190 | 194 | ||
191 | static __init void early_pgm_check_handler(void) | 195 | static __init void early_pgm_check_handler(void) |
@@ -348,7 +352,6 @@ static void __init setup_boot_command_line(void) | |||
348 | 352 | ||
349 | /* copy arch command line */ | 353 | /* copy arch command line */ |
350 | strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); | 354 | strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); |
351 | boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0; | ||
352 | 355 | ||
353 | /* append IPL PARM data to the boot command line */ | 356 | /* append IPL PARM data to the boot command line */ |
354 | if (MACHINE_IS_VM) { | 357 | if (MACHINE_IS_VM) { |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index ec7e35f6055b..1046c2c9f8d1 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -469,6 +469,8 @@ start: | |||
469 | .org 0x10000 | 469 | .org 0x10000 |
470 | startup:basr %r13,0 # get base | 470 | startup:basr %r13,0 # get base |
471 | .LPG0: | 471 | .LPG0: |
472 | xc 0x200(256),0x200 # partially clear lowcore | ||
473 | xc 0x300(256),0x300 | ||
472 | 474 | ||
473 | #ifndef CONFIG_MARCH_G5 | 475 | #ifndef CONFIG_MARCH_G5 |
474 | # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} | 476 | # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} |
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index db476d114caa..2ced846065b7 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S | |||
@@ -20,7 +20,6 @@ startup_continue: | |||
20 | lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers | 20 | lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers |
21 | l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area | 21 | l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area |
22 | # move IPL device to lowcore | 22 | # move IPL device to lowcore |
23 | mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) | ||
24 | # | 23 | # |
25 | # Setup stack | 24 | # Setup stack |
26 | # | 25 | # |
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index f9f70aa15244..65667b2e65ce 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S | |||
@@ -86,7 +86,6 @@ startup_continue: | |||
86 | lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers | 86 | lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers |
87 | lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area | 87 | lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area |
88 | # move IPL device to lowcore | 88 | # move IPL device to lowcore |
89 | mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) | ||
90 | lghi %r0,__LC_PASTE | 89 | lghi %r0,__LC_PASTE |
91 | stg %r0,__LC_VDSO_PER_CPU | 90 | stg %r0,__LC_VDSO_PER_CPU |
92 | # | 91 | # |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 2dcf590faba6..6f3711a0eaaa 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <asm/ebcdic.h> | 23 | #include <asm/ebcdic.h> |
24 | #include <asm/reset.h> | 24 | #include <asm/reset.h> |
25 | #include <asm/sclp.h> | 25 | #include <asm/sclp.h> |
26 | #include <asm/setup.h> | 26 | #include <asm/checksum.h> |
27 | 27 | ||
28 | #define IPL_PARM_BLOCK_VERSION 0 | 28 | #define IPL_PARM_BLOCK_VERSION 0 |
29 | 29 | ||
@@ -56,13 +56,14 @@ struct shutdown_trigger { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Five shutdown action types are supported: | 59 | * The following shutdown action types are supported: |
60 | */ | 60 | */ |
61 | #define SHUTDOWN_ACTION_IPL_STR "ipl" | 61 | #define SHUTDOWN_ACTION_IPL_STR "ipl" |
62 | #define SHUTDOWN_ACTION_REIPL_STR "reipl" | 62 | #define SHUTDOWN_ACTION_REIPL_STR "reipl" |
63 | #define SHUTDOWN_ACTION_DUMP_STR "dump" | 63 | #define SHUTDOWN_ACTION_DUMP_STR "dump" |
64 | #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" | 64 | #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" |
65 | #define SHUTDOWN_ACTION_STOP_STR "stop" | 65 | #define SHUTDOWN_ACTION_STOP_STR "stop" |
66 | #define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl" | ||
66 | 67 | ||
67 | struct shutdown_action { | 68 | struct shutdown_action { |
68 | char *name; | 69 | char *name; |
@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; | |||
146 | static struct ipl_parameter_block *reipl_block_fcp; | 147 | static struct ipl_parameter_block *reipl_block_fcp; |
147 | static struct ipl_parameter_block *reipl_block_ccw; | 148 | static struct ipl_parameter_block *reipl_block_ccw; |
148 | static struct ipl_parameter_block *reipl_block_nss; | 149 | static struct ipl_parameter_block *reipl_block_nss; |
150 | static struct ipl_parameter_block *reipl_block_actual; | ||
149 | 151 | ||
150 | static int dump_capabilities = DUMP_TYPE_NONE; | 152 | static int dump_capabilities = DUMP_TYPE_NONE; |
151 | static enum dump_type dump_type = DUMP_TYPE_NONE; | 153 | static enum dump_type dump_type = DUMP_TYPE_NONE; |
@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type) | |||
835 | reipl_method = REIPL_METHOD_CCW_VM; | 837 | reipl_method = REIPL_METHOD_CCW_VM; |
836 | else | 838 | else |
837 | reipl_method = REIPL_METHOD_CCW_CIO; | 839 | reipl_method = REIPL_METHOD_CCW_CIO; |
840 | reipl_block_actual = reipl_block_ccw; | ||
838 | break; | 841 | break; |
839 | case IPL_TYPE_FCP: | 842 | case IPL_TYPE_FCP: |
840 | if (diag308_set_works) | 843 | if (diag308_set_works) |
@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type) | |||
843 | reipl_method = REIPL_METHOD_FCP_RO_VM; | 846 | reipl_method = REIPL_METHOD_FCP_RO_VM; |
844 | else | 847 | else |
845 | reipl_method = REIPL_METHOD_FCP_RO_DIAG; | 848 | reipl_method = REIPL_METHOD_FCP_RO_DIAG; |
849 | reipl_block_actual = reipl_block_fcp; | ||
846 | break; | 850 | break; |
847 | case IPL_TYPE_FCP_DUMP: | 851 | case IPL_TYPE_FCP_DUMP: |
848 | reipl_method = REIPL_METHOD_FCP_DUMP; | 852 | reipl_method = REIPL_METHOD_FCP_DUMP; |
@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type) | |||
852 | reipl_method = REIPL_METHOD_NSS_DIAG; | 856 | reipl_method = REIPL_METHOD_NSS_DIAG; |
853 | else | 857 | else |
854 | reipl_method = REIPL_METHOD_NSS; | 858 | reipl_method = REIPL_METHOD_NSS; |
859 | reipl_block_actual = reipl_block_nss; | ||
855 | break; | 860 | break; |
856 | case IPL_TYPE_UNKNOWN: | 861 | case IPL_TYPE_UNKNOWN: |
857 | reipl_method = REIPL_METHOD_DEFAULT; | 862 | reipl_method = REIPL_METHOD_DEFAULT; |
@@ -960,7 +965,6 @@ static void reipl_run(struct shutdown_trigger *trigger) | |||
960 | diag308(DIAG308_IPL, NULL); | 965 | diag308(DIAG308_IPL, NULL); |
961 | break; | 966 | break; |
962 | case REIPL_METHOD_FCP_DUMP: | 967 | case REIPL_METHOD_FCP_DUMP: |
963 | default: | ||
964 | break; | 968 | break; |
965 | } | 969 | } |
966 | disabled_wait((unsigned long) __builtin_return_address(0)); | 970 | disabled_wait((unsigned long) __builtin_return_address(0)); |
@@ -1069,10 +1073,12 @@ static int __init reipl_fcp_init(void) | |||
1069 | { | 1073 | { |
1070 | int rc; | 1074 | int rc; |
1071 | 1075 | ||
1072 | if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP)) | 1076 | if (!diag308_set_works) { |
1073 | return 0; | 1077 | if (ipl_info.type == IPL_TYPE_FCP) |
1074 | if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP)) | 1078 | make_attrs_ro(reipl_fcp_attrs); |
1075 | make_attrs_ro(reipl_fcp_attrs); | 1079 | else |
1080 | return 0; | ||
1081 | } | ||
1076 | 1082 | ||
1077 | reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); | 1083 | reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); |
1078 | if (!reipl_block_fcp) | 1084 | if (!reipl_block_fcp) |
@@ -1253,7 +1259,6 @@ static void dump_run(struct shutdown_trigger *trigger) | |||
1253 | diag308(DIAG308_DUMP, NULL); | 1259 | diag308(DIAG308_DUMP, NULL); |
1254 | break; | 1260 | break; |
1255 | case DUMP_METHOD_NONE: | 1261 | case DUMP_METHOD_NONE: |
1256 | default: | ||
1257 | return; | 1262 | return; |
1258 | } | 1263 | } |
1259 | printk(KERN_EMERG "Dump failed!\n"); | 1264 | printk(KERN_EMERG "Dump failed!\n"); |
@@ -1332,6 +1337,49 @@ static struct shutdown_action __refdata dump_action = { | |||
1332 | .init = dump_init, | 1337 | .init = dump_init, |
1333 | }; | 1338 | }; |
1334 | 1339 | ||
1340 | static void dump_reipl_run(struct shutdown_trigger *trigger) | ||
1341 | { | ||
1342 | preempt_disable(); | ||
1343 | /* | ||
1344 | * Bypass dynamic address translation (DAT) when storing IPL parameter | ||
1345 | * information block address and checksum into the prefix area | ||
1346 | * (corresponding to absolute addresses 0-8191). | ||
1347 | * When enhanced DAT applies and the STE format control in one, | ||
1348 | * the absolute address is formed without prefixing. In this case a | ||
1349 | * normal store (stg/st) into the prefix area would no more match to | ||
1350 | * absolute addresses 0-8191. | ||
1351 | */ | ||
1352 | #ifdef CONFIG_64BIT | ||
1353 | asm volatile("sturg %0,%1" | ||
1354 | :: "a" ((unsigned long) reipl_block_actual), | ||
1355 | "a" (&lowcore_ptr[smp_processor_id()]->ipib)); | ||
1356 | #else | ||
1357 | asm volatile("stura %0,%1" | ||
1358 | :: "a" ((unsigned long) reipl_block_actual), | ||
1359 | "a" (&lowcore_ptr[smp_processor_id()]->ipib)); | ||
1360 | #endif | ||
1361 | asm volatile("stura %0,%1" | ||
1362 | :: "a" (csum_partial(reipl_block_actual, | ||
1363 | reipl_block_actual->hdr.len, 0)), | ||
1364 | "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum)); | ||
1365 | preempt_enable(); | ||
1366 | dump_run(trigger); | ||
1367 | } | ||
1368 | |||
1369 | static int __init dump_reipl_init(void) | ||
1370 | { | ||
1371 | if (!diag308_set_works) | ||
1372 | return -EOPNOTSUPP; | ||
1373 | else | ||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | static struct shutdown_action __refdata dump_reipl_action = { | ||
1378 | .name = SHUTDOWN_ACTION_DUMP_REIPL_STR, | ||
1379 | .fn = dump_reipl_run, | ||
1380 | .init = dump_reipl_init, | ||
1381 | }; | ||
1382 | |||
1335 | /* | 1383 | /* |
1336 | * vmcmd shutdown action: Trigger vm command on shutdown. | 1384 | * vmcmd shutdown action: Trigger vm command on shutdown. |
1337 | */ | 1385 | */ |
@@ -1421,7 +1469,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, | |||
1421 | /* action list */ | 1469 | /* action list */ |
1422 | 1470 | ||
1423 | static struct shutdown_action *shutdown_actions_list[] = { | 1471 | static struct shutdown_action *shutdown_actions_list[] = { |
1424 | &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action}; | 1472 | &ipl_action, &reipl_action, &dump_reipl_action, &dump_action, |
1473 | &vmcmd_action, &stop_action}; | ||
1425 | #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) | 1474 | #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) |
1426 | 1475 | ||
1427 | /* | 1476 | /* |
@@ -1434,11 +1483,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, | |||
1434 | size_t len) | 1483 | size_t len) |
1435 | { | 1484 | { |
1436 | int i; | 1485 | int i; |
1486 | |||
1437 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | 1487 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { |
1438 | if (!shutdown_actions_list[i]) | 1488 | if (!shutdown_actions_list[i]) |
1439 | continue; | 1489 | continue; |
1440 | if (strncmp(buf, shutdown_actions_list[i]->name, | 1490 | if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { |
1441 | strlen(shutdown_actions_list[i]->name)) == 0) { | ||
1442 | trigger->action = shutdown_actions_list[i]; | 1491 | trigger->action = shutdown_actions_list[i]; |
1443 | return len; | 1492 | return len; |
1444 | } | 1493 | } |
@@ -1672,7 +1721,7 @@ static int on_panic_notify(struct notifier_block *self, | |||
1672 | 1721 | ||
1673 | static struct notifier_block on_panic_nb = { | 1722 | static struct notifier_block on_panic_nb = { |
1674 | .notifier_call = on_panic_notify, | 1723 | .notifier_call = on_panic_notify, |
1675 | .priority = 0, | 1724 | .priority = INT_MIN, |
1676 | }; | 1725 | }; |
1677 | 1726 | ||
1678 | void __init setup_ipl(void) | 1727 | void __init setup_ipl(void) |
@@ -1696,7 +1745,6 @@ void __init setup_ipl(void) | |||
1696 | sizeof(ipl_info.data.nss.name)); | 1745 | sizeof(ipl_info.data.nss.name)); |
1697 | break; | 1746 | break; |
1698 | case IPL_TYPE_UNKNOWN: | 1747 | case IPL_TYPE_UNKNOWN: |
1699 | default: | ||
1700 | /* We have no info to copy */ | 1748 | /* We have no info to copy */ |
1701 | break; | 1749 | break; |
1702 | } | 1750 | } |
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 59b4e796680a..eed4a00cb676 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c | |||
@@ -310,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, | |||
310 | info->plt_initialized = 1; | 310 | info->plt_initialized = 1; |
311 | } | 311 | } |
312 | if (r_type == R_390_PLTOFF16 || | 312 | if (r_type == R_390_PLTOFF16 || |
313 | r_type == R_390_PLTOFF32 | 313 | r_type == R_390_PLTOFF32 || |
314 | || r_type == R_390_PLTOFF64 | 314 | r_type == R_390_PLTOFF64) |
315 | ) | ||
316 | val = me->arch.plt_offset - me->arch.got_offset + | 315 | val = me->arch.plt_offset - me->arch.got_offset + |
317 | info->plt_offset + rela->r_addend; | 316 | info->plt_offset + rela->r_addend; |
318 | else | 317 | else { |
319 | val = (Elf_Addr) me->module_core + | 318 | if (!((r_type == R_390_PLT16DBL && |
320 | me->arch.plt_offset + info->plt_offset + | 319 | val - loc + 0xffffUL < 0x1ffffeUL) || |
321 | rela->r_addend - loc; | 320 | (r_type == R_390_PLT32DBL && |
321 | val - loc + 0xffffffffULL < 0x1fffffffeULL))) | ||
322 | val = (Elf_Addr) me->module_core + | ||
323 | me->arch.plt_offset + | ||
324 | info->plt_offset; | ||
325 | val += rela->r_addend - loc; | ||
326 | } | ||
322 | if (r_type == R_390_PLT16DBL) | 327 | if (r_type == R_390_PLT16DBL) |
323 | *(unsigned short *) loc = val >> 1; | 328 | *(unsigned short *) loc = val >> 1; |
324 | else if (r_type == R_390_PLTOFF16) | 329 | else if (r_type == R_390_PLTOFF16) |
diff --git a/drivers/s390/s390mach.c b/arch/s390/kernel/nmi.c index 92b0417f8e12..4bfdc421d7e9 100644 --- a/drivers/s390/s390mach.c +++ b/arch/s390/kernel/nmi.c | |||
@@ -1,137 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/s390mach.c | 2 | * Machine check handler |
3 | * S/390 machine check handler | ||
4 | * | 3 | * |
5 | * Copyright IBM Corp. 2000,2008 | 4 | * Copyright IBM Corp. 2000,2009 |
6 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 5 | * Author(s): Ingo Adlung <adlung@de.ibm.com>, |
7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, |
8 | * Cornelia Huck <cornelia.huck@de.ibm.com> | 7 | * Cornelia Huck <cornelia.huck@de.ibm.com>, |
8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, | ||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/sched.h> | ||
13 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
14 | #include <linux/workqueue.h> | ||
15 | #include <linux/time.h> | 13 | #include <linux/time.h> |
16 | #include <linux/device.h> | 14 | #include <linux/module.h> |
17 | #include <linux/kthread.h> | ||
18 | #include <asm/etr.h> | ||
19 | #include <asm/lowcore.h> | 15 | #include <asm/lowcore.h> |
20 | #include <asm/cio.h> | 16 | #include <asm/smp.h> |
17 | #include <asm/etr.h> | ||
21 | #include <asm/cpu.h> | 18 | #include <asm/cpu.h> |
22 | #include "s390mach.h" | 19 | #include <asm/nmi.h> |
23 | 20 | #include <asm/crw.h> | |
24 | static struct semaphore m_sem; | ||
25 | |||
26 | static NORET_TYPE void | ||
27 | s390_handle_damage(char *msg) | ||
28 | { | ||
29 | #ifdef CONFIG_SMP | ||
30 | smp_send_stop(); | ||
31 | #endif | ||
32 | disabled_wait((unsigned long) __builtin_return_address(0)); | ||
33 | for(;;); | ||
34 | } | ||
35 | |||
36 | static crw_handler_t crw_handlers[NR_RSCS]; | ||
37 | |||
38 | /** | ||
39 | * s390_register_crw_handler() - register a channel report word handler | ||
40 | * @rsc: reporting source code to handle | ||
41 | * @handler: handler to be registered | ||
42 | * | ||
43 | * Returns %0 on success and a negative error value otherwise. | ||
44 | */ | ||
45 | int s390_register_crw_handler(int rsc, crw_handler_t handler) | ||
46 | { | ||
47 | if ((rsc < 0) || (rsc >= NR_RSCS)) | ||
48 | return -EINVAL; | ||
49 | if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) | ||
50 | return 0; | ||
51 | return -EBUSY; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * s390_unregister_crw_handler() - unregister a channel report word handler | ||
56 | * @rsc: reporting source code to handle | ||
57 | */ | ||
58 | void s390_unregister_crw_handler(int rsc) | ||
59 | { | ||
60 | if ((rsc < 0) || (rsc >= NR_RSCS)) | ||
61 | return; | ||
62 | xchg(&crw_handlers[rsc], NULL); | ||
63 | synchronize_sched(); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Retrieve CRWs and call function to handle event. | ||
68 | */ | ||
69 | static int s390_collect_crw_info(void *param) | ||
70 | { | ||
71 | struct crw crw[2]; | ||
72 | int ccode; | ||
73 | struct semaphore *sem; | ||
74 | unsigned int chain; | ||
75 | int ignore; | ||
76 | |||
77 | sem = (struct semaphore *)param; | ||
78 | repeat: | ||
79 | ignore = down_interruptible(sem); | ||
80 | chain = 0; | ||
81 | while (1) { | ||
82 | if (unlikely(chain > 1)) { | ||
83 | struct crw tmp_crw; | ||
84 | |||
85 | printk(KERN_WARNING"%s: Code does not support more " | ||
86 | "than two chained crws; please report to " | ||
87 | "linux390@de.ibm.com!\n", __func__); | ||
88 | ccode = stcrw(&tmp_crw); | ||
89 | printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " | ||
90 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
91 | __func__, tmp_crw.slct, tmp_crw.oflw, | ||
92 | tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, | ||
93 | tmp_crw.erc, tmp_crw.rsid); | ||
94 | printk(KERN_WARNING"%s: This was crw number %x in the " | ||
95 | "chain\n", __func__, chain); | ||
96 | if (ccode != 0) | ||
97 | break; | ||
98 | chain = tmp_crw.chn ? chain + 1 : 0; | ||
99 | continue; | ||
100 | } | ||
101 | ccode = stcrw(&crw[chain]); | ||
102 | if (ccode != 0) | ||
103 | break; | ||
104 | printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " | ||
105 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
106 | crw[chain].slct, crw[chain].oflw, crw[chain].chn, | ||
107 | crw[chain].rsc, crw[chain].anc, crw[chain].erc, | ||
108 | crw[chain].rsid); | ||
109 | /* Check for overflows. */ | ||
110 | if (crw[chain].oflw) { | ||
111 | int i; | ||
112 | |||
113 | pr_debug("%s: crw overflow detected!\n", __func__); | ||
114 | for (i = 0; i < NR_RSCS; i++) { | ||
115 | if (crw_handlers[i]) | ||
116 | crw_handlers[i](NULL, NULL, 1); | ||
117 | } | ||
118 | chain = 0; | ||
119 | continue; | ||
120 | } | ||
121 | if (crw[0].chn && !chain) { | ||
122 | chain++; | ||
123 | continue; | ||
124 | } | ||
125 | if (crw_handlers[crw[chain].rsc]) | ||
126 | crw_handlers[crw[chain].rsc](&crw[0], | ||
127 | chain ? &crw[1] : NULL, | ||
128 | 0); | ||
129 | /* chain is always 0 or 1 here. */ | ||
130 | chain = crw[chain].chn ? chain + 1 : 0; | ||
131 | } | ||
132 | goto repeat; | ||
133 | return 0; | ||
134 | } | ||
135 | 21 | ||
136 | struct mcck_struct { | 22 | struct mcck_struct { |
137 | int kill_task; | 23 | int kill_task; |
@@ -142,12 +28,18 @@ struct mcck_struct { | |||
142 | 28 | ||
143 | static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); | 29 | static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); |
144 | 30 | ||
31 | static NORET_TYPE void s390_handle_damage(char *msg) | ||
32 | { | ||
33 | smp_send_stop(); | ||
34 | disabled_wait((unsigned long) __builtin_return_address(0)); | ||
35 | while (1); | ||
36 | } | ||
37 | |||
145 | /* | 38 | /* |
146 | * Main machine check handler function. Will be called with interrupts enabled | 39 | * Main machine check handler function. Will be called with interrupts enabled |
147 | * or disabled and machine checks enabled or disabled. | 40 | * or disabled and machine checks enabled or disabled. |
148 | */ | 41 | */ |
149 | void | 42 | void s390_handle_mcck(void) |
150 | s390_handle_mcck(void) | ||
151 | { | 43 | { |
152 | unsigned long flags; | 44 | unsigned long flags; |
153 | struct mcck_struct mcck; | 45 | struct mcck_struct mcck; |
@@ -166,29 +58,24 @@ s390_handle_mcck(void) | |||
166 | local_irq_restore(flags); | 58 | local_irq_restore(flags); |
167 | 59 | ||
168 | if (mcck.channel_report) | 60 | if (mcck.channel_report) |
169 | up(&m_sem); | 61 | crw_handle_channel_report(); |
170 | 62 | /* | |
171 | #ifdef CONFIG_MACHCHK_WARNING | 63 | * A warning may remain for a prolonged period on the bare iron. |
172 | /* | 64 | * (actually until the machine is powered off, or the problem is gone) |
173 | * The warning may remain for a prolonged period on the bare iron. | 65 | * So we just stop listening for the WARNING MCH and avoid continuously |
174 | * (actually till the machine is powered off, or until the problem is gone) | 66 | * being interrupted. One caveat is however, that we must do this per |
175 | * So we just stop listening for the WARNING MCH and prevent continuously | 67 | * processor and cannot use the smp version of ctl_clear_bit(). |
176 | * being interrupted. One caveat is however, that we must do this per | 68 | * On VM we only get one interrupt per virtally presented machinecheck. |
177 | * processor and cannot use the smp version of ctl_clear_bit(). | 69 | * Though one suffices, we may get one interrupt per (virtual) cpu. |
178 | * On VM we only get one interrupt per virtally presented machinecheck. | 70 | */ |
179 | * Though one suffices, we may get one interrupt per (virtual) processor. | ||
180 | */ | ||
181 | if (mcck.warning) { /* WARNING pending ? */ | 71 | if (mcck.warning) { /* WARNING pending ? */ |
182 | static int mchchk_wng_posted = 0; | 72 | static int mchchk_wng_posted = 0; |
183 | /* | 73 | |
184 | * Use single machine clear, as we cannot handle smp right now | 74 | /* Use single cpu clear, as we cannot handle smp here. */ |
185 | */ | ||
186 | __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ | 75 | __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ |
187 | if (xchg(&mchchk_wng_posted, 1) == 0) | 76 | if (xchg(&mchchk_wng_posted, 1) == 0) |
188 | kill_cad_pid(SIGPWR, 1); | 77 | kill_cad_pid(SIGPWR, 1); |
189 | } | 78 | } |
190 | #endif | ||
191 | |||
192 | if (mcck.kill_task) { | 79 | if (mcck.kill_task) { |
193 | local_irq_enable(); | 80 | local_irq_enable(); |
194 | printk(KERN_EMERG "mcck: Terminating task because of machine " | 81 | printk(KERN_EMERG "mcck: Terminating task because of machine " |
@@ -204,8 +91,7 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck); | |||
204 | * returns 0 if all registers could be validated | 91 | * returns 0 if all registers could be validated |
205 | * returns 1 otherwise | 92 | * returns 1 otherwise |
206 | */ | 93 | */ |
207 | static int | 94 | static int notrace s390_revalidate_registers(struct mci *mci) |
208 | s390_revalidate_registers(struct mci *mci) | ||
209 | { | 95 | { |
210 | int kill_task; | 96 | int kill_task; |
211 | u64 tmpclock; | 97 | u64 tmpclock; |
@@ -214,22 +100,21 @@ s390_revalidate_registers(struct mci *mci) | |||
214 | 100 | ||
215 | kill_task = 0; | 101 | kill_task = 0; |
216 | zero = 0; | 102 | zero = 0; |
217 | /* General purpose registers */ | 103 | |
218 | if (!mci->gr) | 104 | if (!mci->gr) { |
219 | /* | 105 | /* |
220 | * General purpose registers couldn't be restored and have | 106 | * General purpose registers couldn't be restored and have |
221 | * unknown contents. Process needs to be terminated. | 107 | * unknown contents. Process needs to be terminated. |
222 | */ | 108 | */ |
223 | kill_task = 1; | 109 | kill_task = 1; |
224 | 110 | } | |
225 | /* Revalidate floating point registers */ | 111 | if (!mci->fp) { |
226 | if (!mci->fp) | ||
227 | /* | 112 | /* |
228 | * Floating point registers can't be restored and | 113 | * Floating point registers can't be restored and |
229 | * therefore the process needs to be terminated. | 114 | * therefore the process needs to be terminated. |
230 | */ | 115 | */ |
231 | kill_task = 1; | 116 | kill_task = 1; |
232 | 117 | } | |
233 | #ifndef CONFIG_64BIT | 118 | #ifndef CONFIG_64BIT |
234 | asm volatile( | 119 | asm volatile( |
235 | " ld 0,0(%0)\n" | 120 | " ld 0,0(%0)\n" |
@@ -245,9 +130,8 @@ s390_revalidate_registers(struct mci *mci) | |||
245 | fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area; | 130 | fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area; |
246 | #else | 131 | #else |
247 | fpt_save_area = (void *) S390_lowcore.extended_save_area_addr; | 132 | fpt_save_area = (void *) S390_lowcore.extended_save_area_addr; |
248 | fpt_creg_save_area = fpt_save_area+128; | 133 | fpt_creg_save_area = fpt_save_area + 128; |
249 | #endif | 134 | #endif |
250 | /* Floating point control register */ | ||
251 | if (!mci->fc) { | 135 | if (!mci->fc) { |
252 | /* | 136 | /* |
253 | * Floating point control register can't be restored. | 137 | * Floating point control register can't be restored. |
@@ -278,26 +162,25 @@ s390_revalidate_registers(struct mci *mci) | |||
278 | " ld 15,120(%0)\n" | 162 | " ld 15,120(%0)\n" |
279 | : : "a" (fpt_save_area)); | 163 | : : "a" (fpt_save_area)); |
280 | } | 164 | } |
281 | |||
282 | /* Revalidate access registers */ | 165 | /* Revalidate access registers */ |
283 | asm volatile( | 166 | asm volatile( |
284 | " lam 0,15,0(%0)" | 167 | " lam 0,15,0(%0)" |
285 | : : "a" (&S390_lowcore.access_regs_save_area)); | 168 | : : "a" (&S390_lowcore.access_regs_save_area)); |
286 | if (!mci->ar) | 169 | if (!mci->ar) { |
287 | /* | 170 | /* |
288 | * Access registers have unknown contents. | 171 | * Access registers have unknown contents. |
289 | * Terminating task. | 172 | * Terminating task. |
290 | */ | 173 | */ |
291 | kill_task = 1; | 174 | kill_task = 1; |
292 | 175 | } | |
293 | /* Revalidate control registers */ | 176 | /* Revalidate control registers */ |
294 | if (!mci->cr) | 177 | if (!mci->cr) { |
295 | /* | 178 | /* |
296 | * Control registers have unknown contents. | 179 | * Control registers have unknown contents. |
297 | * Can't recover and therefore stopping machine. | 180 | * Can't recover and therefore stopping machine. |
298 | */ | 181 | */ |
299 | s390_handle_damage("invalid control registers."); | 182 | s390_handle_damage("invalid control registers."); |
300 | else | 183 | } else { |
301 | #ifdef CONFIG_64BIT | 184 | #ifdef CONFIG_64BIT |
302 | asm volatile( | 185 | asm volatile( |
303 | " lctlg 0,15,0(%0)" | 186 | " lctlg 0,15,0(%0)" |
@@ -307,12 +190,11 @@ s390_revalidate_registers(struct mci *mci) | |||
307 | " lctl 0,15,0(%0)" | 190 | " lctl 0,15,0(%0)" |
308 | : : "a" (&S390_lowcore.cregs_save_area)); | 191 | : : "a" (&S390_lowcore.cregs_save_area)); |
309 | #endif | 192 | #endif |
310 | 193 | } | |
311 | /* | 194 | /* |
312 | * We don't even try to revalidate the TOD register, since we simply | 195 | * We don't even try to revalidate the TOD register, since we simply |
313 | * can't write something sensible into that register. | 196 | * can't write something sensible into that register. |
314 | */ | 197 | */ |
315 | |||
316 | #ifdef CONFIG_64BIT | 198 | #ifdef CONFIG_64BIT |
317 | /* | 199 | /* |
318 | * See if we can revalidate the TOD programmable register with its | 200 | * See if we can revalidate the TOD programmable register with its |
@@ -330,7 +212,6 @@ s390_revalidate_registers(struct mci *mci) | |||
330 | : : "a" (&S390_lowcore.tod_progreg_save_area) | 212 | : : "a" (&S390_lowcore.tod_progreg_save_area) |
331 | : "0", "cc"); | 213 | : "0", "cc"); |
332 | #endif | 214 | #endif |
333 | |||
334 | /* Revalidate clock comparator register */ | 215 | /* Revalidate clock comparator register */ |
335 | asm volatile( | 216 | asm volatile( |
336 | " stck 0(%1)\n" | 217 | " stck 0(%1)\n" |
@@ -354,32 +235,35 @@ s390_revalidate_registers(struct mci *mci) | |||
354 | #define MAX_IPD_COUNT 29 | 235 | #define MAX_IPD_COUNT 29 |
355 | #define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ | 236 | #define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ |
356 | 237 | ||
238 | #define ED_STP_ISLAND 6 /* External damage STP island check */ | ||
239 | #define ED_STP_SYNC 7 /* External damage STP sync check */ | ||
240 | #define ED_ETR_SYNC 12 /* External damage ETR sync check */ | ||
241 | #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ | ||
242 | |||
357 | /* | 243 | /* |
358 | * machine check handler. | 244 | * machine check handler. |
359 | */ | 245 | */ |
360 | void | 246 | void notrace s390_do_machine_check(struct pt_regs *regs) |
361 | s390_do_machine_check(struct pt_regs *regs) | ||
362 | { | 247 | { |
248 | static int ipd_count; | ||
363 | static DEFINE_SPINLOCK(ipd_lock); | 249 | static DEFINE_SPINLOCK(ipd_lock); |
364 | static unsigned long long last_ipd; | 250 | static unsigned long long last_ipd; |
365 | static int ipd_count; | 251 | struct mcck_struct *mcck; |
366 | unsigned long long tmp; | 252 | unsigned long long tmp; |
367 | struct mci *mci; | 253 | struct mci *mci; |
368 | struct mcck_struct *mcck; | ||
369 | int umode; | 254 | int umode; |
370 | 255 | ||
371 | lockdep_off(); | 256 | lockdep_off(); |
372 | |||
373 | s390_idle_check(); | 257 | s390_idle_check(); |
374 | 258 | ||
375 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; | 259 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; |
376 | mcck = &__get_cpu_var(cpu_mcck); | 260 | mcck = &__get_cpu_var(cpu_mcck); |
377 | umode = user_mode(regs); | 261 | umode = user_mode(regs); |
378 | 262 | ||
379 | if (mci->sd) | 263 | if (mci->sd) { |
380 | /* System damage -> stopping machine */ | 264 | /* System damage -> stopping machine */ |
381 | s390_handle_damage("received system damage machine check."); | 265 | s390_handle_damage("received system damage machine check."); |
382 | 266 | } | |
383 | if (mci->pd) { | 267 | if (mci->pd) { |
384 | if (mci->b) { | 268 | if (mci->b) { |
385 | /* Processing backup -> verify if we can survive this */ | 269 | /* Processing backup -> verify if we can survive this */ |
@@ -409,24 +293,17 @@ s390_do_machine_check(struct pt_regs *regs) | |||
409 | * Nullifying exigent condition, therefore we might | 293 | * Nullifying exigent condition, therefore we might |
410 | * retry this instruction. | 294 | * retry this instruction. |
411 | */ | 295 | */ |
412 | |||
413 | spin_lock(&ipd_lock); | 296 | spin_lock(&ipd_lock); |
414 | |||
415 | tmp = get_clock(); | 297 | tmp = get_clock(); |
416 | |||
417 | if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) | 298 | if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) |
418 | ipd_count++; | 299 | ipd_count++; |
419 | else | 300 | else |
420 | ipd_count = 1; | 301 | ipd_count = 1; |
421 | |||
422 | last_ipd = tmp; | 302 | last_ipd = tmp; |
423 | |||
424 | if (ipd_count == MAX_IPD_COUNT) | 303 | if (ipd_count == MAX_IPD_COUNT) |
425 | s390_handle_damage("too many ipd retries."); | 304 | s390_handle_damage("too many ipd retries."); |
426 | |||
427 | spin_unlock(&ipd_lock); | 305 | spin_unlock(&ipd_lock); |
428 | } | 306 | } else { |
429 | else { | ||
430 | /* Processing damage -> stopping machine */ | 307 | /* Processing damage -> stopping machine */ |
431 | s390_handle_damage("received instruction processing " | 308 | s390_handle_damage("received instruction processing " |
432 | "damage machine check."); | 309 | "damage machine check."); |
@@ -441,20 +318,18 @@ s390_do_machine_check(struct pt_regs *regs) | |||
441 | mcck->kill_task = 1; | 318 | mcck->kill_task = 1; |
442 | mcck->mcck_code = *(unsigned long long *) mci; | 319 | mcck->mcck_code = *(unsigned long long *) mci; |
443 | set_thread_flag(TIF_MCCK_PENDING); | 320 | set_thread_flag(TIF_MCCK_PENDING); |
444 | } | 321 | } else { |
445 | else | ||
446 | /* | 322 | /* |
447 | * Couldn't restore all register contents while in | 323 | * Couldn't restore all register contents while in |
448 | * kernel mode -> stopping machine. | 324 | * kernel mode -> stopping machine. |
449 | */ | 325 | */ |
450 | s390_handle_damage("unable to revalidate registers."); | 326 | s390_handle_damage("unable to revalidate registers."); |
327 | } | ||
451 | } | 328 | } |
452 | |||
453 | if (mci->cd) { | 329 | if (mci->cd) { |
454 | /* Timing facility damage */ | 330 | /* Timing facility damage */ |
455 | s390_handle_damage("TOD clock damaged"); | 331 | s390_handle_damage("TOD clock damaged"); |
456 | } | 332 | } |
457 | |||
458 | if (mci->ed && mci->ec) { | 333 | if (mci->ed && mci->ec) { |
459 | /* External damage */ | 334 | /* External damage */ |
460 | if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) | 335 | if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) |
@@ -466,28 +341,23 @@ s390_do_machine_check(struct pt_regs *regs) | |||
466 | if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND)) | 341 | if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND)) |
467 | stp_island_check(); | 342 | stp_island_check(); |
468 | } | 343 | } |
469 | |||
470 | if (mci->se) | 344 | if (mci->se) |
471 | /* Storage error uncorrected */ | 345 | /* Storage error uncorrected */ |
472 | s390_handle_damage("received storage error uncorrected " | 346 | s390_handle_damage("received storage error uncorrected " |
473 | "machine check."); | 347 | "machine check."); |
474 | |||
475 | if (mci->ke) | 348 | if (mci->ke) |
476 | /* Storage key-error uncorrected */ | 349 | /* Storage key-error uncorrected */ |
477 | s390_handle_damage("received storage key-error uncorrected " | 350 | s390_handle_damage("received storage key-error uncorrected " |
478 | "machine check."); | 351 | "machine check."); |
479 | |||
480 | if (mci->ds && mci->fa) | 352 | if (mci->ds && mci->fa) |
481 | /* Storage degradation */ | 353 | /* Storage degradation */ |
482 | s390_handle_damage("received storage degradation machine " | 354 | s390_handle_damage("received storage degradation machine " |
483 | "check."); | 355 | "check."); |
484 | |||
485 | if (mci->cp) { | 356 | if (mci->cp) { |
486 | /* Channel report word pending */ | 357 | /* Channel report word pending */ |
487 | mcck->channel_report = 1; | 358 | mcck->channel_report = 1; |
488 | set_thread_flag(TIF_MCCK_PENDING); | 359 | set_thread_flag(TIF_MCCK_PENDING); |
489 | } | 360 | } |
490 | |||
491 | if (mci->w) { | 361 | if (mci->w) { |
492 | /* Warning pending */ | 362 | /* Warning pending */ |
493 | mcck->warning = 1; | 363 | mcck->warning = 1; |
@@ -496,43 +366,11 @@ s390_do_machine_check(struct pt_regs *regs) | |||
496 | lockdep_on(); | 366 | lockdep_on(); |
497 | } | 367 | } |
498 | 368 | ||
499 | /* | 369 | static int __init machine_check_init(void) |
500 | * s390_init_machine_check | ||
501 | * | ||
502 | * initialize machine check handling | ||
503 | */ | ||
504 | static int | ||
505 | machine_check_init(void) | ||
506 | { | 370 | { |
507 | init_MUTEX_LOCKED(&m_sem); | ||
508 | ctl_set_bit(14, 25); /* enable external damage MCH */ | 371 | ctl_set_bit(14, 25); /* enable external damage MCH */ |
509 | ctl_set_bit(14, 27); /* enable system recovery MCH */ | 372 | ctl_set_bit(14, 27); /* enable system recovery MCH */ |
510 | #ifdef CONFIG_MACHCHK_WARNING | ||
511 | ctl_set_bit(14, 24); /* enable warning MCH */ | 373 | ctl_set_bit(14, 24); /* enable warning MCH */ |
512 | #endif | ||
513 | return 0; | 374 | return 0; |
514 | } | 375 | } |
515 | |||
516 | /* | ||
517 | * Initialize the machine check handler really early to be able to | ||
518 | * catch all machine checks that happen during boot | ||
519 | */ | ||
520 | arch_initcall(machine_check_init); | 376 | arch_initcall(machine_check_init); |
521 | |||
522 | /* | ||
523 | * Machine checks for the channel subsystem must be enabled | ||
524 | * after the channel subsystem is initialized | ||
525 | */ | ||
526 | static int __init | ||
527 | machine_check_crw_init (void) | ||
528 | { | ||
529 | struct task_struct *task; | ||
530 | |||
531 | task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); | ||
532 | if (IS_ERR(task)) | ||
533 | return PTR_ERR(task); | ||
534 | ctl_set_bit(14, 28); /* enable channel report MCH */ | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | device_initcall (machine_check_crw_init); | ||
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5cd38a90e64d..b48e961a38f6 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -1,18 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/process.c | 2 | * This file handles the architecture dependent parts of process handling. |
3 | * | 3 | * |
4 | * S390 version | 4 | * Copyright IBM Corp. 1999,2009 |
5 | * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | 6 | * Hartmut Penner <hp@de.ibm.com>, |
7 | * Hartmut Penner (hp@de.ibm.com), | 7 | * Denis Joseph Barrow, |
8 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), | ||
9 | * | ||
10 | * Derived from "arch/i386/kernel/process.c" | ||
11 | * Copyright (C) 1995, Linus Torvalds | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This file handles the architecture-dependent parts of process handling.. | ||
16 | */ | 8 | */ |
17 | 9 | ||
18 | #include <linux/compiler.h> | 10 | #include <linux/compiler.h> |
@@ -47,6 +39,7 @@ | |||
47 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
48 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
49 | #include <asm/timer.h> | 41 | #include <asm/timer.h> |
42 | #include <asm/nmi.h> | ||
50 | #include "entry.h" | 43 | #include "entry.h" |
51 | 44 | ||
52 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); | 45 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); |
@@ -76,7 +69,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
76 | return sf->gprs[8]; | 69 | return sf->gprs[8]; |
77 | } | 70 | } |
78 | 71 | ||
79 | extern void s390_handle_mcck(void); | ||
80 | /* | 72 | /* |
81 | * The idle loop on a S390... | 73 | * The idle loop on a S390... |
82 | */ | 74 | */ |
@@ -149,6 +141,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
149 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, | 141 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, |
150 | 0, ®s, 0, NULL, NULL); | 142 | 0, ®s, 0, NULL, NULL); |
151 | } | 143 | } |
144 | EXPORT_SYMBOL(kernel_thread); | ||
152 | 145 | ||
153 | /* | 146 | /* |
154 | * Free current thread data structures etc.. | 147 | * Free current thread data structures etc.. |
@@ -168,34 +161,35 @@ void release_thread(struct task_struct *dead_task) | |||
168 | } | 161 | } |
169 | 162 | ||
170 | int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, | 163 | int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, |
171 | unsigned long unused, | 164 | unsigned long unused, |
172 | struct task_struct * p, struct pt_regs * regs) | 165 | struct task_struct *p, struct pt_regs *regs) |
173 | { | 166 | { |
174 | struct fake_frame | 167 | struct thread_info *ti; |
175 | { | 168 | struct fake_frame |
176 | struct stack_frame sf; | 169 | { |
177 | struct pt_regs childregs; | 170 | struct stack_frame sf; |
178 | } *frame; | 171 | struct pt_regs childregs; |
179 | 172 | } *frame; | |
180 | frame = container_of(task_pt_regs(p), struct fake_frame, childregs); | 173 | |
181 | p->thread.ksp = (unsigned long) frame; | 174 | frame = container_of(task_pt_regs(p), struct fake_frame, childregs); |
175 | p->thread.ksp = (unsigned long) frame; | ||
182 | /* Store access registers to kernel stack of new process. */ | 176 | /* Store access registers to kernel stack of new process. */ |
183 | frame->childregs = *regs; | 177 | frame->childregs = *regs; |
184 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ | 178 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ |
185 | frame->childregs.gprs[15] = new_stackp; | 179 | frame->childregs.gprs[15] = new_stackp; |
186 | frame->sf.back_chain = 0; | 180 | frame->sf.back_chain = 0; |
187 | 181 | ||
188 | /* new return point is ret_from_fork */ | 182 | /* new return point is ret_from_fork */ |
189 | frame->sf.gprs[8] = (unsigned long) ret_from_fork; | 183 | frame->sf.gprs[8] = (unsigned long) ret_from_fork; |
190 | 184 | ||
191 | /* fake return stack for resume(), don't go back to schedule */ | 185 | /* fake return stack for resume(), don't go back to schedule */ |
192 | frame->sf.gprs[9] = (unsigned long) frame; | 186 | frame->sf.gprs[9] = (unsigned long) frame; |
193 | 187 | ||
194 | /* Save access registers to new thread structure. */ | 188 | /* Save access registers to new thread structure. */ |
195 | save_access_regs(&p->thread.acrs[0]); | 189 | save_access_regs(&p->thread.acrs[0]); |
196 | 190 | ||
197 | #ifndef CONFIG_64BIT | 191 | #ifndef CONFIG_64BIT |
198 | /* | 192 | /* |
199 | * save fprs to current->thread.fp_regs to merge them with | 193 | * save fprs to current->thread.fp_regs to merge them with |
200 | * the emulated registers and then copy the result to the child. | 194 | * the emulated registers and then copy the result to the child. |
201 | */ | 195 | */ |
@@ -220,10 +214,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, | |||
220 | #endif /* CONFIG_64BIT */ | 214 | #endif /* CONFIG_64BIT */ |
221 | /* start new process with ar4 pointing to the correct address space */ | 215 | /* start new process with ar4 pointing to the correct address space */ |
222 | p->thread.mm_segment = get_fs(); | 216 | p->thread.mm_segment = get_fs(); |
223 | /* Don't copy debug registers */ | 217 | /* Don't copy debug registers */ |
224 | memset(&p->thread.per_info,0,sizeof(p->thread.per_info)); | 218 | memset(&p->thread.per_info, 0, sizeof(p->thread.per_info)); |
225 | 219 | /* Initialize per thread user and system timer values */ | |
226 | return 0; | 220 | ti = task_thread_info(p); |
221 | ti->user_timer = 0; | ||
222 | ti->system_timer = 0; | ||
223 | return 0; | ||
227 | } | 224 | } |
228 | 225 | ||
229 | SYSCALL_DEFINE0(fork) | 226 | SYSCALL_DEFINE0(fork) |
@@ -311,7 +308,7 @@ out: | |||
311 | int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) | 308 | int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) |
312 | { | 309 | { |
313 | #ifndef CONFIG_64BIT | 310 | #ifndef CONFIG_64BIT |
314 | /* | 311 | /* |
315 | * save fprs to current->thread.fp_regs to merge them with | 312 | * save fprs to current->thread.fp_regs to merge them with |
316 | * the emulated registers and then copy the result to the dump. | 313 | * the emulated registers and then copy the result to the dump. |
317 | */ | 314 | */ |
@@ -322,6 +319,7 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) | |||
322 | #endif /* CONFIG_64BIT */ | 319 | #endif /* CONFIG_64BIT */ |
323 | return 1; | 320 | return 1; |
324 | } | 321 | } |
322 | EXPORT_SYMBOL(dump_fpu); | ||
325 | 323 | ||
326 | unsigned long get_wchan(struct task_struct *p) | 324 | unsigned long get_wchan(struct task_struct *p) |
327 | { | 325 | { |
@@ -346,4 +344,3 @@ unsigned long get_wchan(struct task_struct *p) | |||
346 | } | 344 | } |
347 | return 0; | 345 | return 0; |
348 | } | 346 | } |
349 | |||
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 82c1872cfe80..802c8ab247f3 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c | |||
@@ -18,10 +18,11 @@ | |||
18 | #include <asm/lowcore.h> | 18 | #include <asm/lowcore.h> |
19 | #include <asm/param.h> | 19 | #include <asm/param.h> |
20 | 20 | ||
21 | void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) | 21 | void __cpuinit print_cpu_info(void) |
22 | { | 22 | { |
23 | pr_info("Processor %d started, address %d, identification %06X\n", | 23 | pr_info("Processor %d started, address %d, identification %06X\n", |
24 | cpuinfo->cpu_nr, cpuinfo->cpu_addr, cpuinfo->cpu_id.ident); | 24 | S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, |
25 | S390_lowcore.cpu_id.ident); | ||
25 | } | 26 | } |
26 | 27 | ||
27 | /* | 28 | /* |
@@ -30,48 +31,46 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) | |||
30 | 31 | ||
31 | static int show_cpuinfo(struct seq_file *m, void *v) | 32 | static int show_cpuinfo(struct seq_file *m, void *v) |
32 | { | 33 | { |
33 | static const char *hwcap_str[8] = { | 34 | static const char *hwcap_str[9] = { |
34 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", | 35 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", |
35 | "edat" | 36 | "edat", "etf3eh" |
36 | }; | 37 | }; |
37 | struct cpuinfo_S390 *cpuinfo; | 38 | struct _lowcore *lc; |
38 | unsigned long n = (unsigned long) v - 1; | 39 | unsigned long n = (unsigned long) v - 1; |
39 | int i; | 40 | int i; |
40 | 41 | ||
41 | s390_adjust_jiffies(); | 42 | s390_adjust_jiffies(); |
42 | preempt_disable(); | 43 | preempt_disable(); |
43 | if (!n) { | 44 | if (!n) { |
44 | seq_printf(m, "vendor_id : IBM/S390\n" | 45 | seq_printf(m, "vendor_id : IBM/S390\n" |
45 | "# processors : %i\n" | 46 | "# processors : %i\n" |
46 | "bogomips per cpu: %lu.%02lu\n", | 47 | "bogomips per cpu: %lu.%02lu\n", |
47 | num_online_cpus(), loops_per_jiffy/(500000/HZ), | 48 | num_online_cpus(), loops_per_jiffy/(500000/HZ), |
48 | (loops_per_jiffy/(5000/HZ))%100); | 49 | (loops_per_jiffy/(5000/HZ))%100); |
49 | seq_puts(m, "features\t: "); | 50 | seq_puts(m, "features\t: "); |
50 | for (i = 0; i < 8; i++) | 51 | for (i = 0; i < 9; i++) |
51 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) | 52 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) |
52 | seq_printf(m, "%s ", hwcap_str[i]); | 53 | seq_printf(m, "%s ", hwcap_str[i]); |
53 | seq_puts(m, "\n"); | 54 | seq_puts(m, "\n"); |
54 | } | 55 | } |
55 | 56 | ||
56 | if (cpu_online(n)) { | 57 | if (cpu_online(n)) { |
57 | #ifdef CONFIG_SMP | 58 | #ifdef CONFIG_SMP |
58 | if (smp_processor_id() == n) | 59 | lc = (smp_processor_id() == n) ? |
59 | cpuinfo = &S390_lowcore.cpu_data; | 60 | &S390_lowcore : lowcore_ptr[n]; |
60 | else | ||
61 | cpuinfo = &lowcore_ptr[n]->cpu_data; | ||
62 | #else | 61 | #else |
63 | cpuinfo = &S390_lowcore.cpu_data; | 62 | lc = &S390_lowcore; |
64 | #endif | 63 | #endif |
65 | seq_printf(m, "processor %li: " | 64 | seq_printf(m, "processor %li: " |
66 | "version = %02X, " | 65 | "version = %02X, " |
67 | "identification = %06X, " | 66 | "identification = %06X, " |
68 | "machine = %04X\n", | 67 | "machine = %04X\n", |
69 | n, cpuinfo->cpu_id.version, | 68 | n, lc->cpu_id.version, |
70 | cpuinfo->cpu_id.ident, | 69 | lc->cpu_id.ident, |
71 | cpuinfo->cpu_id.machine); | 70 | lc->cpu_id.machine); |
72 | } | 71 | } |
73 | preempt_enable(); | 72 | preempt_enable(); |
74 | return 0; | 73 | return 0; |
75 | } | 74 | } |
76 | 75 | ||
77 | static void *c_start(struct seq_file *m, loff_t *pos) | 76 | static void *c_start(struct seq_file *m, loff_t *pos) |
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S index c41930499a5f..774147824c3d 100644 --- a/arch/s390/kernel/reipl64.S +++ b/arch/s390/kernel/reipl64.S | |||
@@ -1,10 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/reipl.S | 2 | * Copyright IBM Corp 2000,2009 |
3 | * | 3 | * Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>, |
4 | * S390 version | 4 | * Denis Joseph Barrow, |
5 | * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
6 | * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com) | ||
7 | Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) | ||
8 | */ | 5 | */ |
9 | 6 | ||
10 | #include <asm/lowcore.h> | 7 | #include <asm/lowcore.h> |
@@ -30,7 +27,7 @@ do_reipl_asm: basr %r13,0 | |||
30 | mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10) | 27 | mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10) |
31 | stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) | 28 | stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) |
32 | stckc .Lclkcmp-.Lpg0(%r13) | 29 | stckc .Lclkcmp-.Lpg0(%r13) |
33 | mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13) | 30 | mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(7,%r1),.Lclkcmp-.Lpg0(%r13) |
34 | stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) | 31 | stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) |
35 | stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) | 32 | stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) |
36 | 33 | ||
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 46b90cb03707..656fcbb9bd83 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -1,49 +1,5 @@ | |||
1 | /* | ||
2 | * arch/s390/kernel/s390_ksyms.c | ||
3 | * | ||
4 | * S390 version | ||
5 | */ | ||
6 | #include <linux/highuid.h> | ||
7 | #include <linux/module.h> | 1 | #include <linux/module.h> |
8 | #include <linux/mm.h> | ||
9 | #include <linux/smp.h> | ||
10 | #include <linux/syscalls.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <asm/checksum.h> | ||
13 | #include <asm/cpcmd.h> | ||
14 | #include <asm/delay.h> | ||
15 | #include <asm/pgalloc.h> | ||
16 | #include <asm/setup.h> | ||
17 | #include <asm/ftrace.h> | 2 | #include <asm/ftrace.h> |
18 | #ifdef CONFIG_IP_MULTICAST | ||
19 | #include <net/arp.h> | ||
20 | #endif | ||
21 | |||
22 | /* | ||
23 | * memory management | ||
24 | */ | ||
25 | EXPORT_SYMBOL(_oi_bitmap); | ||
26 | EXPORT_SYMBOL(_ni_bitmap); | ||
27 | EXPORT_SYMBOL(_zb_findmap); | ||
28 | EXPORT_SYMBOL(_sb_findmap); | ||
29 | |||
30 | /* | ||
31 | * binfmt_elf loader | ||
32 | */ | ||
33 | extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs); | ||
34 | EXPORT_SYMBOL(dump_fpu); | ||
35 | EXPORT_SYMBOL(empty_zero_page); | ||
36 | |||
37 | /* | ||
38 | * misc. | ||
39 | */ | ||
40 | EXPORT_SYMBOL(machine_flags); | ||
41 | EXPORT_SYMBOL(__udelay); | ||
42 | EXPORT_SYMBOL(kernel_thread); | ||
43 | EXPORT_SYMBOL(csum_fold); | ||
44 | EXPORT_SYMBOL(console_mode); | ||
45 | EXPORT_SYMBOL(console_devno); | ||
46 | EXPORT_SYMBOL(console_irq); | ||
47 | 3 | ||
48 | #ifdef CONFIG_FUNCTION_TRACER | 4 | #ifdef CONFIG_FUNCTION_TRACER |
49 | EXPORT_SYMBOL(_mcount); | 5 | EXPORT_SYMBOL(_mcount); |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c5cfb6185eac..06201b93cbbf 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -74,9 +74,17 @@ EXPORT_SYMBOL(uaccess); | |||
74 | * Machine setup.. | 74 | * Machine setup.. |
75 | */ | 75 | */ |
76 | unsigned int console_mode = 0; | 76 | unsigned int console_mode = 0; |
77 | EXPORT_SYMBOL(console_mode); | ||
78 | |||
77 | unsigned int console_devno = -1; | 79 | unsigned int console_devno = -1; |
80 | EXPORT_SYMBOL(console_devno); | ||
81 | |||
78 | unsigned int console_irq = -1; | 82 | unsigned int console_irq = -1; |
83 | EXPORT_SYMBOL(console_irq); | ||
84 | |||
79 | unsigned long machine_flags; | 85 | unsigned long machine_flags; |
86 | EXPORT_SYMBOL(machine_flags); | ||
87 | |||
80 | unsigned long elf_hwcap = 0; | 88 | unsigned long elf_hwcap = 0; |
81 | char elf_platform[ELF_PLATFORM_SIZE]; | 89 | char elf_platform[ELF_PLATFORM_SIZE]; |
82 | 90 | ||
@@ -86,6 +94,10 @@ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ | |||
86 | int __initdata memory_end_set; | 94 | int __initdata memory_end_set; |
87 | unsigned long __initdata memory_end; | 95 | unsigned long __initdata memory_end; |
88 | 96 | ||
97 | /* An array with a pointer to the lowcore of every CPU. */ | ||
98 | struct _lowcore *lowcore_ptr[NR_CPUS]; | ||
99 | EXPORT_SYMBOL(lowcore_ptr); | ||
100 | |||
89 | /* | 101 | /* |
90 | * This is set up by the setup-routine at boot-time | 102 | * This is set up by the setup-routine at boot-time |
91 | * for S390 need to find out, what we have to setup | 103 | * for S390 need to find out, what we have to setup |
@@ -109,13 +121,10 @@ static struct resource data_resource = { | |||
109 | */ | 121 | */ |
110 | void __cpuinit cpu_init(void) | 122 | void __cpuinit cpu_init(void) |
111 | { | 123 | { |
112 | int addr = hard_smp_processor_id(); | ||
113 | |||
114 | /* | 124 | /* |
115 | * Store processor id in lowcore (used e.g. in timer_interrupt) | 125 | * Store processor id in lowcore (used e.g. in timer_interrupt) |
116 | */ | 126 | */ |
117 | get_cpu_id(&S390_lowcore.cpu_data.cpu_id); | 127 | get_cpu_id(&S390_lowcore.cpu_id); |
118 | S390_lowcore.cpu_data.cpu_addr = addr; | ||
119 | 128 | ||
120 | /* | 129 | /* |
121 | * Force FPU initialization: | 130 | * Force FPU initialization: |
@@ -125,8 +134,7 @@ void __cpuinit cpu_init(void) | |||
125 | 134 | ||
126 | atomic_inc(&init_mm.mm_count); | 135 | atomic_inc(&init_mm.mm_count); |
127 | current->active_mm = &init_mm; | 136 | current->active_mm = &init_mm; |
128 | if (current->mm) | 137 | BUG_ON(current->mm); |
129 | BUG(); | ||
130 | enter_lazy_tlb(&init_mm, current); | 138 | enter_lazy_tlb(&init_mm, current); |
131 | } | 139 | } |
132 | 140 | ||
@@ -217,7 +225,7 @@ static void __init conmode_default(void) | |||
217 | } | 225 | } |
218 | } | 226 | } |
219 | 227 | ||
220 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) | 228 | #ifdef CONFIG_ZFCPDUMP |
221 | static void __init setup_zfcpdump(unsigned int console_devno) | 229 | static void __init setup_zfcpdump(unsigned int console_devno) |
222 | { | 230 | { |
223 | static char str[41]; | 231 | static char str[41]; |
@@ -289,11 +297,7 @@ static int __init early_parse_mem(char *p) | |||
289 | early_param("mem", early_parse_mem); | 297 | early_param("mem", early_parse_mem); |
290 | 298 | ||
291 | #ifdef CONFIG_S390_SWITCH_AMODE | 299 | #ifdef CONFIG_S390_SWITCH_AMODE |
292 | #ifdef CONFIG_PGSTE | ||
293 | unsigned int switch_amode = 1; | ||
294 | #else | ||
295 | unsigned int switch_amode = 0; | 300 | unsigned int switch_amode = 0; |
296 | #endif | ||
297 | EXPORT_SYMBOL_GPL(switch_amode); | 301 | EXPORT_SYMBOL_GPL(switch_amode); |
298 | 302 | ||
299 | static int set_amode_and_uaccess(unsigned long user_amode, | 303 | static int set_amode_and_uaccess(unsigned long user_amode, |
@@ -414,7 +418,6 @@ setup_lowcore(void) | |||
414 | PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; | 418 | PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; |
415 | lc->io_new_psw.mask = psw_kernel_bits; | 419 | lc->io_new_psw.mask = psw_kernel_bits; |
416 | lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; | 420 | lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; |
417 | lc->ipl_device = S390_lowcore.ipl_device; | ||
418 | lc->clock_comparator = -1ULL; | 421 | lc->clock_comparator = -1ULL; |
419 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; | 422 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; |
420 | lc->async_stack = (unsigned long) | 423 | lc->async_stack = (unsigned long) |
@@ -434,6 +437,7 @@ setup_lowcore(void) | |||
434 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; | 437 | lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; |
435 | #endif | 438 | #endif |
436 | set_prefix((u32)(unsigned long) lc); | 439 | set_prefix((u32)(unsigned long) lc); |
440 | lowcore_ptr[0] = lc; | ||
437 | } | 441 | } |
438 | 442 | ||
439 | static void __init | 443 | static void __init |
@@ -510,7 +514,7 @@ static void __init setup_memory_end(void) | |||
510 | unsigned long max_mem; | 514 | unsigned long max_mem; |
511 | int i; | 515 | int i; |
512 | 516 | ||
513 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) | 517 | #ifdef CONFIG_ZFCPDUMP |
514 | if (ipl_info.type == IPL_TYPE_FCP_DUMP) { | 518 | if (ipl_info.type == IPL_TYPE_FCP_DUMP) { |
515 | memory_end = ZFCPDUMP_HSA_SIZE; | 519 | memory_end = ZFCPDUMP_HSA_SIZE; |
516 | memory_end_set = 1; | 520 | memory_end_set = 1; |
@@ -677,7 +681,6 @@ setup_memory(void) | |||
677 | static void __init setup_hwcaps(void) | 681 | static void __init setup_hwcaps(void) |
678 | { | 682 | { |
679 | static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; | 683 | static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; |
680 | struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; | ||
681 | unsigned long long facility_list_extended; | 684 | unsigned long long facility_list_extended; |
682 | unsigned int facility_list; | 685 | unsigned int facility_list; |
683 | int i; | 686 | int i; |
@@ -693,15 +696,22 @@ static void __init setup_hwcaps(void) | |||
693 | * Bit 17: the message-security assist is installed | 696 | * Bit 17: the message-security assist is installed |
694 | * Bit 19: the long-displacement facility is installed | 697 | * Bit 19: the long-displacement facility is installed |
695 | * Bit 21: the extended-immediate facility is installed | 698 | * Bit 21: the extended-immediate facility is installed |
699 | * Bit 22: extended-translation facility 3 is installed | ||
700 | * Bit 30: extended-translation facility 3 enhancement facility | ||
696 | * These get translated to: | 701 | * These get translated to: |
697 | * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, | 702 | * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, |
698 | * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, | 703 | * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, |
699 | * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5. | 704 | * HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and |
705 | * HWCAP_S390_ETF3EH bit 8 (22 && 30). | ||
700 | */ | 706 | */ |
701 | for (i = 0; i < 6; i++) | 707 | for (i = 0; i < 6; i++) |
702 | if (facility_list & (1UL << (31 - stfl_bits[i]))) | 708 | if (facility_list & (1UL << (31 - stfl_bits[i]))) |
703 | elf_hwcap |= 1UL << i; | 709 | elf_hwcap |= 1UL << i; |
704 | 710 | ||
711 | if ((facility_list & (1UL << (31 - 22))) | ||
712 | && (facility_list & (1UL << (31 - 30)))) | ||
713 | elf_hwcap |= 1UL << 8; | ||
714 | |||
705 | /* | 715 | /* |
706 | * Check for additional facilities with store-facility-list-extended. | 716 | * Check for additional facilities with store-facility-list-extended. |
707 | * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 | 717 | * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 |
@@ -710,20 +720,22 @@ static void __init setup_hwcaps(void) | |||
710 | * How many facility words are stored depends on the number of | 720 | * How many facility words are stored depends on the number of |
711 | * doublewords passed to the instruction. The additional facilites | 721 | * doublewords passed to the instruction. The additional facilites |
712 | * are: | 722 | * are: |
713 | * Bit 43: decimal floating point facility is installed | 723 | * Bit 42: decimal floating point facility is installed |
724 | * Bit 44: perform floating point operation facility is installed | ||
714 | * translated to: | 725 | * translated to: |
715 | * HWCAP_S390_DFP bit 6. | 726 | * HWCAP_S390_DFP bit 6 (42 && 44). |
716 | */ | 727 | */ |
717 | if ((elf_hwcap & (1UL << 2)) && | 728 | if ((elf_hwcap & (1UL << 2)) && |
718 | __stfle(&facility_list_extended, 1) > 0) { | 729 | __stfle(&facility_list_extended, 1) > 0) { |
719 | if (facility_list_extended & (1ULL << (64 - 43))) | 730 | if ((facility_list_extended & (1ULL << (63 - 42))) |
731 | && (facility_list_extended & (1ULL << (63 - 44)))) | ||
720 | elf_hwcap |= 1UL << 6; | 732 | elf_hwcap |= 1UL << 6; |
721 | } | 733 | } |
722 | 734 | ||
723 | if (MACHINE_HAS_HPAGE) | 735 | if (MACHINE_HAS_HPAGE) |
724 | elf_hwcap |= 1UL << 7; | 736 | elf_hwcap |= 1UL << 7; |
725 | 737 | ||
726 | switch (cpuinfo->cpu_id.machine) { | 738 | switch (S390_lowcore.cpu_id.machine) { |
727 | case 0x9672: | 739 | case 0x9672: |
728 | #if !defined(CONFIG_64BIT) | 740 | #if !defined(CONFIG_64BIT) |
729 | default: /* Use "g5" as default for 31 bit kernels. */ | 741 | default: /* Use "g5" as default for 31 bit kernels. */ |
@@ -816,7 +828,7 @@ setup_arch(char **cmdline_p) | |||
816 | setup_lowcore(); | 828 | setup_lowcore(); |
817 | 829 | ||
818 | cpu_init(); | 830 | cpu_init(); |
819 | __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr; | 831 | __cpu_logical_map[0] = stap(); |
820 | s390_init_cpu_topology(); | 832 | s390_init_cpu_topology(); |
821 | 833 | ||
822 | /* | 834 | /* |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 2d337cbb9329..006ed5016eb4 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/cache.h> | 33 | #include <linux/cache.h> |
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/irqflags.h> | ||
35 | #include <linux/cpu.h> | 36 | #include <linux/cpu.h> |
36 | #include <linux/timex.h> | 37 | #include <linux/timex.h> |
37 | #include <linux/bootmem.h> | 38 | #include <linux/bootmem.h> |
@@ -50,12 +51,6 @@ | |||
50 | #include <asm/vdso.h> | 51 | #include <asm/vdso.h> |
51 | #include "entry.h" | 52 | #include "entry.h" |
52 | 53 | ||
53 | /* | ||
54 | * An array with a pointer the lowcore of every CPU. | ||
55 | */ | ||
56 | struct _lowcore *lowcore_ptr[NR_CPUS]; | ||
57 | EXPORT_SYMBOL(lowcore_ptr); | ||
58 | |||
59 | static struct task_struct *current_set[NR_CPUS]; | 54 | static struct task_struct *current_set[NR_CPUS]; |
60 | 55 | ||
61 | static u8 smp_cpu_type; | 56 | static u8 smp_cpu_type; |
@@ -81,9 +76,7 @@ void smp_send_stop(void) | |||
81 | 76 | ||
82 | /* Disable all interrupts/machine checks */ | 77 | /* Disable all interrupts/machine checks */ |
83 | __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); | 78 | __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); |
84 | 79 | trace_hardirqs_off(); | |
85 | /* write magic number to zero page (absolute 0) */ | ||
86 | lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; | ||
87 | 80 | ||
88 | /* stop all processors */ | 81 | /* stop all processors */ |
89 | for_each_online_cpu(cpu) { | 82 | for_each_online_cpu(cpu) { |
@@ -233,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); | |||
233 | */ | 226 | */ |
234 | #define CPU_INIT_NO 1 | 227 | #define CPU_INIT_NO 1 |
235 | 228 | ||
236 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) | 229 | #ifdef CONFIG_ZFCPDUMP |
237 | 230 | ||
238 | /* | 231 | /* |
239 | * zfcpdump_prefix_array holds prefix registers for the following scenario: | 232 | * zfcpdump_prefix_array holds prefix registers for the following scenario: |
@@ -274,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas); | |||
274 | 267 | ||
275 | static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } | 268 | static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } |
276 | 269 | ||
277 | #endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */ | 270 | #endif /* CONFIG_ZFCPDUMP */ |
278 | 271 | ||
279 | static int cpu_stopped(int cpu) | 272 | static int cpu_stopped(int cpu) |
280 | { | 273 | { |
@@ -304,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) | |||
304 | { | 297 | { |
305 | int cpu_id, logical_cpu; | 298 | int cpu_id, logical_cpu; |
306 | 299 | ||
307 | logical_cpu = first_cpu(avail); | 300 | logical_cpu = cpumask_first(&avail); |
308 | if (logical_cpu == NR_CPUS) | 301 | if (logical_cpu >= nr_cpu_ids) |
309 | return 0; | 302 | return 0; |
310 | for (cpu_id = 0; cpu_id <= 65535; cpu_id++) { | 303 | for (cpu_id = 0; cpu_id <= 65535; cpu_id++) { |
311 | if (cpu_known(cpu_id)) | 304 | if (cpu_known(cpu_id)) |
@@ -316,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail) | |||
316 | continue; | 309 | continue; |
317 | cpu_set(logical_cpu, cpu_present_map); | 310 | cpu_set(logical_cpu, cpu_present_map); |
318 | smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; | 311 | smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; |
319 | logical_cpu = next_cpu(logical_cpu, avail); | 312 | logical_cpu = cpumask_next(logical_cpu, &avail); |
320 | if (logical_cpu == NR_CPUS) | 313 | if (logical_cpu >= nr_cpu_ids) |
321 | break; | 314 | break; |
322 | } | 315 | } |
323 | return 0; | 316 | return 0; |
@@ -329,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) | |||
329 | int cpu_id, logical_cpu, cpu; | 322 | int cpu_id, logical_cpu, cpu; |
330 | int rc; | 323 | int rc; |
331 | 324 | ||
332 | logical_cpu = first_cpu(avail); | 325 | logical_cpu = cpumask_first(&avail); |
333 | if (logical_cpu == NR_CPUS) | 326 | if (logical_cpu >= nr_cpu_ids) |
334 | return 0; | 327 | return 0; |
335 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 328 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
336 | if (!info) | 329 | if (!info) |
@@ -351,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail) | |||
351 | smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; | 344 | smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY; |
352 | else | 345 | else |
353 | smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; | 346 | smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED; |
354 | logical_cpu = next_cpu(logical_cpu, avail); | 347 | logical_cpu = cpumask_next(logical_cpu, &avail); |
355 | if (logical_cpu == NR_CPUS) | 348 | if (logical_cpu >= nr_cpu_ids) |
356 | break; | 349 | break; |
357 | } | 350 | } |
358 | out: | 351 | out: |
@@ -379,7 +372,7 @@ static void __init smp_detect_cpus(void) | |||
379 | 372 | ||
380 | c_cpus = 1; | 373 | c_cpus = 1; |
381 | s_cpus = 0; | 374 | s_cpus = 0; |
382 | boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; | 375 | boot_cpu_addr = __cpu_logical_map[0]; |
383 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 376 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
384 | if (!info) | 377 | if (!info) |
385 | panic("smp_detect_cpus failed to allocate memory\n"); | 378 | panic("smp_detect_cpus failed to allocate memory\n"); |
@@ -453,7 +446,7 @@ int __cpuinit start_secondary(void *cpuvoid) | |||
453 | /* Switch on interrupts */ | 446 | /* Switch on interrupts */ |
454 | local_irq_enable(); | 447 | local_irq_enable(); |
455 | /* Print info about this processor */ | 448 | /* Print info about this processor */ |
456 | print_cpu_info(&S390_lowcore.cpu_data); | 449 | print_cpu_info(); |
457 | /* cpu_idle will call schedule for us */ | 450 | /* cpu_idle will call schedule for us */ |
458 | cpu_idle(); | 451 | cpu_idle(); |
459 | return 0; | 452 | return 0; |
@@ -515,7 +508,6 @@ out: | |||
515 | return -ENOMEM; | 508 | return -ENOMEM; |
516 | } | 509 | } |
517 | 510 | ||
518 | #ifdef CONFIG_HOTPLUG_CPU | ||
519 | static void smp_free_lowcore(int cpu) | 511 | static void smp_free_lowcore(int cpu) |
520 | { | 512 | { |
521 | struct _lowcore *lowcore; | 513 | struct _lowcore *lowcore; |
@@ -534,7 +526,6 @@ static void smp_free_lowcore(int cpu) | |||
534 | free_pages((unsigned long) lowcore, lc_order); | 526 | free_pages((unsigned long) lowcore, lc_order); |
535 | lowcore_ptr[cpu] = NULL; | 527 | lowcore_ptr[cpu] = NULL; |
536 | } | 528 | } |
537 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
538 | 529 | ||
539 | /* Upping and downing of CPUs */ | 530 | /* Upping and downing of CPUs */ |
540 | int __cpuinit __cpu_up(unsigned int cpu) | 531 | int __cpuinit __cpu_up(unsigned int cpu) |
@@ -543,16 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
543 | struct _lowcore *cpu_lowcore; | 534 | struct _lowcore *cpu_lowcore; |
544 | struct stack_frame *sf; | 535 | struct stack_frame *sf; |
545 | sigp_ccode ccode; | 536 | sigp_ccode ccode; |
537 | u32 lowcore; | ||
546 | 538 | ||
547 | if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) | 539 | if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) |
548 | return -EIO; | 540 | return -EIO; |
549 | if (smp_alloc_lowcore(cpu)) | 541 | if (smp_alloc_lowcore(cpu)) |
550 | return -ENOMEM; | 542 | return -ENOMEM; |
551 | 543 | do { | |
552 | ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]), | 544 | ccode = signal_processor(cpu, sigp_initial_cpu_reset); |
553 | cpu, sigp_set_prefix); | 545 | if (ccode == sigp_busy) |
554 | if (ccode) | 546 | udelay(10); |
555 | return -EIO; | 547 | if (ccode == sigp_not_operational) |
548 | goto err_out; | ||
549 | } while (ccode == sigp_busy); | ||
550 | |||
551 | lowcore = (u32)(unsigned long)lowcore_ptr[cpu]; | ||
552 | while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) | ||
553 | udelay(10); | ||
556 | 554 | ||
557 | idle = current_set[cpu]; | 555 | idle = current_set[cpu]; |
558 | cpu_lowcore = lowcore_ptr[cpu]; | 556 | cpu_lowcore = lowcore_ptr[cpu]; |
@@ -571,9 +569,8 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
571 | : : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); | 569 | : : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); |
572 | cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; | 570 | cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; |
573 | cpu_lowcore->current_task = (unsigned long) idle; | 571 | cpu_lowcore->current_task = (unsigned long) idle; |
574 | cpu_lowcore->cpu_data.cpu_nr = cpu; | 572 | cpu_lowcore->cpu_nr = cpu; |
575 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; | 573 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; |
576 | cpu_lowcore->ipl_device = S390_lowcore.ipl_device; | ||
577 | eieio(); | 574 | eieio(); |
578 | 575 | ||
579 | while (signal_processor(cpu, sigp_restart) == sigp_busy) | 576 | while (signal_processor(cpu, sigp_restart) == sigp_busy) |
@@ -582,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
582 | while (!cpu_online(cpu)) | 579 | while (!cpu_online(cpu)) |
583 | cpu_relax(); | 580 | cpu_relax(); |
584 | return 0; | 581 | return 0; |
582 | |||
583 | err_out: | ||
584 | smp_free_lowcore(cpu); | ||
585 | return -EIO; | ||
585 | } | 586 | } |
586 | 587 | ||
587 | static int __init setup_possible_cpus(char *s) | 588 | static int __init setup_possible_cpus(char *s) |
@@ -589,9 +590,8 @@ static int __init setup_possible_cpus(char *s) | |||
589 | int pcpus, cpu; | 590 | int pcpus, cpu; |
590 | 591 | ||
591 | pcpus = simple_strtoul(s, NULL, 0); | 592 | pcpus = simple_strtoul(s, NULL, 0); |
592 | cpu_possible_map = cpumask_of_cpu(0); | 593 | for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++) |
593 | for (cpu = 1; cpu < pcpus && cpu < NR_CPUS; cpu++) | 594 | set_cpu_possible(cpu, true); |
594 | cpu_set(cpu, cpu_possible_map); | ||
595 | return 0; | 595 | return 0; |
596 | } | 596 | } |
597 | early_param("possible_cpus", setup_possible_cpus); | 597 | early_param("possible_cpus", setup_possible_cpus); |
@@ -663,7 +663,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
663 | /* request the 0x1201 emergency signal external interrupt */ | 663 | /* request the 0x1201 emergency signal external interrupt */ |
664 | if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) | 664 | if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) |
665 | panic("Couldn't request external interrupt 0x1201"); | 665 | panic("Couldn't request external interrupt 0x1201"); |
666 | print_cpu_info(&S390_lowcore.cpu_data); | 666 | print_cpu_info(); |
667 | 667 | ||
668 | /* Reallocate current lowcore, but keep its contents. */ | 668 | /* Reallocate current lowcore, but keep its contents. */ |
669 | lc_order = sizeof(long) == 8 ? 1 : 0; | 669 | lc_order = sizeof(long) == 8 ? 1 : 0; |
diff --git a/drivers/s390/sysinfo.c b/arch/s390/kernel/sysinfo.c index 0eea90781385..b5e75e1061c8 100644 --- a/drivers/s390/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c | |||
@@ -1,9 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/sysinfo.c | 2 | * Copyright IBM Corp. 2001, 2009 |
3 | * | 3 | * Author(s): Ulrich Weigand <Ulrich.Weigand@de.ibm.com>, |
4 | * Copyright IBM Corp. 2001, 2008 | 4 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, |
5 | * Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com) | ||
6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
7 | */ | 5 | */ |
8 | 6 | ||
9 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
@@ -24,7 +22,7 @@ | |||
24 | 22 | ||
25 | static inline int stsi_0(void) | 23 | static inline int stsi_0(void) |
26 | { | 24 | { |
27 | int rc = stsi (NULL, 0, 0, 0); | 25 | int rc = stsi(NULL, 0, 0, 0); |
28 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); | 26 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); |
29 | } | 27 | } |
30 | 28 | ||
@@ -78,23 +76,6 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) | |||
78 | return len; | 76 | return len; |
79 | } | 77 | } |
80 | 78 | ||
81 | #if 0 /* Currently unused */ | ||
82 | static int stsi_1_2_1(struct sysinfo_1_2_1 *info, char *page, int len) | ||
83 | { | ||
84 | if (stsi(info, 1, 2, 1) == -ENOSYS) | ||
85 | return len; | ||
86 | |||
87 | len += sprintf(page + len, "\n"); | ||
88 | EBCASC(info->sequence, sizeof(info->sequence)); | ||
89 | EBCASC(info->plant, sizeof(info->plant)); | ||
90 | len += sprintf(page + len, "Sequence Code of CPU: %-16.16s\n", | ||
91 | info->sequence); | ||
92 | len += sprintf(page + len, "Plant of CPU: %-16.16s\n", | ||
93 | info->plant); | ||
94 | return len; | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | 79 | static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) |
99 | { | 80 | { |
100 | struct sysinfo_1_2_2_extension *ext; | 81 | 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) | |||
145 | if (info->secondary_capability != 0) | 126 | if (info->secondary_capability != 0) |
146 | len += sprintf(page + len, "Secondary Capability: %d\n", | 127 | len += sprintf(page + len, "Secondary Capability: %d\n", |
147 | info->secondary_capability); | 128 | info->secondary_capability); |
148 | |||
149 | return len; | 129 | return len; |
150 | } | 130 | } |
151 | 131 | ||
152 | #if 0 /* Currently unused */ | ||
153 | static int stsi_2_2_1(struct sysinfo_2_2_1 *info, char *page, int len) | ||
154 | { | ||
155 | if (stsi(info, 2, 2, 1) == -ENOSYS) | ||
156 | return len; | ||
157 | |||
158 | len += sprintf(page + len, "\n"); | ||
159 | EBCASC (info->sequence, sizeof(info->sequence)); | ||
160 | EBCASC (info->plant, sizeof(info->plant)); | ||
161 | len += sprintf(page + len, "Sequence Code of logical CPU: %-16.16s\n", | ||
162 | info->sequence); | ||
163 | len += sprintf(page + len, "Plant of logical CPU: %-16.16s\n", | ||
164 | info->plant); | ||
165 | return len; | ||
166 | } | ||
167 | #endif | ||
168 | |||
169 | static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) | 132 | static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) |
170 | { | 133 | { |
171 | if (stsi(info, 2, 2, 2) == -ENOSYS) | 134 | if (stsi(info, 2, 2, 2) == -ENOSYS) |
172 | return len; | 135 | return len; |
173 | 136 | ||
174 | EBCASC (info->name, sizeof(info->name)); | 137 | EBCASC(info->name, sizeof(info->name)); |
175 | 138 | ||
176 | len += sprintf(page + len, "\n"); | 139 | len += sprintf(page + len, "\n"); |
177 | len += sprintf(page + len, "LPAR Number: %d\n", | 140 | 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) | |||
214 | if (stsi(info, 3, 2, 2) == -ENOSYS) | 177 | if (stsi(info, 3, 2, 2) == -ENOSYS) |
215 | return len; | 178 | return len; |
216 | for (i = 0; i < info->count; i++) { | 179 | for (i = 0; i < info->count; i++) { |
217 | EBCASC (info->vm[i].name, sizeof(info->vm[i].name)); | 180 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); |
218 | EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi)); | 181 | EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); |
219 | len += sprintf(page + len, "\n"); | 182 | len += sprintf(page + len, "\n"); |
220 | len += sprintf(page + len, "VM%02d Name: %-8.8s\n", | 183 | len += sprintf(page + len, "VM%02d Name: %-8.8s\n", |
221 | i, info->vm[i].name); | 184 | 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) | |||
237 | return len; | 200 | return len; |
238 | } | 201 | } |
239 | 202 | ||
240 | |||
241 | static int proc_read_sysinfo(char *page, char **start, | 203 | static int proc_read_sysinfo(char *page, char **start, |
242 | off_t off, int count, | 204 | off_t off, int count, |
243 | int *eof, void *data) | 205 | int *eof, void *data) |
244 | { | 206 | { |
245 | unsigned long info = get_zeroed_page (GFP_KERNEL); | 207 | unsigned long info = get_zeroed_page(GFP_KERNEL); |
246 | int level, len; | 208 | int level, len; |
247 | 209 | ||
248 | if (!info) | 210 | if (!info) |
249 | return 0; | 211 | return 0; |
250 | 212 | ||
@@ -262,8 +224,8 @@ static int proc_read_sysinfo(char *page, char **start, | |||
262 | if (level >= 3) | 224 | if (level >= 3) |
263 | len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); | 225 | len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); |
264 | 226 | ||
265 | free_page (info); | 227 | free_page(info); |
266 | return len; | 228 | return len; |
267 | } | 229 | } |
268 | 230 | ||
269 | static __init int create_proc_sysinfo(void) | 231 | static __init int create_proc_sysinfo(void) |
@@ -272,8 +234,7 @@ static __init int create_proc_sysinfo(void) | |||
272 | proc_read_sysinfo, NULL); | 234 | proc_read_sysinfo, NULL); |
273 | return 0; | 235 | return 0; |
274 | } | 236 | } |
275 | 237 | device_initcall(create_proc_sysinfo); | |
276 | __initcall(create_proc_sysinfo); | ||
277 | 238 | ||
278 | /* | 239 | /* |
279 | * Service levels interface. | 240 | * Service levels interface. |
@@ -387,13 +348,11 @@ static __init int create_proc_service_level(void) | |||
387 | register_service_level(&service_level_vm); | 348 | register_service_level(&service_level_vm); |
388 | return 0; | 349 | return 0; |
389 | } | 350 | } |
390 | |||
391 | subsys_initcall(create_proc_service_level); | 351 | subsys_initcall(create_proc_service_level); |
392 | 352 | ||
393 | /* | 353 | /* |
394 | * Bogomips calculation based on cpu capability. | 354 | * Bogomips calculation based on cpu capability. |
395 | */ | 355 | */ |
396 | |||
397 | int get_cpu_capability(unsigned int *capability) | 356 | int get_cpu_capability(unsigned int *capability) |
398 | { | 357 | { |
399 | struct sysinfo_1_2_2 *info; | 358 | struct sysinfo_1_2_2 *info; |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index fc468cae4460..f72d41068dc2 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old, | |||
331 | } | 331 | } |
332 | 332 | ||
333 | static DEFINE_PER_CPU(atomic_t, clock_sync_word); | 333 | static DEFINE_PER_CPU(atomic_t, clock_sync_word); |
334 | static DEFINE_MUTEX(clock_sync_mutex); | ||
334 | static unsigned long clock_sync_flags; | 335 | static unsigned long clock_sync_flags; |
335 | 336 | ||
336 | #define CLOCK_SYNC_HAS_ETR 0 | 337 | #define CLOCK_SYNC_HAS_ETR 0 |
@@ -394,6 +395,20 @@ static void enable_sync_clock(void) | |||
394 | atomic_set_mask(0x80000000, sw_ptr); | 395 | atomic_set_mask(0x80000000, sw_ptr); |
395 | } | 396 | } |
396 | 397 | ||
398 | /* | ||
399 | * Function to check if the clock is in sync. | ||
400 | */ | ||
401 | static inline int check_sync_clock(void) | ||
402 | { | ||
403 | atomic_t *sw_ptr; | ||
404 | int rc; | ||
405 | |||
406 | sw_ptr = &get_cpu_var(clock_sync_word); | ||
407 | rc = (atomic_read(sw_ptr) & 0x80000000U) != 0; | ||
408 | put_cpu_var(clock_sync_sync); | ||
409 | return rc; | ||
410 | } | ||
411 | |||
397 | /* Single threaded workqueue used for etr and stp sync events */ | 412 | /* Single threaded workqueue used for etr and stp sync events */ |
398 | static struct workqueue_struct *time_sync_wq; | 413 | static struct workqueue_struct *time_sync_wq; |
399 | 414 | ||
@@ -485,6 +500,8 @@ static void etr_reset(void) | |||
485 | if (etr_setr(&etr_eacr) == 0) { | 500 | if (etr_setr(&etr_eacr) == 0) { |
486 | etr_tolec = get_clock(); | 501 | etr_tolec = get_clock(); |
487 | set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags); | 502 | set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags); |
503 | if (etr_port0_online && etr_port1_online) | ||
504 | set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
488 | } else if (etr_port0_online || etr_port1_online) { | 505 | } else if (etr_port0_online || etr_port1_online) { |
489 | pr_warning("The real or virtual hardware system does " | 506 | pr_warning("The real or virtual hardware system does " |
490 | "not provide an ETR interface\n"); | 507 | "not provide an ETR interface\n"); |
@@ -533,8 +550,7 @@ void etr_switch_to_local(void) | |||
533 | { | 550 | { |
534 | if (!etr_eacr.sl) | 551 | if (!etr_eacr.sl) |
535 | return; | 552 | return; |
536 | if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) | 553 | disable_sync_clock(NULL); |
537 | disable_sync_clock(NULL); | ||
538 | set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); | 554 | set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); |
539 | queue_work(time_sync_wq, &etr_work); | 555 | queue_work(time_sync_wq, &etr_work); |
540 | } | 556 | } |
@@ -549,8 +565,7 @@ void etr_sync_check(void) | |||
549 | { | 565 | { |
550 | if (!etr_eacr.es) | 566 | if (!etr_eacr.es) |
551 | return; | 567 | return; |
552 | if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) | 568 | disable_sync_clock(NULL); |
553 | disable_sync_clock(NULL); | ||
554 | set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); | 569 | set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); |
555 | queue_work(time_sync_wq, &etr_work); | 570 | queue_work(time_sync_wq, &etr_work); |
556 | } | 571 | } |
@@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib, | |||
914 | * Do not try to get the alternate port aib if the clock | 929 | * Do not try to get the alternate port aib if the clock |
915 | * is not in sync yet. | 930 | * is not in sync yet. |
916 | */ | 931 | */ |
917 | if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es) | 932 | if (!check_sync_clock()) |
918 | return eacr; | 933 | return eacr; |
919 | 934 | ||
920 | /* | 935 | /* |
@@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work) | |||
997 | on_each_cpu(disable_sync_clock, NULL, 1); | 1012 | on_each_cpu(disable_sync_clock, NULL, 1); |
998 | del_timer_sync(&etr_timer); | 1013 | del_timer_sync(&etr_timer); |
999 | etr_update_eacr(eacr); | 1014 | etr_update_eacr(eacr); |
1000 | clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1001 | goto out_unlock; | 1015 | goto out_unlock; |
1002 | } | 1016 | } |
1003 | 1017 | ||
@@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work) | |||
1071 | /* Both ports not usable. */ | 1085 | /* Both ports not usable. */ |
1072 | eacr.es = eacr.sl = 0; | 1086 | eacr.es = eacr.sl = 0; |
1073 | sync_port = -1; | 1087 | sync_port = -1; |
1074 | clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1075 | } | 1088 | } |
1076 | 1089 | ||
1077 | if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) | ||
1078 | eacr.es = 0; | ||
1079 | |||
1080 | /* | 1090 | /* |
1081 | * If the clock is in sync just update the eacr and return. | 1091 | * If the clock is in sync just update the eacr and return. |
1082 | * If there is no valid sync port wait for a port update. | 1092 | * If there is no valid sync port wait for a port update. |
1083 | */ | 1093 | */ |
1084 | if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) || | 1094 | if (check_sync_clock() || sync_port < 0) { |
1085 | eacr.es || sync_port < 0) { | ||
1086 | etr_update_eacr(eacr); | 1095 | etr_update_eacr(eacr); |
1087 | etr_set_tolec_timeout(now); | 1096 | etr_set_tolec_timeout(now); |
1088 | goto out_unlock; | 1097 | goto out_unlock; |
@@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work) | |||
1103 | * and set up a timer to try again after 0.5 seconds | 1112 | * and set up a timer to try again after 0.5 seconds |
1104 | */ | 1113 | */ |
1105 | etr_update_eacr(eacr); | 1114 | etr_update_eacr(eacr); |
1106 | set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1107 | if (now < etr_tolec + (1600000 << 12) || | 1115 | if (now < etr_tolec + (1600000 << 12) || |
1108 | etr_sync_clock_stop(&aib, sync_port) != 0) { | 1116 | etr_sync_clock_stop(&aib, sync_port) != 0) { |
1109 | /* Sync failed. Try again in 1/2 second. */ | 1117 | /* Sync failed. Try again in 1/2 second. */ |
1110 | eacr.es = 0; | 1118 | eacr.es = 0; |
1111 | etr_update_eacr(eacr); | 1119 | etr_update_eacr(eacr); |
1112 | clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1113 | etr_set_sync_timeout(); | 1120 | etr_set_sync_timeout(); |
1114 | } else | 1121 | } else |
1115 | etr_set_tolec_timeout(now); | 1122 | etr_set_tolec_timeout(now); |
@@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev, | |||
1191 | return -EINVAL; | 1198 | return -EINVAL; |
1192 | if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags)) | 1199 | if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags)) |
1193 | return -EOPNOTSUPP; | 1200 | return -EOPNOTSUPP; |
1201 | mutex_lock(&clock_sync_mutex); | ||
1194 | if (dev == &etr_port0_dev) { | 1202 | if (dev == &etr_port0_dev) { |
1195 | if (etr_port0_online == value) | 1203 | if (etr_port0_online == value) |
1196 | return count; /* Nothing to do. */ | 1204 | goto out; /* Nothing to do. */ |
1197 | etr_port0_online = value; | 1205 | etr_port0_online = value; |
1206 | if (etr_port0_online && etr_port1_online) | ||
1207 | set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1208 | else | ||
1209 | clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1198 | set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); | 1210 | set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); |
1199 | queue_work(time_sync_wq, &etr_work); | 1211 | queue_work(time_sync_wq, &etr_work); |
1200 | } else { | 1212 | } else { |
1201 | if (etr_port1_online == value) | 1213 | if (etr_port1_online == value) |
1202 | return count; /* Nothing to do. */ | 1214 | goto out; /* Nothing to do. */ |
1203 | etr_port1_online = value; | 1215 | etr_port1_online = value; |
1216 | if (etr_port0_online && etr_port1_online) | ||
1217 | set_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1218 | else | ||
1219 | clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); | ||
1204 | set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); | 1220 | set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); |
1205 | queue_work(time_sync_wq, &etr_work); | 1221 | queue_work(time_sync_wq, &etr_work); |
1206 | } | 1222 | } |
1223 | out: | ||
1224 | mutex_unlock(&clock_sync_mutex); | ||
1207 | return count; | 1225 | return count; |
1208 | } | 1226 | } |
1209 | 1227 | ||
@@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm) | |||
1471 | */ | 1489 | */ |
1472 | void stp_sync_check(void) | 1490 | void stp_sync_check(void) |
1473 | { | 1491 | { |
1474 | if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) | ||
1475 | return; | ||
1476 | disable_sync_clock(NULL); | 1492 | disable_sync_clock(NULL); |
1477 | queue_work(time_sync_wq, &stp_work); | 1493 | queue_work(time_sync_wq, &stp_work); |
1478 | } | 1494 | } |
@@ -1485,8 +1501,6 @@ void stp_sync_check(void) | |||
1485 | */ | 1501 | */ |
1486 | void stp_island_check(void) | 1502 | void stp_island_check(void) |
1487 | { | 1503 | { |
1488 | if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) | ||
1489 | return; | ||
1490 | disable_sync_clock(NULL); | 1504 | disable_sync_clock(NULL); |
1491 | queue_work(time_sync_wq, &stp_work); | 1505 | queue_work(time_sync_wq, &stp_work); |
1492 | } | 1506 | } |
@@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data) | |||
1513 | 1527 | ||
1514 | enable_sync_clock(); | 1528 | enable_sync_clock(); |
1515 | 1529 | ||
1516 | set_bit(CLOCK_SYNC_STP, &clock_sync_flags); | ||
1517 | if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) | ||
1518 | queue_work(time_sync_wq, &etr_work); | ||
1519 | |||
1520 | rc = 0; | 1530 | rc = 0; |
1521 | if (stp_info.todoff[0] || stp_info.todoff[1] || | 1531 | if (stp_info.todoff[0] || stp_info.todoff[1] || |
1522 | stp_info.todoff[2] || stp_info.todoff[3] || | 1532 | stp_info.todoff[2] || stp_info.todoff[3] || |
@@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data) | |||
1535 | if (rc) { | 1545 | if (rc) { |
1536 | disable_sync_clock(NULL); | 1546 | disable_sync_clock(NULL); |
1537 | stp_sync->in_sync = -EAGAIN; | 1547 | stp_sync->in_sync = -EAGAIN; |
1538 | clear_bit(CLOCK_SYNC_STP, &clock_sync_flags); | ||
1539 | if (etr_port0_online || etr_port1_online) | ||
1540 | queue_work(time_sync_wq, &etr_work); | ||
1541 | } else | 1548 | } else |
1542 | stp_sync->in_sync = 1; | 1549 | stp_sync->in_sync = 1; |
1543 | xchg(&first, 0); | 1550 | xchg(&first, 0); |
@@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work) | |||
1569 | if (rc || stp_info.c == 0) | 1576 | if (rc || stp_info.c == 0) |
1570 | goto out_unlock; | 1577 | goto out_unlock; |
1571 | 1578 | ||
1579 | /* Skip synchronization if the clock is already in sync. */ | ||
1580 | if (check_sync_clock()) | ||
1581 | goto out_unlock; | ||
1582 | |||
1572 | memset(&stp_sync, 0, sizeof(stp_sync)); | 1583 | memset(&stp_sync, 0, sizeof(stp_sync)); |
1573 | get_online_cpus(); | 1584 | get_online_cpus(); |
1574 | atomic_set(&stp_sync.cpus, num_online_cpus() - 1); | 1585 | atomic_set(&stp_sync.cpus, num_online_cpus() - 1); |
@@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class, | |||
1684 | return -EINVAL; | 1695 | return -EINVAL; |
1685 | if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) | 1696 | if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) |
1686 | return -EOPNOTSUPP; | 1697 | return -EOPNOTSUPP; |
1698 | mutex_lock(&clock_sync_mutex); | ||
1687 | stp_online = value; | 1699 | stp_online = value; |
1700 | if (stp_online) | ||
1701 | set_bit(CLOCK_SYNC_STP, &clock_sync_flags); | ||
1702 | else | ||
1703 | clear_bit(CLOCK_SYNC_STP, &clock_sync_flags); | ||
1688 | queue_work(time_sync_wq, &stp_work); | 1704 | queue_work(time_sync_wq, &stp_work); |
1705 | mutex_unlock(&clock_sync_mutex); | ||
1689 | return count; | 1706 | return count; |
1690 | } | 1707 | } |
1691 | 1708 | ||
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index cc362c9ea8f1..3c72c9cf22b6 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(topology_lock); | |||
74 | 74 | ||
75 | cpumask_t cpu_core_map[NR_CPUS]; | 75 | cpumask_t cpu_core_map[NR_CPUS]; |
76 | 76 | ||
77 | cpumask_t cpu_coregroup_map(unsigned int cpu) | 77 | static cpumask_t cpu_coregroup_map(unsigned int cpu) |
78 | { | 78 | { |
79 | struct core_info *core = &core_info; | 79 | struct core_info *core = &core_info; |
80 | unsigned long flags; | 80 | unsigned long flags; |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 4584d81984c0..c2e42cc65ce7 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -61,9 +61,11 @@ extern pgm_check_handler_t do_asce_exception; | |||
61 | #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) | 61 | #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) |
62 | 62 | ||
63 | #ifndef CONFIG_64BIT | 63 | #ifndef CONFIG_64BIT |
64 | #define LONG "%08lx " | ||
64 | #define FOURLONG "%08lx %08lx %08lx %08lx\n" | 65 | #define FOURLONG "%08lx %08lx %08lx %08lx\n" |
65 | static int kstack_depth_to_print = 12; | 66 | static int kstack_depth_to_print = 12; |
66 | #else /* CONFIG_64BIT */ | 67 | #else /* CONFIG_64BIT */ |
68 | #define LONG "%016lx " | ||
67 | #define FOURLONG "%016lx %016lx %016lx %016lx\n" | 69 | #define FOURLONG "%016lx %016lx %016lx %016lx\n" |
68 | static int kstack_depth_to_print = 20; | 70 | static int kstack_depth_to_print = 20; |
69 | #endif /* CONFIG_64BIT */ | 71 | #endif /* CONFIG_64BIT */ |
@@ -155,7 +157,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
155 | break; | 157 | break; |
156 | if (i && ((i * sizeof (long) % 32) == 0)) | 158 | if (i && ((i * sizeof (long) % 32) == 0)) |
157 | printk("\n "); | 159 | printk("\n "); |
158 | printk("%p ", (void *)*stack++); | 160 | printk(LONG, *stack++); |
159 | } | 161 | } |
160 | printk("\n"); | 162 | printk("\n"); |
161 | show_trace(task, sp); | 163 | show_trace(task, sp); |
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 690e17819686..89b2e7f1b7a9 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c | |||
@@ -144,7 +144,6 @@ out: | |||
144 | return -ENOMEM; | 144 | return -ENOMEM; |
145 | } | 145 | } |
146 | 146 | ||
147 | #ifdef CONFIG_HOTPLUG_CPU | ||
148 | void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) | 147 | void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) |
149 | { | 148 | { |
150 | unsigned long segment_table, page_table, page_frame; | 149 | unsigned long segment_table, page_table, page_frame; |
@@ -163,7 +162,6 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) | |||
163 | free_page(page_table); | 162 | free_page(page_table); |
164 | free_pages(segment_table, SEGMENT_ORDER); | 163 | free_pages(segment_table, SEGMENT_ORDER); |
165 | } | 164 | } |
166 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
167 | 165 | ||
168 | static void __vdso_init_cr5(void *dummy) | 166 | static void __vdso_init_cr5(void *dummy) |
169 | { | 167 | { |
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index d796d05c9c01..7a2063eb88f0 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S | |||
@@ -108,6 +108,8 @@ SECTIONS | |||
108 | EXIT_TEXT | 108 | EXIT_TEXT |
109 | } | 109 | } |
110 | 110 | ||
111 | /* early.c uses stsi, which requires page aligned data. */ | ||
112 | . = ALIGN(PAGE_SIZE); | ||
111 | .init.data : { | 113 | .init.data : { |
112 | INIT_DATA | 114 | INIT_DATA |
113 | } | 115 | } |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index cbfe91e10120..f4d56e9939c9 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
24 | #include <asm/lowcore.h> | 24 | #include <asm/lowcore.h> |
25 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
26 | 26 | #include <asm/nmi.h> | |
27 | #include "kvm-s390.h" | 27 | #include "kvm-s390.h" |
28 | #include "gaccess.h" | 28 | #include "gaccess.h" |
29 | 29 | ||
@@ -286,7 +286,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
286 | setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup, | 286 | setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup, |
287 | (unsigned long) vcpu); | 287 | (unsigned long) vcpu); |
288 | get_cpu_id(&vcpu->arch.cpu_id); | 288 | get_cpu_id(&vcpu->arch.cpu_id); |
289 | vcpu->arch.cpu_id.version = 0xfe; | 289 | vcpu->arch.cpu_id.version = 0xff; |
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
292 | 292 | ||
@@ -440,8 +440,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, | |||
440 | return -EINVAL; /* not implemented yet */ | 440 | return -EINVAL; /* not implemented yet */ |
441 | } | 441 | } |
442 | 442 | ||
443 | extern void s390_handle_mcck(void); | ||
444 | |||
445 | static void __vcpu_run(struct kvm_vcpu *vcpu) | 443 | static void __vcpu_run(struct kvm_vcpu *vcpu) |
446 | { | 444 | { |
447 | memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16); | 445 | memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16); |
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 6ccb9fab055a..3f5f680726ed 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/timex.h> | 11 | #include <linux/timex.h> |
12 | #include <linux/module.h> | ||
12 | #include <linux/irqflags.h> | 13 | #include <linux/irqflags.h> |
13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
14 | 15 | ||
@@ -92,6 +93,7 @@ out: | |||
92 | local_irq_restore(flags); | 93 | local_irq_restore(flags); |
93 | preempt_enable(); | 94 | preempt_enable(); |
94 | } | 95 | } |
96 | EXPORT_SYMBOL(__udelay); | ||
95 | 97 | ||
96 | /* | 98 | /* |
97 | * Simple udelay variant. To be used on startup and reboot | 99 | * Simple udelay variant. To be used on startup and reboot |
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index ae5cf5d03d41..4143b7c19096 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c | |||
@@ -44,7 +44,11 @@ static inline char *__strnend(const char *s, size_t n) | |||
44 | */ | 44 | */ |
45 | size_t strlen(const char *s) | 45 | size_t strlen(const char *s) |
46 | { | 46 | { |
47 | #if __GNUC__ < 4 | ||
47 | return __strend(s) - s; | 48 | return __strend(s) - s; |
49 | #else | ||
50 | return __builtin_strlen(s); | ||
51 | #endif | ||
48 | } | 52 | } |
49 | EXPORT_SYMBOL(strlen); | 53 | EXPORT_SYMBOL(strlen); |
50 | 54 | ||
@@ -70,6 +74,7 @@ EXPORT_SYMBOL(strnlen); | |||
70 | */ | 74 | */ |
71 | char *strcpy(char *dest, const char *src) | 75 | char *strcpy(char *dest, const char *src) |
72 | { | 76 | { |
77 | #if __GNUC__ < 4 | ||
73 | register int r0 asm("0") = 0; | 78 | register int r0 asm("0") = 0; |
74 | char *ret = dest; | 79 | char *ret = dest; |
75 | 80 | ||
@@ -78,6 +83,9 @@ char *strcpy(char *dest, const char *src) | |||
78 | : "+&a" (dest), "+&a" (src) : "d" (r0) | 83 | : "+&a" (dest), "+&a" (src) : "d" (r0) |
79 | : "cc", "memory" ); | 84 | : "cc", "memory" ); |
80 | return ret; | 85 | return ret; |
86 | #else | ||
87 | return __builtin_strcpy(dest, src); | ||
88 | #endif | ||
81 | } | 89 | } |
82 | EXPORT_SYMBOL(strcpy); | 90 | EXPORT_SYMBOL(strcpy); |
83 | 91 | ||
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 4d537205e83c..833e8366c351 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -200,29 +200,6 @@ static void do_low_address(struct pt_regs *regs, unsigned long error_code) | |||
200 | do_no_context(regs, error_code, 0); | 200 | do_no_context(regs, error_code, 0); |
201 | } | 201 | } |
202 | 202 | ||
203 | /* | ||
204 | * We ran out of memory, or some other thing happened to us that made | ||
205 | * us unable to handle the page fault gracefully. | ||
206 | */ | ||
207 | static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code, | ||
208 | unsigned long address) | ||
209 | { | ||
210 | struct task_struct *tsk = current; | ||
211 | struct mm_struct *mm = tsk->mm; | ||
212 | |||
213 | up_read(&mm->mmap_sem); | ||
214 | if (is_global_init(tsk)) { | ||
215 | yield(); | ||
216 | down_read(&mm->mmap_sem); | ||
217 | return 1; | ||
218 | } | ||
219 | printk("VM: killing process %s\n", tsk->comm); | ||
220 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
221 | do_group_exit(SIGKILL); | ||
222 | do_no_context(regs, error_code, address); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static void do_sigbus(struct pt_regs *regs, unsigned long error_code, | 203 | static void do_sigbus(struct pt_regs *regs, unsigned long error_code, |
227 | unsigned long address) | 204 | unsigned long address) |
228 | { | 205 | { |
@@ -367,7 +344,6 @@ good_area: | |||
367 | goto bad_area; | 344 | goto bad_area; |
368 | } | 345 | } |
369 | 346 | ||
370 | survive: | ||
371 | if (is_vm_hugetlb_page(vma)) | 347 | if (is_vm_hugetlb_page(vma)) |
372 | address &= HPAGE_MASK; | 348 | address &= HPAGE_MASK; |
373 | /* | 349 | /* |
@@ -378,8 +354,8 @@ survive: | |||
378 | fault = handle_mm_fault(mm, vma, address, write); | 354 | fault = handle_mm_fault(mm, vma, address, write); |
379 | if (unlikely(fault & VM_FAULT_ERROR)) { | 355 | if (unlikely(fault & VM_FAULT_ERROR)) { |
380 | if (fault & VM_FAULT_OOM) { | 356 | if (fault & VM_FAULT_OOM) { |
381 | if (do_out_of_memory(regs, error_code, address)) | 357 | up_read(&mm->mmap_sem); |
382 | goto survive; | 358 | pagefault_out_of_memory(); |
383 | return; | 359 | return; |
384 | } else if (fault & VM_FAULT_SIGBUS) { | 360 | } else if (fault & VM_FAULT_SIGBUS) { |
385 | do_sigbus(regs, error_code, address); | 361 | do_sigbus(regs, error_code, address); |
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index f0258ca3b17e..c634dfbe92e9 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -40,7 +40,9 @@ | |||
40 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 40 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
41 | 41 | ||
42 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); | 42 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); |
43 | |||
43 | char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); | 44 | char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); |
45 | EXPORT_SYMBOL(empty_zero_page); | ||
44 | 46 | ||
45 | /* | 47 | /* |
46 | * paging_init() sets up the page tables | 48 | * paging_init() sets up the page tables |
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6b6ddc4ea02b..be6c1cf4ad5a 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -258,6 +258,10 @@ int s390_enable_sie(void) | |||
258 | struct task_struct *tsk = current; | 258 | struct task_struct *tsk = current; |
259 | struct mm_struct *mm, *old_mm; | 259 | struct mm_struct *mm, *old_mm; |
260 | 260 | ||
261 | /* Do we have switched amode? If no, we cannot do sie */ | ||
262 | if (!switch_amode) | ||
263 | return -EINVAL; | ||
264 | |||
261 | /* Do we have pgstes? if yes, we are done */ | 265 | /* Do we have pgstes? if yes, we are done */ |
262 | if (tsk->mm->context.has_pgste) | 266 | if (tsk->mm->context.has_pgste) |
263 | return 0; | 267 | return 0; |
@@ -292,7 +296,7 @@ int s390_enable_sie(void) | |||
292 | tsk->mm = tsk->active_mm = mm; | 296 | tsk->mm = tsk->active_mm = mm; |
293 | preempt_disable(); | 297 | preempt_disable(); |
294 | update_mm(mm, tsk); | 298 | update_mm(mm, tsk); |
295 | cpu_set(smp_processor_id(), mm->cpu_vm_mask); | 299 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); |
296 | preempt_enable(); | 300 | preempt_enable(); |
297 | task_unlock(tsk); | 301 | task_unlock(tsk); |
298 | mmput(old_mm); | 302 | mmput(old_mm); |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index a53496828b76..54481a887769 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -13,10 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <asm/ebcdic.h> | 15 | #include <asm/ebcdic.h> |
16 | #include <linux/ctype.h> | ||
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/mempool.h> | 19 | #include <linux/mempool.h> |
19 | #include <linux/module.h> | 20 | #include <linux/moduleparam.h> |
20 | #include <linux/tty.h> | 21 | #include <linux/tty.h> |
21 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
22 | #include <net/iucv/iucv.h> | 23 | #include <net/iucv/iucv.h> |
@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1; | |||
95 | /* Array of allocated hvc iucv tty lines... */ | 96 | /* Array of allocated hvc iucv tty lines... */ |
96 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; | 97 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; |
97 | #define IUCV_HVC_CON_IDX (0) | 98 | #define IUCV_HVC_CON_IDX (0) |
99 | /* List of z/VM user ID filter entries (struct iucv_vmid_filter) */ | ||
100 | #define MAX_VMID_FILTER (500) | ||
101 | static size_t hvc_iucv_filter_size; | ||
102 | static void *hvc_iucv_filter; | ||
103 | static const char *hvc_iucv_filter_string; | ||
104 | static DEFINE_RWLOCK(hvc_iucv_filter_lock); | ||
98 | 105 | ||
99 | /* Kmem cache and mempool for iucv_tty_buffer elements */ | 106 | /* Kmem cache and mempool for iucv_tty_buffer elements */ |
100 | static struct kmem_cache *hvc_iucv_buffer_cache; | 107 | static struct kmem_cache *hvc_iucv_buffer_cache; |
@@ -618,6 +625,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) | |||
618 | } | 625 | } |
619 | 626 | ||
620 | /** | 627 | /** |
628 | * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID | ||
629 | * @ipvmid: Originating z/VM user ID (right padded with blanks) | ||
630 | * | ||
631 | * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise | ||
632 | * non-zero. | ||
633 | */ | ||
634 | static int hvc_iucv_filter_connreq(u8 ipvmid[8]) | ||
635 | { | ||
636 | size_t i; | ||
637 | |||
638 | /* Note: default policy is ACCEPT if no filter is set */ | ||
639 | if (!hvc_iucv_filter_size) | ||
640 | return 0; | ||
641 | |||
642 | for (i = 0; i < hvc_iucv_filter_size; i++) | ||
643 | if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8)) | ||
644 | return 0; | ||
645 | return 1; | ||
646 | } | ||
647 | |||
648 | /** | ||
621 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. | 649 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. |
622 | * @path: Pending path (struct iucv_path) | 650 | * @path: Pending path (struct iucv_path) |
623 | * @ipvmid: z/VM system identifier of originator | 651 | * @ipvmid: z/VM system identifier of originator |
@@ -641,6 +669,7 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
641 | { | 669 | { |
642 | struct hvc_iucv_private *priv; | 670 | struct hvc_iucv_private *priv; |
643 | u8 nuser_data[16]; | 671 | u8 nuser_data[16]; |
672 | u8 vm_user_id[9]; | ||
644 | int i, rc; | 673 | int i, rc; |
645 | 674 | ||
646 | priv = NULL; | 675 | priv = NULL; |
@@ -653,6 +682,20 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
653 | if (!priv) | 682 | if (!priv) |
654 | return -ENODEV; | 683 | return -ENODEV; |
655 | 684 | ||
685 | /* Enforce that ipvmid is allowed to connect to us */ | ||
686 | read_lock(&hvc_iucv_filter_lock); | ||
687 | rc = hvc_iucv_filter_connreq(ipvmid); | ||
688 | read_unlock(&hvc_iucv_filter_lock); | ||
689 | if (rc) { | ||
690 | iucv_path_sever(path, ipuser); | ||
691 | iucv_path_free(path); | ||
692 | memcpy(vm_user_id, ipvmid, 8); | ||
693 | vm_user_id[8] = 0; | ||
694 | pr_info("A connection request from z/VM user ID %s " | ||
695 | "was refused\n", vm_user_id); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
656 | spin_lock(&priv->lock); | 699 | spin_lock(&priv->lock); |
657 | 700 | ||
658 | /* If the terminal is already connected or being severed, then sever | 701 | /* If the terminal is already connected or being severed, then sever |
@@ -877,6 +920,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) | |||
877 | } | 920 | } |
878 | 921 | ||
879 | /** | 922 | /** |
923 | * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID | ||
924 | * @filter: String containing a comma-separated list of z/VM user IDs | ||
925 | */ | ||
926 | static const char *hvc_iucv_parse_filter(const char *filter, char *dest) | ||
927 | { | ||
928 | const char *nextdelim, *residual; | ||
929 | size_t len; | ||
930 | |||
931 | nextdelim = strchr(filter, ','); | ||
932 | if (nextdelim) { | ||
933 | len = nextdelim - filter; | ||
934 | residual = nextdelim + 1; | ||
935 | } else { | ||
936 | len = strlen(filter); | ||
937 | residual = filter + len; | ||
938 | } | ||
939 | |||
940 | if (len == 0) | ||
941 | return ERR_PTR(-EINVAL); | ||
942 | |||
943 | /* check for '\n' (if called from sysfs) */ | ||
944 | if (filter[len - 1] == '\n') | ||
945 | len--; | ||
946 | |||
947 | if (len > 8) | ||
948 | return ERR_PTR(-EINVAL); | ||
949 | |||
950 | /* pad with blanks and save upper case version of user ID */ | ||
951 | memset(dest, ' ', 8); | ||
952 | while (len--) | ||
953 | dest[len] = toupper(filter[len]); | ||
954 | return residual; | ||
955 | } | ||
956 | |||
957 | /** | ||
958 | * hvc_iucv_setup_filter() - Set up z/VM user ID filter | ||
959 | * @filter: String consisting of a comma-separated list of z/VM user IDs | ||
960 | * | ||
961 | * The function parses the @filter string and creates an array containing | ||
962 | * the list of z/VM user ID filter entries. | ||
963 | * Return code 0 means success, -EINVAL if the filter is syntactically | ||
964 | * incorrect, -ENOMEM if there was not enough memory to allocate the | ||
965 | * filter list array, or -ENOSPC if too many z/VM user IDs have been specified. | ||
966 | */ | ||
967 | static int hvc_iucv_setup_filter(const char *val) | ||
968 | { | ||
969 | const char *residual; | ||
970 | int err; | ||
971 | size_t size, count; | ||
972 | void *array, *old_filter; | ||
973 | |||
974 | count = strlen(val); | ||
975 | if (count == 0 || (count == 1 && val[0] == '\n')) { | ||
976 | size = 0; | ||
977 | array = NULL; | ||
978 | goto out_replace_filter; /* clear filter */ | ||
979 | } | ||
980 | |||
981 | /* count user IDs in order to allocate sufficient memory */ | ||
982 | size = 1; | ||
983 | residual = val; | ||
984 | while ((residual = strchr(residual, ',')) != NULL) { | ||
985 | residual++; | ||
986 | size++; | ||
987 | } | ||
988 | |||
989 | /* check if the specified list exceeds the filter limit */ | ||
990 | if (size > MAX_VMID_FILTER) | ||
991 | return -ENOSPC; | ||
992 | |||
993 | array = kzalloc(size * 8, GFP_KERNEL); | ||
994 | if (!array) | ||
995 | return -ENOMEM; | ||
996 | |||
997 | count = size; | ||
998 | residual = val; | ||
999 | while (*residual && count) { | ||
1000 | residual = hvc_iucv_parse_filter(residual, | ||
1001 | array + ((size - count) * 8)); | ||
1002 | if (IS_ERR(residual)) { | ||
1003 | err = PTR_ERR(residual); | ||
1004 | kfree(array); | ||
1005 | goto out_err; | ||
1006 | } | ||
1007 | count--; | ||
1008 | } | ||
1009 | |||
1010 | out_replace_filter: | ||
1011 | write_lock_bh(&hvc_iucv_filter_lock); | ||
1012 | old_filter = hvc_iucv_filter; | ||
1013 | hvc_iucv_filter_size = size; | ||
1014 | hvc_iucv_filter = array; | ||
1015 | write_unlock_bh(&hvc_iucv_filter_lock); | ||
1016 | kfree(old_filter); | ||
1017 | |||
1018 | err = 0; | ||
1019 | out_err: | ||
1020 | return err; | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * param_set_vmidfilter() - Set z/VM user ID filter parameter | ||
1025 | * @val: String consisting of a comma-separated list of z/VM user IDs | ||
1026 | * @kp: Kernel parameter pointing to hvc_iucv_filter array | ||
1027 | * | ||
1028 | * The function sets up the z/VM user ID filter specified as comma-separated | ||
1029 | * list of user IDs in @val. | ||
1030 | * Note: If it is called early in the boot process, @val is stored and | ||
1031 | * parsed later in hvc_iucv_init(). | ||
1032 | */ | ||
1033 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | ||
1034 | { | ||
1035 | int rc; | ||
1036 | |||
1037 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
1038 | return -ENODEV; | ||
1039 | |||
1040 | if (!val) | ||
1041 | return -EINVAL; | ||
1042 | |||
1043 | rc = 0; | ||
1044 | if (slab_is_available()) | ||
1045 | rc = hvc_iucv_setup_filter(val); | ||
1046 | else | ||
1047 | hvc_iucv_filter_string = val; /* defer... */ | ||
1048 | return rc; | ||
1049 | } | ||
1050 | |||
1051 | /** | ||
1052 | * param_get_vmidfilter() - Get z/VM user ID filter | ||
1053 | * @buffer: Buffer to store z/VM user ID filter, | ||
1054 | * (buffer size assumption PAGE_SIZE) | ||
1055 | * @kp: Kernel parameter pointing to the hvc_iucv_filter array | ||
1056 | * | ||
1057 | * The function stores the filter as a comma-separated list of z/VM user IDs | ||
1058 | * in @buffer. Typically, sysfs routines call this function for attr show. | ||
1059 | */ | ||
1060 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | ||
1061 | { | ||
1062 | int rc; | ||
1063 | size_t index, len; | ||
1064 | void *start, *end; | ||
1065 | |||
1066 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
1067 | return -ENODEV; | ||
1068 | |||
1069 | rc = 0; | ||
1070 | read_lock_bh(&hvc_iucv_filter_lock); | ||
1071 | for (index = 0; index < hvc_iucv_filter_size; index++) { | ||
1072 | start = hvc_iucv_filter + (8 * index); | ||
1073 | end = memchr(start, ' ', 8); | ||
1074 | len = (end) ? end - start : 8; | ||
1075 | memcpy(buffer + rc, start, len); | ||
1076 | rc += len; | ||
1077 | buffer[rc++] = ','; | ||
1078 | } | ||
1079 | read_unlock_bh(&hvc_iucv_filter_lock); | ||
1080 | if (rc) | ||
1081 | buffer[--rc] = '\0'; /* replace last comma and update rc */ | ||
1082 | return rc; | ||
1083 | } | ||
1084 | |||
1085 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | ||
1086 | |||
1087 | /** | ||
880 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1088 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
881 | */ | 1089 | */ |
882 | static int __init hvc_iucv_init(void) | 1090 | static int __init hvc_iucv_init(void) |
@@ -884,24 +1092,53 @@ static int __init hvc_iucv_init(void) | |||
884 | int rc; | 1092 | int rc; |
885 | unsigned int i; | 1093 | unsigned int i; |
886 | 1094 | ||
1095 | if (!hvc_iucv_devices) | ||
1096 | return -ENODEV; | ||
1097 | |||
887 | if (!MACHINE_IS_VM) { | 1098 | if (!MACHINE_IS_VM) { |
888 | pr_info("The z/VM IUCV HVC device driver cannot " | 1099 | pr_notice("The z/VM IUCV HVC device driver cannot " |
889 | "be used without z/VM\n"); | 1100 | "be used without z/VM\n"); |
890 | return -ENODEV; | 1101 | rc = -ENODEV; |
1102 | goto out_error; | ||
891 | } | 1103 | } |
892 | 1104 | ||
893 | if (!hvc_iucv_devices) | 1105 | if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) { |
894 | return -ENODEV; | 1106 | pr_err("%lu is not a valid value for the hvc_iucv= " |
1107 | "kernel parameter\n", hvc_iucv_devices); | ||
1108 | rc = -EINVAL; | ||
1109 | goto out_error; | ||
1110 | } | ||
895 | 1111 | ||
896 | if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) | 1112 | /* parse hvc_iucv_allow string and create z/VM user ID filter list */ |
897 | return -EINVAL; | 1113 | if (hvc_iucv_filter_string) { |
1114 | rc = hvc_iucv_setup_filter(hvc_iucv_filter_string); | ||
1115 | switch (rc) { | ||
1116 | case 0: | ||
1117 | break; | ||
1118 | case -ENOMEM: | ||
1119 | pr_err("Allocating memory failed with " | ||
1120 | "reason code=%d\n", 3); | ||
1121 | goto out_error; | ||
1122 | case -EINVAL: | ||
1123 | pr_err("hvc_iucv_allow= does not specify a valid " | ||
1124 | "z/VM user ID list\n"); | ||
1125 | goto out_error; | ||
1126 | case -ENOSPC: | ||
1127 | pr_err("hvc_iucv_allow= specifies too many " | ||
1128 | "z/VM user IDs\n"); | ||
1129 | goto out_error; | ||
1130 | default: | ||
1131 | goto out_error; | ||
1132 | } | ||
1133 | } | ||
898 | 1134 | ||
899 | hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, | 1135 | hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, |
900 | sizeof(struct iucv_tty_buffer), | 1136 | sizeof(struct iucv_tty_buffer), |
901 | 0, 0, NULL); | 1137 | 0, 0, NULL); |
902 | if (!hvc_iucv_buffer_cache) { | 1138 | if (!hvc_iucv_buffer_cache) { |
903 | pr_err("Allocating memory failed with reason code=%d\n", 1); | 1139 | pr_err("Allocating memory failed with reason code=%d\n", 1); |
904 | return -ENOMEM; | 1140 | rc = -ENOMEM; |
1141 | goto out_error; | ||
905 | } | 1142 | } |
906 | 1143 | ||
907 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, | 1144 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, |
@@ -909,7 +1146,8 @@ static int __init hvc_iucv_init(void) | |||
909 | if (!hvc_iucv_mempool) { | 1146 | if (!hvc_iucv_mempool) { |
910 | pr_err("Allocating memory failed with reason code=%d\n", 2); | 1147 | pr_err("Allocating memory failed with reason code=%d\n", 2); |
911 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 1148 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
912 | return -ENOMEM; | 1149 | rc = -ENOMEM; |
1150 | goto out_error; | ||
913 | } | 1151 | } |
914 | 1152 | ||
915 | /* register the first terminal device as console | 1153 | /* register the first terminal device as console |
@@ -953,6 +1191,8 @@ out_error_hvc: | |||
953 | out_error_memory: | 1191 | out_error_memory: |
954 | mempool_destroy(hvc_iucv_mempool); | 1192 | mempool_destroy(hvc_iucv_mempool); |
955 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 1193 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
1194 | out_error: | ||
1195 | hvc_iucv_devices = 0; /* ensure that we do not provide any device */ | ||
956 | return rc; | 1196 | return rc; |
957 | } | 1197 | } |
958 | 1198 | ||
@@ -968,3 +1208,4 @@ static int __init hvc_iucv_config(char *val) | |||
968 | 1208 | ||
969 | device_initcall(hvc_iucv_init); | 1209 | device_initcall(hvc_iucv_init); |
970 | __setup("hvc_iucv=", hvc_iucv_config); | 1210 | __setup("hvc_iucv=", hvc_iucv_config); |
1211 | core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640); | ||
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index d0eae59bc366..95bccfd3f169 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile | |||
@@ -2,9 +2,6 @@ | |||
2 | # Makefile for the S/390 specific device drivers | 2 | # Makefile for the S/390 specific device drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | ||
6 | |||
7 | obj-y += s390mach.o sysinfo.o | ||
8 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ | 5 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ |
9 | 6 | ||
10 | drivers-y += drivers/s390/built-in.o | 7 | drivers-y += drivers/s390/built-in.o |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 08c23a921012..2fd64e5a9ab2 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -9,6 +9,9 @@ | |||
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define KMSG_COMPONENT "dasd" | ||
13 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
14 | |||
12 | #include <linux/kmod.h> | 15 | #include <linux/kmod.h> |
13 | #include <linux/init.h> | 16 | #include <linux/init.h> |
14 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
@@ -22,6 +25,7 @@ | |||
22 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
23 | #include <asm/idals.h> | 26 | #include <asm/idals.h> |
24 | #include <asm/todclk.h> | 27 | #include <asm/todclk.h> |
28 | #include <asm/itcw.h> | ||
25 | 29 | ||
26 | /* This is ugly... */ | 30 | /* This is ugly... */ |
27 | #define PRINTK_HEADER "dasd:" | 31 | #define PRINTK_HEADER "dasd:" |
@@ -221,7 +225,7 @@ static int dasd_state_known_to_basic(struct dasd_device *device) | |||
221 | return rc; | 225 | return rc; |
222 | } | 226 | } |
223 | /* register 'device' debug area, used for all DBF_DEV_XXX calls */ | 227 | /* register 'device' debug area, used for all DBF_DEV_XXX calls */ |
224 | device->debug_area = debug_register(dev_name(&device->cdev->dev), 1, 1, | 228 | device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1, |
225 | 8 * sizeof(long)); | 229 | 8 * sizeof(long)); |
226 | debug_register_view(device->debug_area, &debug_sprintf_view); | 230 | debug_register_view(device->debug_area, &debug_sprintf_view); |
227 | debug_set_level(device->debug_area, DBF_WARNING); | 231 | debug_set_level(device->debug_area, DBF_WARNING); |
@@ -762,7 +766,7 @@ static inline int dasd_check_cqr(struct dasd_ccw_req *cqr) | |||
762 | return -EINVAL; | 766 | return -EINVAL; |
763 | device = cqr->startdev; | 767 | device = cqr->startdev; |
764 | if (strncmp((char *) &cqr->magic, device->discipline->ebcname, 4)) { | 768 | if (strncmp((char *) &cqr->magic, device->discipline->ebcname, 4)) { |
765 | DEV_MESSAGE(KERN_WARNING, device, | 769 | DBF_DEV_EVENT(DBF_WARNING, device, |
766 | " dasd_ccw_req 0x%08x magic doesn't match" | 770 | " dasd_ccw_req 0x%08x magic doesn't match" |
767 | " discipline 0x%08x", | 771 | " discipline 0x%08x", |
768 | cqr->magic, | 772 | cqr->magic, |
@@ -782,6 +786,7 @@ int dasd_term_IO(struct dasd_ccw_req *cqr) | |||
782 | { | 786 | { |
783 | struct dasd_device *device; | 787 | struct dasd_device *device; |
784 | int retries, rc; | 788 | int retries, rc; |
789 | char errorstring[ERRORLENGTH]; | ||
785 | 790 | ||
786 | /* Check the cqr */ | 791 | /* Check the cqr */ |
787 | rc = dasd_check_cqr(cqr); | 792 | rc = dasd_check_cqr(cqr); |
@@ -815,10 +820,10 @@ int dasd_term_IO(struct dasd_ccw_req *cqr) | |||
815 | "device busy, retry later"); | 820 | "device busy, retry later"); |
816 | break; | 821 | break; |
817 | default: | 822 | default: |
818 | DEV_MESSAGE(KERN_ERR, device, | 823 | /* internal error 10 - unknown rc*/ |
819 | "line %d unknown RC=%d, please " | 824 | snprintf(errorstring, ERRORLENGTH, "10 %d", rc); |
820 | "report to linux390@de.ibm.com", | 825 | dev_err(&device->cdev->dev, "An error occurred in the " |
821 | __LINE__, rc); | 826 | "DASD device driver, reason=%s\n", errorstring); |
822 | BUG(); | 827 | BUG(); |
823 | break; | 828 | break; |
824 | } | 829 | } |
@@ -836,6 +841,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
836 | { | 841 | { |
837 | struct dasd_device *device; | 842 | struct dasd_device *device; |
838 | int rc; | 843 | int rc; |
844 | char errorstring[ERRORLENGTH]; | ||
839 | 845 | ||
840 | /* Check the cqr */ | 846 | /* Check the cqr */ |
841 | rc = dasd_check_cqr(cqr); | 847 | rc = dasd_check_cqr(cqr); |
@@ -843,17 +849,23 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
843 | return rc; | 849 | return rc; |
844 | device = (struct dasd_device *) cqr->startdev; | 850 | device = (struct dasd_device *) cqr->startdev; |
845 | if (cqr->retries < 0) { | 851 | if (cqr->retries < 0) { |
846 | DEV_MESSAGE(KERN_DEBUG, device, | 852 | /* internal error 14 - start_IO run out of retries */ |
847 | "start_IO: request %p (%02x/%i) - no retry left.", | 853 | sprintf(errorstring, "14 %p", cqr); |
848 | cqr, cqr->status, cqr->retries); | 854 | dev_err(&device->cdev->dev, "An error occurred in the DASD " |
855 | "device driver, reason=%s\n", errorstring); | ||
849 | cqr->status = DASD_CQR_ERROR; | 856 | cqr->status = DASD_CQR_ERROR; |
850 | return -EIO; | 857 | return -EIO; |
851 | } | 858 | } |
852 | cqr->startclk = get_clock(); | 859 | cqr->startclk = get_clock(); |
853 | cqr->starttime = jiffies; | 860 | cqr->starttime = jiffies; |
854 | cqr->retries--; | 861 | cqr->retries--; |
855 | rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr, | 862 | if (cqr->cpmode == 1) { |
856 | cqr->lpm, 0); | 863 | rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, |
864 | (long) cqr, cqr->lpm); | ||
865 | } else { | ||
866 | rc = ccw_device_start(device->cdev, cqr->cpaddr, | ||
867 | (long) cqr, cqr->lpm, 0); | ||
868 | } | ||
857 | switch (rc) { | 869 | switch (rc) { |
858 | case 0: | 870 | case 0: |
859 | cqr->status = DASD_CQR_IN_IO; | 871 | cqr->status = DASD_CQR_IN_IO; |
@@ -862,11 +874,11 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
862 | cqr); | 874 | cqr); |
863 | break; | 875 | break; |
864 | case -EBUSY: | 876 | case -EBUSY: |
865 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | 877 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", |
866 | "start_IO: device busy, retry later"); | 878 | "start_IO: device busy, retry later"); |
867 | break; | 879 | break; |
868 | case -ETIMEDOUT: | 880 | case -ETIMEDOUT: |
869 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | 881 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", |
870 | "start_IO: request timeout, retry later"); | 882 | "start_IO: request timeout, retry later"); |
871 | break; | 883 | break; |
872 | case -EACCES: | 884 | case -EACCES: |
@@ -876,19 +888,24 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
876 | * Do a retry with all available pathes. | 888 | * Do a retry with all available pathes. |
877 | */ | 889 | */ |
878 | cqr->lpm = LPM_ANYPATH; | 890 | cqr->lpm = LPM_ANYPATH; |
879 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | 891 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", |
880 | "start_IO: selected pathes gone," | 892 | "start_IO: selected pathes gone," |
881 | " retry on all pathes"); | 893 | " retry on all pathes"); |
882 | break; | 894 | break; |
883 | case -ENODEV: | 895 | case -ENODEV: |
896 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", | ||
897 | "start_IO: -ENODEV device gone, retry"); | ||
898 | break; | ||
884 | case -EIO: | 899 | case -EIO: |
885 | DBF_DEV_EVENT(DBF_ERR, device, "%s", | 900 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", |
886 | "start_IO: device gone, retry"); | 901 | "start_IO: -EIO device gone, retry"); |
887 | break; | 902 | break; |
888 | default: | 903 | default: |
889 | DEV_MESSAGE(KERN_ERR, device, | 904 | /* internal error 11 - unknown rc */ |
890 | "line %d unknown RC=%d, please report" | 905 | snprintf(errorstring, ERRORLENGTH, "11 %d", rc); |
891 | " to linux390@de.ibm.com", __LINE__, rc); | 906 | dev_err(&device->cdev->dev, |
907 | "An error occurred in the DASD device driver, " | ||
908 | "reason=%s\n", errorstring); | ||
892 | BUG(); | 909 | BUG(); |
893 | break; | 910 | break; |
894 | } | 911 | } |
@@ -945,7 +962,7 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, | |||
945 | return; | 962 | return; |
946 | cqr = (struct dasd_ccw_req *) intparm; | 963 | cqr = (struct dasd_ccw_req *) intparm; |
947 | if (cqr->status != DASD_CQR_IN_IO) { | 964 | if (cqr->status != DASD_CQR_IN_IO) { |
948 | MESSAGE(KERN_DEBUG, | 965 | DBF_EVENT(DBF_DEBUG, |
949 | "invalid status in handle_killed_request: " | 966 | "invalid status in handle_killed_request: " |
950 | "bus_id %s, status %02x", | 967 | "bus_id %s, status %02x", |
951 | dev_name(&cdev->dev), cqr->status); | 968 | dev_name(&cdev->dev), cqr->status); |
@@ -956,8 +973,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, | |||
956 | if (device == NULL || | 973 | if (device == NULL || |
957 | device != dasd_device_from_cdev_locked(cdev) || | 974 | device != dasd_device_from_cdev_locked(cdev) || |
958 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { | 975 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { |
959 | MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", | 976 | DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " |
960 | dev_name(&cdev->dev)); | 977 | "bus_id %s", dev_name(&cdev->dev)); |
961 | return; | 978 | return; |
962 | } | 979 | } |
963 | 980 | ||
@@ -996,11 +1013,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
996 | case -EIO: | 1013 | case -EIO: |
997 | break; | 1014 | break; |
998 | case -ETIMEDOUT: | 1015 | case -ETIMEDOUT: |
999 | printk(KERN_WARNING"%s(%s): request timed out\n", | 1016 | DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n", |
1000 | __func__, dev_name(&cdev->dev)); | 1017 | __func__, dev_name(&cdev->dev)); |
1001 | break; | 1018 | break; |
1002 | default: | 1019 | default: |
1003 | printk(KERN_WARNING"%s(%s): unknown error %ld\n", | 1020 | DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n", |
1004 | __func__, dev_name(&cdev->dev), PTR_ERR(irb)); | 1021 | __func__, dev_name(&cdev->dev), PTR_ERR(irb)); |
1005 | } | 1022 | } |
1006 | dasd_handle_killed_request(cdev, intparm); | 1023 | dasd_handle_killed_request(cdev, intparm); |
@@ -1009,15 +1026,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1009 | 1026 | ||
1010 | now = get_clock(); | 1027 | now = get_clock(); |
1011 | 1028 | ||
1012 | DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x", | ||
1013 | dev_name(&cdev->dev), ((irb->scsw.cmd.cstat << 8) | | ||
1014 | irb->scsw.cmd.dstat), (unsigned int) intparm); | ||
1015 | |||
1016 | /* check for unsolicited interrupts */ | 1029 | /* check for unsolicited interrupts */ |
1017 | cqr = (struct dasd_ccw_req *) intparm; | 1030 | cqr = (struct dasd_ccw_req *) intparm; |
1018 | if (!cqr || ((irb->scsw.cmd.cc == 1) && | 1031 | if (!cqr || ((scsw_cc(&irb->scsw) == 1) && |
1019 | (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && | 1032 | (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && |
1020 | (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND))) { | 1033 | (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) { |
1021 | if (cqr && cqr->status == DASD_CQR_IN_IO) | 1034 | if (cqr && cqr->status == DASD_CQR_IN_IO) |
1022 | cqr->status = DASD_CQR_QUEUED; | 1035 | cqr->status = DASD_CQR_QUEUED; |
1023 | device = dasd_device_from_cdev_locked(cdev); | 1036 | device = dasd_device_from_cdev_locked(cdev); |
@@ -1033,14 +1046,14 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1033 | device = (struct dasd_device *) cqr->startdev; | 1046 | device = (struct dasd_device *) cqr->startdev; |
1034 | if (!device || | 1047 | if (!device || |
1035 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { | 1048 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { |
1036 | MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", | 1049 | DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " |
1037 | dev_name(&cdev->dev)); | 1050 | "bus_id %s", dev_name(&cdev->dev)); |
1038 | return; | 1051 | return; |
1039 | } | 1052 | } |
1040 | 1053 | ||
1041 | /* Check for clear pending */ | 1054 | /* Check for clear pending */ |
1042 | if (cqr->status == DASD_CQR_CLEAR_PENDING && | 1055 | if (cqr->status == DASD_CQR_CLEAR_PENDING && |
1043 | irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) { | 1056 | scsw_fctl(&irb->scsw) & SCSW_FCTL_CLEAR_FUNC) { |
1044 | cqr->status = DASD_CQR_CLEARED; | 1057 | cqr->status = DASD_CQR_CLEARED; |
1045 | dasd_device_clear_timer(device); | 1058 | dasd_device_clear_timer(device); |
1046 | wake_up(&dasd_flush_wq); | 1059 | wake_up(&dasd_flush_wq); |
@@ -1048,19 +1061,17 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1048 | return; | 1061 | return; |
1049 | } | 1062 | } |
1050 | 1063 | ||
1051 | /* check status - the request might have been killed by dyn detach */ | 1064 | /* check status - the request might have been killed by dyn detach */ |
1052 | if (cqr->status != DASD_CQR_IN_IO) { | 1065 | if (cqr->status != DASD_CQR_IN_IO) { |
1053 | MESSAGE(KERN_DEBUG, | 1066 | DBF_DEV_EVENT(DBF_DEBUG, device, "invalid status: bus_id %s, " |
1054 | "invalid status: bus_id %s, status %02x", | 1067 | "status %02x", dev_name(&cdev->dev), cqr->status); |
1055 | dev_name(&cdev->dev), cqr->status); | ||
1056 | return; | 1068 | return; |
1057 | } | 1069 | } |
1058 | DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p", | 1070 | |
1059 | ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), cqr); | ||
1060 | next = NULL; | 1071 | next = NULL; |
1061 | expires = 0; | 1072 | expires = 0; |
1062 | if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && | 1073 | if (scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && |
1063 | irb->scsw.cmd.cstat == 0 && !irb->esw.esw0.erw.cons) { | 1074 | scsw_cstat(&irb->scsw) == 0) { |
1064 | /* request was completed successfully */ | 1075 | /* request was completed successfully */ |
1065 | cqr->status = DASD_CQR_SUCCESS; | 1076 | cqr->status = DASD_CQR_SUCCESS; |
1066 | cqr->stopclk = now; | 1077 | cqr->stopclk = now; |
@@ -1071,18 +1082,23 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1071 | } | 1082 | } |
1072 | } else { /* error */ | 1083 | } else { /* error */ |
1073 | memcpy(&cqr->irb, irb, sizeof(struct irb)); | 1084 | memcpy(&cqr->irb, irb, sizeof(struct irb)); |
1085 | /* log sense for every failed I/O to s390 debugfeature */ | ||
1086 | dasd_log_sense_dbf(cqr, irb); | ||
1074 | if (device->features & DASD_FEATURE_ERPLOG) { | 1087 | if (device->features & DASD_FEATURE_ERPLOG) { |
1075 | dasd_log_sense(cqr, irb); | 1088 | dasd_log_sense(cqr, irb); |
1076 | } | 1089 | } |
1090 | |||
1077 | /* | 1091 | /* |
1078 | * If we don't want complex ERP for this request, then just | 1092 | * If we don't want complex ERP for this request, then just |
1079 | * reset this and retry it in the fastpath | 1093 | * reset this and retry it in the fastpath |
1080 | */ | 1094 | */ |
1081 | if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && | 1095 | if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && |
1082 | cqr->retries > 0) { | 1096 | cqr->retries > 0) { |
1083 | DEV_MESSAGE(KERN_DEBUG, device, | 1097 | if (cqr->lpm == LPM_ANYPATH) |
1084 | "default ERP in fastpath (%i retries left)", | 1098 | DBF_DEV_EVENT(DBF_DEBUG, device, |
1085 | cqr->retries); | 1099 | "default ERP in fastpath " |
1100 | "(%i retries left)", | ||
1101 | cqr->retries); | ||
1086 | cqr->lpm = LPM_ANYPATH; | 1102 | cqr->lpm = LPM_ANYPATH; |
1087 | cqr->status = DASD_CQR_QUEUED; | 1103 | cqr->status = DASD_CQR_QUEUED; |
1088 | next = cqr; | 1104 | next = cqr; |
@@ -1093,10 +1109,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1093 | (!device->stopped)) { | 1109 | (!device->stopped)) { |
1094 | if (device->discipline->start_IO(next) == 0) | 1110 | if (device->discipline->start_IO(next) == 0) |
1095 | expires = next->expires; | 1111 | expires = next->expires; |
1096 | else | ||
1097 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | ||
1098 | "Interrupt fastpath " | ||
1099 | "failed!"); | ||
1100 | } | 1112 | } |
1101 | if (expires != 0) | 1113 | if (expires != 0) |
1102 | dasd_device_set_timer(device, expires); | 1114 | dasd_device_set_timer(device, expires); |
@@ -1169,6 +1181,7 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, | |||
1169 | struct dasd_block *block; | 1181 | struct dasd_block *block; |
1170 | void (*callback)(struct dasd_ccw_req *, void *data); | 1182 | void (*callback)(struct dasd_ccw_req *, void *data); |
1171 | void *callback_data; | 1183 | void *callback_data; |
1184 | char errorstring[ERRORLENGTH]; | ||
1172 | 1185 | ||
1173 | list_for_each_safe(l, n, final_queue) { | 1186 | list_for_each_safe(l, n, final_queue) { |
1174 | cqr = list_entry(l, struct dasd_ccw_req, devlist); | 1187 | cqr = list_entry(l, struct dasd_ccw_req, devlist); |
@@ -1189,10 +1202,11 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, | |||
1189 | cqr->status = DASD_CQR_TERMINATED; | 1202 | cqr->status = DASD_CQR_TERMINATED; |
1190 | break; | 1203 | break; |
1191 | default: | 1204 | default: |
1192 | DEV_MESSAGE(KERN_ERR, device, | 1205 | /* internal error 12 - wrong cqr status*/ |
1193 | "wrong cqr status in __dasd_process_final_queue " | 1206 | snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status); |
1194 | "for cqr %p, status %x", | 1207 | dev_err(&device->cdev->dev, |
1195 | cqr, cqr->status); | 1208 | "An error occurred in the DASD device driver, " |
1209 | "reason=%s\n", errorstring); | ||
1196 | BUG(); | 1210 | BUG(); |
1197 | } | 1211 | } |
1198 | if (cqr->callback != NULL) | 1212 | if (cqr->callback != NULL) |
@@ -1217,18 +1231,17 @@ static void __dasd_device_check_expire(struct dasd_device *device) | |||
1217 | (time_after_eq(jiffies, cqr->expires + cqr->starttime))) { | 1231 | (time_after_eq(jiffies, cqr->expires + cqr->starttime))) { |
1218 | if (device->discipline->term_IO(cqr) != 0) { | 1232 | if (device->discipline->term_IO(cqr) != 0) { |
1219 | /* Hmpf, try again in 5 sec */ | 1233 | /* Hmpf, try again in 5 sec */ |
1220 | DEV_MESSAGE(KERN_ERR, device, | 1234 | dev_err(&device->cdev->dev, |
1221 | "internal error - timeout (%is) expired " | 1235 | "cqr %p timed out (%is) but cannot be " |
1222 | "for cqr %p, termination failed, " | 1236 | "ended, retrying in 5 s\n", |
1223 | "retrying in 5s", | 1237 | cqr, (cqr->expires/HZ)); |
1224 | (cqr->expires/HZ), cqr); | ||
1225 | cqr->expires += 5*HZ; | 1238 | cqr->expires += 5*HZ; |
1226 | dasd_device_set_timer(device, 5*HZ); | 1239 | dasd_device_set_timer(device, 5*HZ); |
1227 | } else { | 1240 | } else { |
1228 | DEV_MESSAGE(KERN_ERR, device, | 1241 | dev_err(&device->cdev->dev, |
1229 | "internal error - timeout (%is) expired " | 1242 | "cqr %p timed out (%is), %i retries " |
1230 | "for cqr %p (%i retries left)", | 1243 | "remaining\n", cqr, (cqr->expires/HZ), |
1231 | (cqr->expires/HZ), cqr, cqr->retries); | 1244 | cqr->retries); |
1232 | } | 1245 | } |
1233 | } | 1246 | } |
1234 | } | 1247 | } |
@@ -1290,10 +1303,9 @@ int dasd_flush_device_queue(struct dasd_device *device) | |||
1290 | rc = device->discipline->term_IO(cqr); | 1303 | rc = device->discipline->term_IO(cqr); |
1291 | if (rc) { | 1304 | if (rc) { |
1292 | /* unable to terminate requeust */ | 1305 | /* unable to terminate requeust */ |
1293 | DEV_MESSAGE(KERN_ERR, device, | 1306 | dev_err(&device->cdev->dev, |
1294 | "dasd flush ccw_queue is unable " | 1307 | "Flushing the DASD request queue " |
1295 | " to terminate request %p", | 1308 | "failed for request %p\n", cqr); |
1296 | cqr); | ||
1297 | /* stop flush processing */ | 1309 | /* stop flush processing */ |
1298 | goto finished; | 1310 | goto finished; |
1299 | } | 1311 | } |
@@ -1537,10 +1549,9 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr) | |||
1537 | /* request in IO - terminate IO and release again */ | 1549 | /* request in IO - terminate IO and release again */ |
1538 | rc = device->discipline->term_IO(cqr); | 1550 | rc = device->discipline->term_IO(cqr); |
1539 | if (rc) { | 1551 | if (rc) { |
1540 | DEV_MESSAGE(KERN_ERR, device, | 1552 | dev_err(&device->cdev->dev, |
1541 | "dasd_cancel_req is unable " | 1553 | "Cancelling request %p failed with rc=%d\n", |
1542 | " to terminate request %p, rc = %d", | 1554 | cqr, rc); |
1543 | cqr, rc); | ||
1544 | } else { | 1555 | } else { |
1545 | cqr->stopclk = get_clock(); | 1556 | cqr->stopclk = get_clock(); |
1546 | rc = 1; | 1557 | rc = 1; |
@@ -1617,7 +1628,7 @@ static inline void __dasd_block_process_erp(struct dasd_block *block, | |||
1617 | if (cqr->status == DASD_CQR_DONE) | 1628 | if (cqr->status == DASD_CQR_DONE) |
1618 | DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful"); | 1629 | DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful"); |
1619 | else | 1630 | else |
1620 | DEV_MESSAGE(KERN_ERR, device, "%s", "ERP unsuccessful"); | 1631 | dev_err(&device->cdev->dev, "ERP failed for the DASD\n"); |
1621 | erp_fn = device->discipline->erp_postaction(cqr); | 1632 | erp_fn = device->discipline->erp_postaction(cqr); |
1622 | erp_fn(cqr); | 1633 | erp_fn(cqr); |
1623 | } | 1634 | } |
@@ -1991,8 +2002,11 @@ static void dasd_setup_queue(struct dasd_block *block) | |||
1991 | blk_queue_max_sectors(block->request_queue, max); | 2002 | blk_queue_max_sectors(block->request_queue, max); |
1992 | blk_queue_max_phys_segments(block->request_queue, -1L); | 2003 | blk_queue_max_phys_segments(block->request_queue, -1L); |
1993 | blk_queue_max_hw_segments(block->request_queue, -1L); | 2004 | blk_queue_max_hw_segments(block->request_queue, -1L); |
1994 | blk_queue_max_segment_size(block->request_queue, -1L); | 2005 | /* with page sized segments we can translate each segement into |
1995 | blk_queue_segment_boundary(block->request_queue, -1L); | 2006 | * one idaw/tidaw |
2007 | */ | ||
2008 | blk_queue_max_segment_size(block->request_queue, PAGE_SIZE); | ||
2009 | blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1); | ||
1996 | blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN, NULL); | 2010 | blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN, NULL); |
1997 | } | 2011 | } |
1998 | 2012 | ||
@@ -2043,8 +2057,9 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) | |||
2043 | } | 2057 | } |
2044 | 2058 | ||
2045 | if (dasd_probeonly) { | 2059 | if (dasd_probeonly) { |
2046 | DEV_MESSAGE(KERN_INFO, base, "%s", | 2060 | dev_info(&base->cdev->dev, |
2047 | "No access to device due to probeonly mode"); | 2061 | "Accessing the DASD failed because it is in " |
2062 | "probeonly mode\n"); | ||
2048 | rc = -EPERM; | 2063 | rc = -EPERM; |
2049 | goto out; | 2064 | goto out; |
2050 | } | 2065 | } |
@@ -2101,7 +2116,8 @@ dasd_device_operations = { | |||
2101 | .owner = THIS_MODULE, | 2116 | .owner = THIS_MODULE, |
2102 | .open = dasd_open, | 2117 | .open = dasd_open, |
2103 | .release = dasd_release, | 2118 | .release = dasd_release, |
2104 | .locked_ioctl = dasd_ioctl, | 2119 | .ioctl = dasd_ioctl, |
2120 | .compat_ioctl = dasd_ioctl, | ||
2105 | .getgeo = dasd_getgeo, | 2121 | .getgeo = dasd_getgeo, |
2106 | }; | 2122 | }; |
2107 | 2123 | ||
@@ -2143,14 +2159,14 @@ int dasd_generic_probe(struct ccw_device *cdev, | |||
2143 | 2159 | ||
2144 | ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); | 2160 | ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); |
2145 | if (ret) { | 2161 | if (ret) { |
2146 | printk(KERN_WARNING | 2162 | DBF_EVENT(DBF_WARNING, |
2147 | "dasd_generic_probe: could not set ccw-device options " | 2163 | "dasd_generic_probe: could not set ccw-device options " |
2148 | "for %s\n", dev_name(&cdev->dev)); | 2164 | "for %s\n", dev_name(&cdev->dev)); |
2149 | return ret; | 2165 | return ret; |
2150 | } | 2166 | } |
2151 | ret = dasd_add_sysfs_files(cdev); | 2167 | ret = dasd_add_sysfs_files(cdev); |
2152 | if (ret) { | 2168 | if (ret) { |
2153 | printk(KERN_WARNING | 2169 | DBF_EVENT(DBF_WARNING, |
2154 | "dasd_generic_probe: could not add sysfs entries " | 2170 | "dasd_generic_probe: could not add sysfs entries " |
2155 | "for %s\n", dev_name(&cdev->dev)); | 2171 | "for %s\n", dev_name(&cdev->dev)); |
2156 | return ret; | 2172 | return ret; |
@@ -2166,9 +2182,7 @@ int dasd_generic_probe(struct ccw_device *cdev, | |||
2166 | (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) | 2182 | (dasd_autodetect && dasd_busid_known(dev_name(&cdev->dev)) != 0)) |
2167 | ret = ccw_device_set_online(cdev); | 2183 | ret = ccw_device_set_online(cdev); |
2168 | if (ret) | 2184 | if (ret) |
2169 | printk(KERN_WARNING | 2185 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", |
2170 | "dasd_generic_probe: could not initially " | ||
2171 | "online ccw-device %s; return code: %d\n", | ||
2172 | dev_name(&cdev->dev), ret); | 2186 | dev_name(&cdev->dev), ret); |
2173 | return 0; | 2187 | return 0; |
2174 | } | 2188 | } |
@@ -2232,10 +2246,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
2232 | discipline = base_discipline; | 2246 | discipline = base_discipline; |
2233 | if (device->features & DASD_FEATURE_USEDIAG) { | 2247 | if (device->features & DASD_FEATURE_USEDIAG) { |
2234 | if (!dasd_diag_discipline_pointer) { | 2248 | if (!dasd_diag_discipline_pointer) { |
2235 | printk (KERN_WARNING | 2249 | pr_warning("%s Setting the DASD online failed because " |
2236 | "dasd_generic couldn't online device %s " | 2250 | "of missing DIAG discipline\n", |
2237 | "- discipline DIAG not available\n", | 2251 | dev_name(&cdev->dev)); |
2238 | dev_name(&cdev->dev)); | ||
2239 | dasd_delete_device(device); | 2252 | dasd_delete_device(device); |
2240 | return -ENODEV; | 2253 | return -ENODEV; |
2241 | } | 2254 | } |
@@ -2256,10 +2269,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
2256 | /* check_device will allocate block device if necessary */ | 2269 | /* check_device will allocate block device if necessary */ |
2257 | rc = discipline->check_device(device); | 2270 | rc = discipline->check_device(device); |
2258 | if (rc) { | 2271 | if (rc) { |
2259 | printk (KERN_WARNING | 2272 | pr_warning("%s Setting the DASD online with discipline %s " |
2260 | "dasd_generic couldn't online device %s " | 2273 | "failed with rc=%i\n", |
2261 | "with discipline %s rc=%i\n", | 2274 | dev_name(&cdev->dev), discipline->name, rc); |
2262 | dev_name(&cdev->dev), discipline->name, rc); | ||
2263 | module_put(discipline->owner); | 2275 | module_put(discipline->owner); |
2264 | module_put(base_discipline->owner); | 2276 | module_put(base_discipline->owner); |
2265 | dasd_delete_device(device); | 2277 | dasd_delete_device(device); |
@@ -2268,9 +2280,8 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
2268 | 2280 | ||
2269 | dasd_set_target_state(device, DASD_STATE_ONLINE); | 2281 | dasd_set_target_state(device, DASD_STATE_ONLINE); |
2270 | if (device->state <= DASD_STATE_KNOWN) { | 2282 | if (device->state <= DASD_STATE_KNOWN) { |
2271 | printk (KERN_WARNING | 2283 | pr_warning("%s Setting the DASD online failed because of a " |
2272 | "dasd_generic discipline not found for %s\n", | 2284 | "missing discipline\n", dev_name(&cdev->dev)); |
2273 | dev_name(&cdev->dev)); | ||
2274 | rc = -ENODEV; | 2285 | rc = -ENODEV; |
2275 | dasd_set_target_state(device, DASD_STATE_NEW); | 2286 | dasd_set_target_state(device, DASD_STATE_NEW); |
2276 | if (device->block) | 2287 | if (device->block) |
@@ -2314,13 +2325,13 @@ int dasd_generic_set_offline(struct ccw_device *cdev) | |||
2314 | open_count = atomic_read(&device->block->open_count); | 2325 | open_count = atomic_read(&device->block->open_count); |
2315 | if (open_count > max_count) { | 2326 | if (open_count > max_count) { |
2316 | if (open_count > 0) | 2327 | if (open_count > 0) |
2317 | printk(KERN_WARNING "Can't offline dasd " | 2328 | pr_warning("%s: The DASD cannot be set offline " |
2318 | "device with open count = %i.\n", | 2329 | "with open count %i\n", |
2319 | open_count); | 2330 | dev_name(&cdev->dev), open_count); |
2320 | else | 2331 | else |
2321 | printk(KERN_WARNING "%s", | 2332 | pr_warning("%s: The DASD cannot be set offline " |
2322 | "Can't offline dasd device due " | 2333 | "while it is in use\n", |
2323 | "to internal use\n"); | 2334 | dev_name(&cdev->dev)); |
2324 | clear_bit(DASD_FLAG_OFFLINE, &device->flags); | 2335 | clear_bit(DASD_FLAG_OFFLINE, &device->flags); |
2325 | dasd_put_device(device); | 2336 | dasd_put_device(device); |
2326 | return -EBUSY; | 2337 | return -EBUSY; |
@@ -2393,8 +2404,10 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, | |||
2393 | cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device); | 2404 | cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device); |
2394 | 2405 | ||
2395 | if (IS_ERR(cqr)) { | 2406 | if (IS_ERR(cqr)) { |
2396 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 2407 | /* internal error 13 - Allocating the RDC request failed*/ |
2397 | "Could not allocate RDC request"); | 2408 | dev_err(&device->cdev->dev, |
2409 | "An error occurred in the DASD device driver, " | ||
2410 | "reason=%s\n", "13"); | ||
2398 | return cqr; | 2411 | return cqr; |
2399 | } | 2412 | } |
2400 | 2413 | ||
@@ -2431,6 +2444,40 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, | |||
2431 | } | 2444 | } |
2432 | EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars); | 2445 | EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars); |
2433 | 2446 | ||
2447 | /* | ||
2448 | * In command mode and transport mode we need to look for sense | ||
2449 | * data in different places. The sense data itself is allways | ||
2450 | * an array of 32 bytes, so we can unify the sense data access | ||
2451 | * for both modes. | ||
2452 | */ | ||
2453 | char *dasd_get_sense(struct irb *irb) | ||
2454 | { | ||
2455 | struct tsb *tsb = NULL; | ||
2456 | char *sense = NULL; | ||
2457 | |||
2458 | if (scsw_is_tm(&irb->scsw) && (irb->scsw.tm.fcxs == 0x01)) { | ||
2459 | if (irb->scsw.tm.tcw) | ||
2460 | tsb = tcw_get_tsb((struct tcw *)(unsigned long) | ||
2461 | irb->scsw.tm.tcw); | ||
2462 | if (tsb && tsb->length == 64 && tsb->flags) | ||
2463 | switch (tsb->flags & 0x07) { | ||
2464 | case 1: /* tsa_iostat */ | ||
2465 | sense = tsb->tsa.iostat.sense; | ||
2466 | break; | ||
2467 | case 2: /* tsa_ddpc */ | ||
2468 | sense = tsb->tsa.ddpc.sense; | ||
2469 | break; | ||
2470 | default: | ||
2471 | /* currently we don't use interrogate data */ | ||
2472 | break; | ||
2473 | } | ||
2474 | } else if (irb->esw.esw0.erw.cons) { | ||
2475 | sense = irb->ecw; | ||
2476 | } | ||
2477 | return sense; | ||
2478 | } | ||
2479 | EXPORT_SYMBOL_GPL(dasd_get_sense); | ||
2480 | |||
2434 | static int __init dasd_init(void) | 2481 | static int __init dasd_init(void) |
2435 | { | 2482 | { |
2436 | int rc; | 2483 | int rc; |
@@ -2472,7 +2519,7 @@ static int __init dasd_init(void) | |||
2472 | 2519 | ||
2473 | return 0; | 2520 | return 0; |
2474 | failed: | 2521 | failed: |
2475 | MESSAGE(KERN_INFO, "%s", "initialization not performed due to errors"); | 2522 | pr_info("The DASD device driver could not be initialized\n"); |
2476 | dasd_exit(); | 2523 | dasd_exit(); |
2477 | return rc; | 2524 | return rc; |
2478 | } | 2525 | } |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index d82aad5224f0..27991b692056 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -7,6 +7,8 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #define KMSG_COMPONENT "dasd" | ||
11 | |||
10 | #include <linux/timer.h> | 12 | #include <linux/timer.h> |
11 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
12 | #include <asm/idals.h> | 14 | #include <asm/idals.h> |
@@ -75,7 +77,7 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) | |||
75 | struct dasd_device *device = erp->startdev; | 77 | struct dasd_device *device = erp->startdev; |
76 | unsigned long flags; | 78 | unsigned long flags; |
77 | 79 | ||
78 | DEV_MESSAGE(KERN_INFO, device, | 80 | DBF_DEV_EVENT(DBF_INFO, device, |
79 | "blocking request queue for %is", expires/HZ); | 81 | "blocking request queue for %is", expires/HZ); |
80 | 82 | ||
81 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 83 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
@@ -114,9 +116,9 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp) | |||
114 | } else { | 116 | } else { |
115 | 117 | ||
116 | /* issue a message and wait for 'device ready' interrupt */ | 118 | /* issue a message and wait for 'device ready' interrupt */ |
117 | DEV_MESSAGE(KERN_ERR, device, "%s", | 119 | dev_err(&device->cdev->dev, |
118 | "is offline or not installed - " | 120 | "is offline or not installed - " |
119 | "INTERVENTION REQUIRED!!"); | 121 | "INTERVENTION REQUIRED!!\n"); |
120 | 122 | ||
121 | dasd_3990_erp_block_queue(erp, 60*HZ); | 123 | dasd_3990_erp_block_queue(erp, 60*HZ); |
122 | } | 124 | } |
@@ -158,7 +160,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | |||
158 | 160 | ||
159 | if ((erp->lpm & opm) != 0x00) { | 161 | if ((erp->lpm & opm) != 0x00) { |
160 | 162 | ||
161 | DEV_MESSAGE(KERN_DEBUG, device, | 163 | DBF_DEV_EVENT(DBF_WARNING, device, |
162 | "try alternate lpm=%x (lpum=%x / opm=%x)", | 164 | "try alternate lpm=%x (lpum=%x / opm=%x)", |
163 | erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm); | 165 | erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm); |
164 | 166 | ||
@@ -166,10 +168,9 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | |||
166 | erp->status = DASD_CQR_FILLED; | 168 | erp->status = DASD_CQR_FILLED; |
167 | erp->retries = 10; | 169 | erp->retries = 10; |
168 | } else { | 170 | } else { |
169 | DEV_MESSAGE(KERN_ERR, device, | 171 | dev_err(&device->cdev->dev, |
170 | "No alternate channel path left (lpum=%x / " | 172 | "The DASD cannot be reached on any path (lpum=%x" |
171 | "opm=%x) -> permanent error", | 173 | "/opm=%x)\n", erp->irb.esw.esw0.sublog.lpum, opm); |
172 | erp->irb.esw.esw0.sublog.lpum, opm); | ||
173 | 174 | ||
174 | /* post request with permanent error */ | 175 | /* post request with permanent error */ |
175 | erp->status = DASD_CQR_FAILED; | 176 | erp->status = DASD_CQR_FAILED; |
@@ -204,8 +205,8 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) | |||
204 | sizeof(struct DCTL_data), | 205 | sizeof(struct DCTL_data), |
205 | device); | 206 | device); |
206 | if (IS_ERR(dctl_cqr)) { | 207 | if (IS_ERR(dctl_cqr)) { |
207 | DEV_MESSAGE(KERN_ERR, device, "%s", | 208 | dev_err(&device->cdev->dev, |
208 | "Unable to allocate DCTL-CQR"); | 209 | "Unable to allocate DCTL-CQR\n"); |
209 | erp->status = DASD_CQR_FAILED; | 210 | erp->status = DASD_CQR_FAILED; |
210 | return erp; | 211 | return erp; |
211 | } | 212 | } |
@@ -294,7 +295,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
294 | /* interrupt (this enables easier enqueing of the cqr) */ | 295 | /* interrupt (this enables easier enqueing of the cqr) */ |
295 | if (erp->function != dasd_3990_erp_action_4) { | 296 | if (erp->function != dasd_3990_erp_action_4) { |
296 | 297 | ||
297 | DEV_MESSAGE(KERN_INFO, device, "%s", | 298 | DBF_DEV_EVENT(DBF_INFO, device, "%s", |
298 | "dasd_3990_erp_action_4: first time retry"); | 299 | "dasd_3990_erp_action_4: first time retry"); |
299 | 300 | ||
300 | erp->retries = 256; | 301 | erp->retries = 256; |
@@ -303,7 +304,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
303 | } else { | 304 | } else { |
304 | if (sense && (sense[25] == 0x1D)) { /* state change pending */ | 305 | if (sense && (sense[25] == 0x1D)) { /* state change pending */ |
305 | 306 | ||
306 | DEV_MESSAGE(KERN_INFO, device, | 307 | DBF_DEV_EVENT(DBF_INFO, device, |
307 | "waiting for state change pending " | 308 | "waiting for state change pending " |
308 | "interrupt, %d retries left", | 309 | "interrupt, %d retries left", |
309 | erp->retries); | 310 | erp->retries); |
@@ -311,15 +312,14 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
311 | dasd_3990_erp_block_queue(erp, 30*HZ); | 312 | dasd_3990_erp_block_queue(erp, 30*HZ); |
312 | 313 | ||
313 | } else if (sense && (sense[25] == 0x1E)) { /* busy */ | 314 | } else if (sense && (sense[25] == 0x1E)) { /* busy */ |
314 | DEV_MESSAGE(KERN_INFO, device, | 315 | DBF_DEV_EVENT(DBF_INFO, device, |
315 | "busy - redriving request later, " | 316 | "busy - redriving request later, " |
316 | "%d retries left", | 317 | "%d retries left", |
317 | erp->retries); | 318 | erp->retries); |
318 | dasd_3990_erp_block_queue(erp, HZ); | 319 | dasd_3990_erp_block_queue(erp, HZ); |
319 | } else { | 320 | } else { |
320 | |||
321 | /* no state change pending - retry */ | 321 | /* no state change pending - retry */ |
322 | DEV_MESSAGE (KERN_INFO, device, | 322 | DBF_DEV_EVENT(DBF_INFO, device, |
323 | "redriving request immediately, " | 323 | "redriving request immediately, " |
324 | "%d retries left", | 324 | "%d retries left", |
325 | erp->retries); | 325 | erp->retries); |
@@ -384,6 +384,7 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
384 | struct dasd_device *device = erp->startdev; | 384 | struct dasd_device *device = erp->startdev; |
385 | char msg_format = (sense[7] & 0xF0); | 385 | char msg_format = (sense[7] & 0xF0); |
386 | char msg_no = (sense[7] & 0x0F); | 386 | char msg_no = (sense[7] & 0x0F); |
387 | char errorstring[ERRORLENGTH]; | ||
387 | 388 | ||
388 | switch (msg_format) { | 389 | switch (msg_format) { |
389 | case 0x00: /* Format 0 - Program or System Checks */ | 390 | case 0x00: /* Format 0 - Program or System Checks */ |
@@ -394,95 +395,97 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
394 | case 0x00: /* No Message */ | 395 | case 0x00: /* No Message */ |
395 | break; | 396 | break; |
396 | case 0x01: | 397 | case 0x01: |
397 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 398 | dev_warn(&device->cdev->dev, |
398 | "FORMAT 0 - Invalid Command"); | 399 | "FORMAT 0 - Invalid Command\n"); |
399 | break; | 400 | break; |
400 | case 0x02: | 401 | case 0x02: |
401 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 402 | dev_warn(&device->cdev->dev, |
402 | "FORMAT 0 - Invalid Command " | 403 | "FORMAT 0 - Invalid Command " |
403 | "Sequence"); | 404 | "Sequence\n"); |
404 | break; | 405 | break; |
405 | case 0x03: | 406 | case 0x03: |
406 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 407 | dev_warn(&device->cdev->dev, |
407 | "FORMAT 0 - CCW Count less than " | 408 | "FORMAT 0 - CCW Count less than " |
408 | "required"); | 409 | "required\n"); |
409 | break; | 410 | break; |
410 | case 0x04: | 411 | case 0x04: |
411 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 412 | dev_warn(&device->cdev->dev, |
412 | "FORMAT 0 - Invalid Parameter"); | 413 | "FORMAT 0 - Invalid Parameter\n"); |
413 | break; | 414 | break; |
414 | case 0x05: | 415 | case 0x05: |
415 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 416 | dev_warn(&device->cdev->dev, |
416 | "FORMAT 0 - Diagnostic of Sepecial" | 417 | "FORMAT 0 - Diagnostic of Special" |
417 | " Command Violates File Mask"); | 418 | " Command Violates File Mask\n"); |
418 | break; | 419 | break; |
419 | case 0x07: | 420 | case 0x07: |
420 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 421 | dev_warn(&device->cdev->dev, |
421 | "FORMAT 0 - Channel Returned with " | 422 | "FORMAT 0 - Channel Returned with " |
422 | "Incorrect retry CCW"); | 423 | "Incorrect retry CCW\n"); |
423 | break; | 424 | break; |
424 | case 0x08: | 425 | case 0x08: |
425 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 426 | dev_warn(&device->cdev->dev, |
426 | "FORMAT 0 - Reset Notification"); | 427 | "FORMAT 0 - Reset Notification\n"); |
427 | break; | 428 | break; |
428 | case 0x09: | 429 | case 0x09: |
429 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 430 | dev_warn(&device->cdev->dev, |
430 | "FORMAT 0 - Storage Path Restart"); | 431 | "FORMAT 0 - Storage Path Restart\n"); |
431 | break; | 432 | break; |
432 | case 0x0A: | 433 | case 0x0A: |
433 | DEV_MESSAGE(KERN_WARNING, device, | 434 | dev_warn(&device->cdev->dev, |
434 | "FORMAT 0 - Channel requested " | 435 | "FORMAT 0 - Channel requested " |
435 | "... %02x", sense[8]); | 436 | "... %02x\n", sense[8]); |
436 | break; | 437 | break; |
437 | case 0x0B: | 438 | case 0x0B: |
438 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 439 | dev_warn(&device->cdev->dev, |
439 | "FORMAT 0 - Invalid Defective/" | 440 | "FORMAT 0 - Invalid Defective/" |
440 | "Alternate Track Pointer"); | 441 | "Alternate Track Pointer\n"); |
441 | break; | 442 | break; |
442 | case 0x0C: | 443 | case 0x0C: |
443 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 444 | dev_warn(&device->cdev->dev, |
444 | "FORMAT 0 - DPS Installation " | 445 | "FORMAT 0 - DPS Installation " |
445 | "Check"); | 446 | "Check\n"); |
446 | break; | 447 | break; |
447 | case 0x0E: | 448 | case 0x0E: |
448 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 449 | dev_warn(&device->cdev->dev, |
449 | "FORMAT 0 - Command Invalid on " | 450 | "FORMAT 0 - Command Invalid on " |
450 | "Secondary Address"); | 451 | "Secondary Address\n"); |
451 | break; | 452 | break; |
452 | case 0x0F: | 453 | case 0x0F: |
453 | DEV_MESSAGE(KERN_WARNING, device, | 454 | dev_warn(&device->cdev->dev, |
454 | "FORMAT 0 - Status Not As " | 455 | "FORMAT 0 - Status Not As " |
455 | "Required: reason %02x", sense[8]); | 456 | "Required: reason %02x\n", |
457 | sense[8]); | ||
456 | break; | 458 | break; |
457 | default: | 459 | default: |
458 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 460 | dev_warn(&device->cdev->dev, |
459 | "FORMAT 0 - Reseved"); | 461 | "FORMAT 0 - Reserved\n"); |
460 | } | 462 | } |
461 | } else { | 463 | } else { |
462 | switch (msg_no) { | 464 | switch (msg_no) { |
463 | case 0x00: /* No Message */ | 465 | case 0x00: /* No Message */ |
464 | break; | 466 | break; |
465 | case 0x01: | 467 | case 0x01: |
466 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 468 | dev_warn(&device->cdev->dev, |
467 | "FORMAT 0 - Device Error Source"); | 469 | "FORMAT 0 - Device Error " |
470 | "Source\n"); | ||
468 | break; | 471 | break; |
469 | case 0x02: | 472 | case 0x02: |
470 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 473 | dev_warn(&device->cdev->dev, |
471 | "FORMAT 0 - Reserved"); | 474 | "FORMAT 0 - Reserved\n"); |
472 | break; | 475 | break; |
473 | case 0x03: | 476 | case 0x03: |
474 | DEV_MESSAGE(KERN_WARNING, device, | 477 | dev_warn(&device->cdev->dev, |
475 | "FORMAT 0 - Device Fenced - " | 478 | "FORMAT 0 - Device Fenced - " |
476 | "device = %02x", sense[4]); | 479 | "device = %02x\n", sense[4]); |
477 | break; | 480 | break; |
478 | case 0x04: | 481 | case 0x04: |
479 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 482 | dev_warn(&device->cdev->dev, |
480 | "FORMAT 0 - Data Pinned for " | 483 | "FORMAT 0 - Data Pinned for " |
481 | "Device"); | 484 | "Device\n"); |
482 | break; | 485 | break; |
483 | default: | 486 | default: |
484 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 487 | dev_warn(&device->cdev->dev, |
485 | "FORMAT 0 - Reserved"); | 488 | "FORMAT 0 - Reserved\n"); |
486 | } | 489 | } |
487 | } | 490 | } |
488 | break; | 491 | break; |
@@ -492,348 +495,352 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
492 | case 0x00: /* No Message */ | 495 | case 0x00: /* No Message */ |
493 | break; | 496 | break; |
494 | case 0x01: | 497 | case 0x01: |
495 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 498 | dev_warn(&device->cdev->dev, |
496 | "FORMAT 1 - Device Status 1 not as " | 499 | "FORMAT 1 - Device Status 1 not as " |
497 | "expected"); | 500 | "expected\n"); |
498 | break; | 501 | break; |
499 | case 0x03: | 502 | case 0x03: |
500 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 503 | dev_warn(&device->cdev->dev, |
501 | "FORMAT 1 - Index missing"); | 504 | "FORMAT 1 - Index missing\n"); |
502 | break; | 505 | break; |
503 | case 0x04: | 506 | case 0x04: |
504 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 507 | dev_warn(&device->cdev->dev, |
505 | "FORMAT 1 - Interruption cannot be reset"); | 508 | "FORMAT 1 - Interruption cannot be " |
509 | "reset\n"); | ||
506 | break; | 510 | break; |
507 | case 0x05: | 511 | case 0x05: |
508 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 512 | dev_warn(&device->cdev->dev, |
509 | "FORMAT 1 - Device did not respond to " | 513 | "FORMAT 1 - Device did not respond to " |
510 | "selection"); | 514 | "selection\n"); |
511 | break; | 515 | break; |
512 | case 0x06: | 516 | case 0x06: |
513 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 517 | dev_warn(&device->cdev->dev, |
514 | "FORMAT 1 - Device check-2 error or Set " | 518 | "FORMAT 1 - Device check-2 error or Set " |
515 | "Sector is not complete"); | 519 | "Sector is not complete\n"); |
516 | break; | 520 | break; |
517 | case 0x07: | 521 | case 0x07: |
518 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 522 | dev_warn(&device->cdev->dev, |
519 | "FORMAT 1 - Head address does not " | 523 | "FORMAT 1 - Head address does not " |
520 | "compare"); | 524 | "compare\n"); |
521 | break; | 525 | break; |
522 | case 0x08: | 526 | case 0x08: |
523 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 527 | dev_warn(&device->cdev->dev, |
524 | "FORMAT 1 - Device status 1 not valid"); | 528 | "FORMAT 1 - Device status 1 not valid\n"); |
525 | break; | 529 | break; |
526 | case 0x09: | 530 | case 0x09: |
527 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 531 | dev_warn(&device->cdev->dev, |
528 | "FORMAT 1 - Device not ready"); | 532 | "FORMAT 1 - Device not ready\n"); |
529 | break; | 533 | break; |
530 | case 0x0A: | 534 | case 0x0A: |
531 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 535 | dev_warn(&device->cdev->dev, |
532 | "FORMAT 1 - Track physical address did " | 536 | "FORMAT 1 - Track physical address did " |
533 | "not compare"); | 537 | "not compare\n"); |
534 | break; | 538 | break; |
535 | case 0x0B: | 539 | case 0x0B: |
536 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 540 | dev_warn(&device->cdev->dev, |
537 | "FORMAT 1 - Missing device address bit"); | 541 | "FORMAT 1 - Missing device address bit\n"); |
538 | break; | 542 | break; |
539 | case 0x0C: | 543 | case 0x0C: |
540 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 544 | dev_warn(&device->cdev->dev, |
541 | "FORMAT 1 - Drive motor switch is off"); | 545 | "FORMAT 1 - Drive motor switch is off\n"); |
542 | break; | 546 | break; |
543 | case 0x0D: | 547 | case 0x0D: |
544 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 548 | dev_warn(&device->cdev->dev, |
545 | "FORMAT 1 - Seek incomplete"); | 549 | "FORMAT 1 - Seek incomplete\n"); |
546 | break; | 550 | break; |
547 | case 0x0E: | 551 | case 0x0E: |
548 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 552 | dev_warn(&device->cdev->dev, |
549 | "FORMAT 1 - Cylinder address did not " | 553 | "FORMAT 1 - Cylinder address did not " |
550 | "compare"); | 554 | "compare\n"); |
551 | break; | 555 | break; |
552 | case 0x0F: | 556 | case 0x0F: |
553 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 557 | dev_warn(&device->cdev->dev, |
554 | "FORMAT 1 - Offset active cannot be " | 558 | "FORMAT 1 - Offset active cannot be " |
555 | "reset"); | 559 | "reset\n"); |
556 | break; | 560 | break; |
557 | default: | 561 | default: |
558 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 562 | dev_warn(&device->cdev->dev, |
559 | "FORMAT 1 - Reserved"); | 563 | "FORMAT 1 - Reserved\n"); |
560 | } | 564 | } |
561 | break; | 565 | break; |
562 | 566 | ||
563 | case 0x20: /* Format 2 - 3990 Equipment Checks */ | 567 | case 0x20: /* Format 2 - 3990 Equipment Checks */ |
564 | switch (msg_no) { | 568 | switch (msg_no) { |
565 | case 0x08: | 569 | case 0x08: |
566 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 570 | dev_warn(&device->cdev->dev, |
567 | "FORMAT 2 - 3990 check-2 error"); | 571 | "FORMAT 2 - 3990 check-2 error\n"); |
568 | break; | 572 | break; |
569 | case 0x0E: | 573 | case 0x0E: |
570 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 574 | dev_warn(&device->cdev->dev, |
571 | "FORMAT 2 - Support facility errors"); | 575 | "FORMAT 2 - Support facility errors\n"); |
572 | break; | 576 | break; |
573 | case 0x0F: | 577 | case 0x0F: |
574 | DEV_MESSAGE(KERN_WARNING, device, | 578 | dev_warn(&device->cdev->dev, |
575 | "FORMAT 2 - Microcode detected error %02x", | 579 | "FORMAT 2 - Microcode detected error " |
576 | sense[8]); | 580 | "%02x\n", |
581 | sense[8]); | ||
577 | break; | 582 | break; |
578 | default: | 583 | default: |
579 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 584 | dev_warn(&device->cdev->dev, |
580 | "FORMAT 2 - Reserved"); | 585 | "FORMAT 2 - Reserved\n"); |
581 | } | 586 | } |
582 | break; | 587 | break; |
583 | 588 | ||
584 | case 0x30: /* Format 3 - 3990 Control Checks */ | 589 | case 0x30: /* Format 3 - 3990 Control Checks */ |
585 | switch (msg_no) { | 590 | switch (msg_no) { |
586 | case 0x0F: | 591 | case 0x0F: |
587 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 592 | dev_warn(&device->cdev->dev, |
588 | "FORMAT 3 - Allegiance terminated"); | 593 | "FORMAT 3 - Allegiance terminated\n"); |
589 | break; | 594 | break; |
590 | default: | 595 | default: |
591 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 596 | dev_warn(&device->cdev->dev, |
592 | "FORMAT 3 - Reserved"); | 597 | "FORMAT 3 - Reserved\n"); |
593 | } | 598 | } |
594 | break; | 599 | break; |
595 | 600 | ||
596 | case 0x40: /* Format 4 - Data Checks */ | 601 | case 0x40: /* Format 4 - Data Checks */ |
597 | switch (msg_no) { | 602 | switch (msg_no) { |
598 | case 0x00: | 603 | case 0x00: |
599 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 604 | dev_warn(&device->cdev->dev, |
600 | "FORMAT 4 - Home address area error"); | 605 | "FORMAT 4 - Home address area error\n"); |
601 | break; | 606 | break; |
602 | case 0x01: | 607 | case 0x01: |
603 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 608 | dev_warn(&device->cdev->dev, |
604 | "FORMAT 4 - Count area error"); | 609 | "FORMAT 4 - Count area error\n"); |
605 | break; | 610 | break; |
606 | case 0x02: | 611 | case 0x02: |
607 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 612 | dev_warn(&device->cdev->dev, |
608 | "FORMAT 4 - Key area error"); | 613 | "FORMAT 4 - Key area error\n"); |
609 | break; | 614 | break; |
610 | case 0x03: | 615 | case 0x03: |
611 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 616 | dev_warn(&device->cdev->dev, |
612 | "FORMAT 4 - Data area error"); | 617 | "FORMAT 4 - Data area error\n"); |
613 | break; | 618 | break; |
614 | case 0x04: | 619 | case 0x04: |
615 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 620 | dev_warn(&device->cdev->dev, |
616 | "FORMAT 4 - No sync byte in home address " | 621 | "FORMAT 4 - No sync byte in home address " |
617 | "area"); | 622 | "area\n"); |
618 | break; | 623 | break; |
619 | case 0x05: | 624 | case 0x05: |
620 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 625 | dev_warn(&device->cdev->dev, |
621 | "FORMAT 4 - No sync byte in count address " | 626 | "FORMAT 4 - No sync byte in count address " |
622 | "area"); | 627 | "area\n"); |
623 | break; | 628 | break; |
624 | case 0x06: | 629 | case 0x06: |
625 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 630 | dev_warn(&device->cdev->dev, |
626 | "FORMAT 4 - No sync byte in key area"); | 631 | "FORMAT 4 - No sync byte in key area\n"); |
627 | break; | 632 | break; |
628 | case 0x07: | 633 | case 0x07: |
629 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 634 | dev_warn(&device->cdev->dev, |
630 | "FORMAT 4 - No sync byte in data area"); | 635 | "FORMAT 4 - No sync byte in data area\n"); |
631 | break; | 636 | break; |
632 | case 0x08: | 637 | case 0x08: |
633 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 638 | dev_warn(&device->cdev->dev, |
634 | "FORMAT 4 - Home address area error; " | 639 | "FORMAT 4 - Home address area error; " |
635 | "offset active"); | 640 | "offset active\n"); |
636 | break; | 641 | break; |
637 | case 0x09: | 642 | case 0x09: |
638 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 643 | dev_warn(&device->cdev->dev, |
639 | "FORMAT 4 - Count area error; offset " | 644 | "FORMAT 4 - Count area error; offset " |
640 | "active"); | 645 | "active\n"); |
641 | break; | 646 | break; |
642 | case 0x0A: | 647 | case 0x0A: |
643 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 648 | dev_warn(&device->cdev->dev, |
644 | "FORMAT 4 - Key area error; offset " | 649 | "FORMAT 4 - Key area error; offset " |
645 | "active"); | 650 | "active\n"); |
646 | break; | 651 | break; |
647 | case 0x0B: | 652 | case 0x0B: |
648 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 653 | dev_warn(&device->cdev->dev, |
649 | "FORMAT 4 - Data area error; " | 654 | "FORMAT 4 - Data area error; " |
650 | "offset active"); | 655 | "offset active\n"); |
651 | break; | 656 | break; |
652 | case 0x0C: | 657 | case 0x0C: |
653 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 658 | dev_warn(&device->cdev->dev, |
654 | "FORMAT 4 - No sync byte in home " | 659 | "FORMAT 4 - No sync byte in home " |
655 | "address area; offset active"); | 660 | "address area; offset active\n"); |
656 | break; | 661 | break; |
657 | case 0x0D: | 662 | case 0x0D: |
658 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 663 | dev_warn(&device->cdev->dev, |
659 | "FORMAT 4 - No syn byte in count " | 664 | "FORMAT 4 - No syn byte in count " |
660 | "address area; offset active"); | 665 | "address area; offset active\n"); |
661 | break; | 666 | break; |
662 | case 0x0E: | 667 | case 0x0E: |
663 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 668 | dev_warn(&device->cdev->dev, |
664 | "FORMAT 4 - No sync byte in key area; " | 669 | "FORMAT 4 - No sync byte in key area; " |
665 | "offset active"); | 670 | "offset active\n"); |
666 | break; | 671 | break; |
667 | case 0x0F: | 672 | case 0x0F: |
668 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 673 | dev_warn(&device->cdev->dev, |
669 | "FORMAT 4 - No syn byte in data area; " | 674 | "FORMAT 4 - No syn byte in data area; " |
670 | "offset active"); | 675 | "offset active\n"); |
671 | break; | 676 | break; |
672 | default: | 677 | default: |
673 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 678 | dev_warn(&device->cdev->dev, |
674 | "FORMAT 4 - Reserved"); | 679 | "FORMAT 4 - Reserved\n"); |
675 | } | 680 | } |
676 | break; | 681 | break; |
677 | 682 | ||
678 | case 0x50: /* Format 5 - Data Check with displacement information */ | 683 | case 0x50: /* Format 5 - Data Check with displacement information */ |
679 | switch (msg_no) { | 684 | switch (msg_no) { |
680 | case 0x00: | 685 | case 0x00: |
681 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 686 | dev_warn(&device->cdev->dev, |
682 | "FORMAT 5 - Data Check in the " | 687 | "FORMAT 5 - Data Check in the " |
683 | "home address area"); | 688 | "home address area\n"); |
684 | break; | 689 | break; |
685 | case 0x01: | 690 | case 0x01: |
686 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 691 | dev_warn(&device->cdev->dev, |
687 | "FORMAT 5 - Data Check in the count area"); | 692 | "FORMAT 5 - Data Check in the count " |
693 | "area\n"); | ||
688 | break; | 694 | break; |
689 | case 0x02: | 695 | case 0x02: |
690 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 696 | dev_warn(&device->cdev->dev, |
691 | "FORMAT 5 - Data Check in the key area"); | 697 | "FORMAT 5 - Data Check in the key area\n"); |
692 | break; | 698 | break; |
693 | case 0x03: | 699 | case 0x03: |
694 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 700 | dev_warn(&device->cdev->dev, |
695 | "FORMAT 5 - Data Check in the data area"); | 701 | "FORMAT 5 - Data Check in the data " |
702 | "area\n"); | ||
696 | break; | 703 | break; |
697 | case 0x08: | 704 | case 0x08: |
698 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 705 | dev_warn(&device->cdev->dev, |
699 | "FORMAT 5 - Data Check in the " | 706 | "FORMAT 5 - Data Check in the " |
700 | "home address area; offset active"); | 707 | "home address area; offset active\n"); |
701 | break; | 708 | break; |
702 | case 0x09: | 709 | case 0x09: |
703 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 710 | dev_warn(&device->cdev->dev, |
704 | "FORMAT 5 - Data Check in the count area; " | 711 | "FORMAT 5 - Data Check in the count area; " |
705 | "offset active"); | 712 | "offset active\n"); |
706 | break; | 713 | break; |
707 | case 0x0A: | 714 | case 0x0A: |
708 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 715 | dev_warn(&device->cdev->dev, |
709 | "FORMAT 5 - Data Check in the key area; " | 716 | "FORMAT 5 - Data Check in the key area; " |
710 | "offset active"); | 717 | "offset active\n"); |
711 | break; | 718 | break; |
712 | case 0x0B: | 719 | case 0x0B: |
713 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 720 | dev_warn(&device->cdev->dev, |
714 | "FORMAT 5 - Data Check in the data area; " | 721 | "FORMAT 5 - Data Check in the data area; " |
715 | "offset active"); | 722 | "offset active\n"); |
716 | break; | 723 | break; |
717 | default: | 724 | default: |
718 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 725 | dev_warn(&device->cdev->dev, |
719 | "FORMAT 5 - Reserved"); | 726 | "FORMAT 5 - Reserved\n"); |
720 | } | 727 | } |
721 | break; | 728 | break; |
722 | 729 | ||
723 | case 0x60: /* Format 6 - Usage Statistics/Overrun Errors */ | 730 | case 0x60: /* Format 6 - Usage Statistics/Overrun Errors */ |
724 | switch (msg_no) { | 731 | switch (msg_no) { |
725 | case 0x00: | 732 | case 0x00: |
726 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 733 | dev_warn(&device->cdev->dev, |
727 | "FORMAT 6 - Overrun on channel A"); | 734 | "FORMAT 6 - Overrun on channel A\n"); |
728 | break; | 735 | break; |
729 | case 0x01: | 736 | case 0x01: |
730 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 737 | dev_warn(&device->cdev->dev, |
731 | "FORMAT 6 - Overrun on channel B"); | 738 | "FORMAT 6 - Overrun on channel B\n"); |
732 | break; | 739 | break; |
733 | case 0x02: | 740 | case 0x02: |
734 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 741 | dev_warn(&device->cdev->dev, |
735 | "FORMAT 6 - Overrun on channel C"); | 742 | "FORMAT 6 - Overrun on channel C\n"); |
736 | break; | 743 | break; |
737 | case 0x03: | 744 | case 0x03: |
738 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 745 | dev_warn(&device->cdev->dev, |
739 | "FORMAT 6 - Overrun on channel D"); | 746 | "FORMAT 6 - Overrun on channel D\n"); |
740 | break; | 747 | break; |
741 | case 0x04: | 748 | case 0x04: |
742 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 749 | dev_warn(&device->cdev->dev, |
743 | "FORMAT 6 - Overrun on channel E"); | 750 | "FORMAT 6 - Overrun on channel E\n"); |
744 | break; | 751 | break; |
745 | case 0x05: | 752 | case 0x05: |
746 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 753 | dev_warn(&device->cdev->dev, |
747 | "FORMAT 6 - Overrun on channel F"); | 754 | "FORMAT 6 - Overrun on channel F\n"); |
748 | break; | 755 | break; |
749 | case 0x06: | 756 | case 0x06: |
750 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 757 | dev_warn(&device->cdev->dev, |
751 | "FORMAT 6 - Overrun on channel G"); | 758 | "FORMAT 6 - Overrun on channel G\n"); |
752 | break; | 759 | break; |
753 | case 0x07: | 760 | case 0x07: |
754 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 761 | dev_warn(&device->cdev->dev, |
755 | "FORMAT 6 - Overrun on channel H"); | 762 | "FORMAT 6 - Overrun on channel H\n"); |
756 | break; | 763 | break; |
757 | default: | 764 | default: |
758 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 765 | dev_warn(&device->cdev->dev, |
759 | "FORMAT 6 - Reserved"); | 766 | "FORMAT 6 - Reserved\n"); |
760 | } | 767 | } |
761 | break; | 768 | break; |
762 | 769 | ||
763 | case 0x70: /* Format 7 - Device Connection Control Checks */ | 770 | case 0x70: /* Format 7 - Device Connection Control Checks */ |
764 | switch (msg_no) { | 771 | switch (msg_no) { |
765 | case 0x00: | 772 | case 0x00: |
766 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 773 | dev_warn(&device->cdev->dev, |
767 | "FORMAT 7 - RCC initiated by a connection " | 774 | "FORMAT 7 - RCC initiated by a connection " |
768 | "check alert"); | 775 | "check alert\n"); |
769 | break; | 776 | break; |
770 | case 0x01: | 777 | case 0x01: |
771 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 778 | dev_warn(&device->cdev->dev, |
772 | "FORMAT 7 - RCC 1 sequence not " | 779 | "FORMAT 7 - RCC 1 sequence not " |
773 | "successful"); | 780 | "successful\n"); |
774 | break; | 781 | break; |
775 | case 0x02: | 782 | case 0x02: |
776 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 783 | dev_warn(&device->cdev->dev, |
777 | "FORMAT 7 - RCC 1 and RCC 2 sequences not " | 784 | "FORMAT 7 - RCC 1 and RCC 2 sequences not " |
778 | "successful"); | 785 | "successful\n"); |
779 | break; | 786 | break; |
780 | case 0x03: | 787 | case 0x03: |
781 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 788 | dev_warn(&device->cdev->dev, |
782 | "FORMAT 7 - Invalid tag-in during " | 789 | "FORMAT 7 - Invalid tag-in during " |
783 | "selection sequence"); | 790 | "selection sequence\n"); |
784 | break; | 791 | break; |
785 | case 0x04: | 792 | case 0x04: |
786 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 793 | dev_warn(&device->cdev->dev, |
787 | "FORMAT 7 - extra RCC required"); | 794 | "FORMAT 7 - extra RCC required\n"); |
788 | break; | 795 | break; |
789 | case 0x05: | 796 | case 0x05: |
790 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 797 | dev_warn(&device->cdev->dev, |
791 | "FORMAT 7 - Invalid DCC selection " | 798 | "FORMAT 7 - Invalid DCC selection " |
792 | "response or timeout"); | 799 | "response or timeout\n"); |
793 | break; | 800 | break; |
794 | case 0x06: | 801 | case 0x06: |
795 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 802 | dev_warn(&device->cdev->dev, |
796 | "FORMAT 7 - Missing end operation; device " | 803 | "FORMAT 7 - Missing end operation; device " |
797 | "transfer complete"); | 804 | "transfer complete\n"); |
798 | break; | 805 | break; |
799 | case 0x07: | 806 | case 0x07: |
800 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 807 | dev_warn(&device->cdev->dev, |
801 | "FORMAT 7 - Missing end operation; device " | 808 | "FORMAT 7 - Missing end operation; device " |
802 | "transfer incomplete"); | 809 | "transfer incomplete\n"); |
803 | break; | 810 | break; |
804 | case 0x08: | 811 | case 0x08: |
805 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 812 | dev_warn(&device->cdev->dev, |
806 | "FORMAT 7 - Invalid tag-in for an " | 813 | "FORMAT 7 - Invalid tag-in for an " |
807 | "immediate command sequence"); | 814 | "immediate command sequence\n"); |
808 | break; | 815 | break; |
809 | case 0x09: | 816 | case 0x09: |
810 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 817 | dev_warn(&device->cdev->dev, |
811 | "FORMAT 7 - Invalid tag-in for an " | 818 | "FORMAT 7 - Invalid tag-in for an " |
812 | "extended command sequence"); | 819 | "extended command sequence\n"); |
813 | break; | 820 | break; |
814 | case 0x0A: | 821 | case 0x0A: |
815 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 822 | dev_warn(&device->cdev->dev, |
816 | "FORMAT 7 - 3990 microcode time out when " | 823 | "FORMAT 7 - 3990 microcode time out when " |
817 | "stopping selection"); | 824 | "stopping selection\n"); |
818 | break; | 825 | break; |
819 | case 0x0B: | 826 | case 0x0B: |
820 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 827 | dev_warn(&device->cdev->dev, |
821 | "FORMAT 7 - No response to selection " | 828 | "FORMAT 7 - No response to selection " |
822 | "after a poll interruption"); | 829 | "after a poll interruption\n"); |
823 | break; | 830 | break; |
824 | case 0x0C: | 831 | case 0x0C: |
825 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 832 | dev_warn(&device->cdev->dev, |
826 | "FORMAT 7 - Permanent path error (DASD " | 833 | "FORMAT 7 - Permanent path error (DASD " |
827 | "controller not available)"); | 834 | "controller not available)\n"); |
828 | break; | 835 | break; |
829 | case 0x0D: | 836 | case 0x0D: |
830 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 837 | dev_warn(&device->cdev->dev, |
831 | "FORMAT 7 - DASD controller not available" | 838 | "FORMAT 7 - DASD controller not available" |
832 | " on disconnected command chain"); | 839 | " on disconnected command chain\n"); |
833 | break; | 840 | break; |
834 | default: | 841 | default: |
835 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 842 | dev_warn(&device->cdev->dev, |
836 | "FORMAT 7 - Reserved"); | 843 | "FORMAT 7 - Reserved\n"); |
837 | } | 844 | } |
838 | break; | 845 | break; |
839 | 846 | ||
@@ -841,52 +848,52 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
841 | switch (msg_no) { | 848 | switch (msg_no) { |
842 | case 0x00: /* No Message */ | 849 | case 0x00: /* No Message */ |
843 | case 0x01: | 850 | case 0x01: |
844 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 851 | dev_warn(&device->cdev->dev, |
845 | "FORMAT 8 - Error correction code " | 852 | "FORMAT 8 - Error correction code " |
846 | "hardware fault"); | 853 | "hardware fault\n"); |
847 | break; | 854 | break; |
848 | case 0x03: | 855 | case 0x03: |
849 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 856 | dev_warn(&device->cdev->dev, |
850 | "FORMAT 8 - Unexpected end operation " | 857 | "FORMAT 8 - Unexpected end operation " |
851 | "response code"); | 858 | "response code\n"); |
852 | break; | 859 | break; |
853 | case 0x04: | 860 | case 0x04: |
854 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 861 | dev_warn(&device->cdev->dev, |
855 | "FORMAT 8 - End operation with transfer " | 862 | "FORMAT 8 - End operation with transfer " |
856 | "count not zero"); | 863 | "count not zero\n"); |
857 | break; | 864 | break; |
858 | case 0x05: | 865 | case 0x05: |
859 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 866 | dev_warn(&device->cdev->dev, |
860 | "FORMAT 8 - End operation with transfer " | 867 | "FORMAT 8 - End operation with transfer " |
861 | "count zero"); | 868 | "count zero\n"); |
862 | break; | 869 | break; |
863 | case 0x06: | 870 | case 0x06: |
864 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 871 | dev_warn(&device->cdev->dev, |
865 | "FORMAT 8 - DPS checks after a system " | 872 | "FORMAT 8 - DPS checks after a system " |
866 | "reset or selective reset"); | 873 | "reset or selective reset\n"); |
867 | break; | 874 | break; |
868 | case 0x07: | 875 | case 0x07: |
869 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 876 | dev_warn(&device->cdev->dev, |
870 | "FORMAT 8 - DPS cannot be filled"); | 877 | "FORMAT 8 - DPS cannot be filled\n"); |
871 | break; | 878 | break; |
872 | case 0x08: | 879 | case 0x08: |
873 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 880 | dev_warn(&device->cdev->dev, |
874 | "FORMAT 8 - Short busy time-out during " | 881 | "FORMAT 8 - Short busy time-out during " |
875 | "device selection"); | 882 | "device selection\n"); |
876 | break; | 883 | break; |
877 | case 0x09: | 884 | case 0x09: |
878 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 885 | dev_warn(&device->cdev->dev, |
879 | "FORMAT 8 - DASD controller failed to " | 886 | "FORMAT 8 - DASD controller failed to " |
880 | "set or reset the long busy latch"); | 887 | "set or reset the long busy latch\n"); |
881 | break; | 888 | break; |
882 | case 0x0A: | 889 | case 0x0A: |
883 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 890 | dev_warn(&device->cdev->dev, |
884 | "FORMAT 8 - No interruption from device " | 891 | "FORMAT 8 - No interruption from device " |
885 | "during a command chain"); | 892 | "during a command chain\n"); |
886 | break; | 893 | break; |
887 | default: | 894 | default: |
888 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 895 | dev_warn(&device->cdev->dev, |
889 | "FORMAT 8 - Reserved"); | 896 | "FORMAT 8 - Reserved\n"); |
890 | } | 897 | } |
891 | break; | 898 | break; |
892 | 899 | ||
@@ -895,97 +902,100 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
895 | case 0x00: | 902 | case 0x00: |
896 | break; /* No Message */ | 903 | break; /* No Message */ |
897 | case 0x06: | 904 | case 0x06: |
898 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 905 | dev_warn(&device->cdev->dev, |
899 | "FORMAT 9 - Device check-2 error"); | 906 | "FORMAT 9 - Device check-2 error\n"); |
900 | break; | 907 | break; |
901 | case 0x07: | 908 | case 0x07: |
902 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 909 | dev_warn(&device->cdev->dev, |
903 | "FORMAT 9 - Head address did not compare"); | 910 | "FORMAT 9 - Head address did not " |
911 | "compare\n"); | ||
904 | break; | 912 | break; |
905 | case 0x0A: | 913 | case 0x0A: |
906 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 914 | dev_warn(&device->cdev->dev, |
907 | "FORMAT 9 - Track physical address did " | 915 | "FORMAT 9 - Track physical address did " |
908 | "not compare while oriented"); | 916 | "not compare while oriented\n"); |
909 | break; | 917 | break; |
910 | case 0x0E: | 918 | case 0x0E: |
911 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 919 | dev_warn(&device->cdev->dev, |
912 | "FORMAT 9 - Cylinder address did not " | 920 | "FORMAT 9 - Cylinder address did not " |
913 | "compare"); | 921 | "compare\n"); |
914 | break; | 922 | break; |
915 | default: | 923 | default: |
916 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 924 | dev_warn(&device->cdev->dev, |
917 | "FORMAT 9 - Reserved"); | 925 | "FORMAT 9 - Reserved\n"); |
918 | } | 926 | } |
919 | break; | 927 | break; |
920 | 928 | ||
921 | case 0xF0: /* Format F - Cache Storage Checks */ | 929 | case 0xF0: /* Format F - Cache Storage Checks */ |
922 | switch (msg_no) { | 930 | switch (msg_no) { |
923 | case 0x00: | 931 | case 0x00: |
924 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 932 | dev_warn(&device->cdev->dev, |
925 | "FORMAT F - Operation Terminated"); | 933 | "FORMAT F - Operation Terminated\n"); |
926 | break; | 934 | break; |
927 | case 0x01: | 935 | case 0x01: |
928 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 936 | dev_warn(&device->cdev->dev, |
929 | "FORMAT F - Subsystem Processing Error"); | 937 | "FORMAT F - Subsystem Processing Error\n"); |
930 | break; | 938 | break; |
931 | case 0x02: | 939 | case 0x02: |
932 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 940 | dev_warn(&device->cdev->dev, |
933 | "FORMAT F - Cache or nonvolatile storage " | 941 | "FORMAT F - Cache or nonvolatile storage " |
934 | "equipment failure"); | 942 | "equipment failure\n"); |
935 | break; | 943 | break; |
936 | case 0x04: | 944 | case 0x04: |
937 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 945 | dev_warn(&device->cdev->dev, |
938 | "FORMAT F - Caching terminated"); | 946 | "FORMAT F - Caching terminated\n"); |
939 | break; | 947 | break; |
940 | case 0x06: | 948 | case 0x06: |
941 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 949 | dev_warn(&device->cdev->dev, |
942 | "FORMAT F - Cache fast write access not " | 950 | "FORMAT F - Cache fast write access not " |
943 | "authorized"); | 951 | "authorized\n"); |
944 | break; | 952 | break; |
945 | case 0x07: | 953 | case 0x07: |
946 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 954 | dev_warn(&device->cdev->dev, |
947 | "FORMAT F - Track format incorrect"); | 955 | "FORMAT F - Track format incorrect\n"); |
948 | break; | 956 | break; |
949 | case 0x09: | 957 | case 0x09: |
950 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 958 | dev_warn(&device->cdev->dev, |
951 | "FORMAT F - Caching reinitiated"); | 959 | "FORMAT F - Caching reinitiated\n"); |
952 | break; | 960 | break; |
953 | case 0x0A: | 961 | case 0x0A: |
954 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 962 | dev_warn(&device->cdev->dev, |
955 | "FORMAT F - Nonvolatile storage " | 963 | "FORMAT F - Nonvolatile storage " |
956 | "terminated"); | 964 | "terminated\n"); |
957 | break; | 965 | break; |
958 | case 0x0B: | 966 | case 0x0B: |
959 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 967 | dev_warn(&device->cdev->dev, |
960 | "FORMAT F - Volume is suspended duplex"); | 968 | "FORMAT F - Volume is suspended duplex\n"); |
961 | /* call extended error reporting (EER) */ | 969 | /* call extended error reporting (EER) */ |
962 | dasd_eer_write(device, erp->refers, | 970 | dasd_eer_write(device, erp->refers, |
963 | DASD_EER_PPRCSUSPEND); | 971 | DASD_EER_PPRCSUSPEND); |
964 | break; | 972 | break; |
965 | case 0x0C: | 973 | case 0x0C: |
966 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 974 | dev_warn(&device->cdev->dev, |
967 | "FORMAT F - Subsystem status connot be " | 975 | "FORMAT F - Subsystem status cannot be " |
968 | "determined"); | 976 | "determined\n"); |
969 | break; | 977 | break; |
970 | case 0x0D: | 978 | case 0x0D: |
971 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 979 | dev_warn(&device->cdev->dev, |
972 | "FORMAT F - Caching status reset to " | 980 | "FORMAT F - Caching status reset to " |
973 | "default"); | 981 | "default\n"); |
974 | break; | 982 | break; |
975 | case 0x0E: | 983 | case 0x0E: |
976 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 984 | dev_warn(&device->cdev->dev, |
977 | "FORMAT F - DASD Fast Write inhibited"); | 985 | "FORMAT F - DASD Fast Write inhibited\n"); |
978 | break; | 986 | break; |
979 | default: | 987 | default: |
980 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 988 | dev_warn(&device->cdev->dev, |
981 | "FORMAT D - Reserved"); | 989 | "FORMAT D - Reserved\n"); |
982 | } | 990 | } |
983 | break; | 991 | break; |
984 | 992 | ||
985 | default: /* unknown message format - should not happen */ | 993 | default: /* unknown message format - should not happen |
986 | DEV_MESSAGE (KERN_WARNING, device, | 994 | internal error 03 - unknown message format */ |
987 | "unknown message format %02x", | 995 | snprintf(errorstring, ERRORLENGTH, "03 %x02", msg_format); |
988 | msg_format); | 996 | dev_err(&device->cdev->dev, |
997 | "An error occurred in the DASD device driver, " | ||
998 | "reason=%s\n", errorstring); | ||
989 | break; | 999 | break; |
990 | } /* end switch message format */ | 1000 | } /* end switch message format */ |
991 | 1001 | ||
@@ -1015,7 +1025,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) | |||
1015 | /* env data present (ACTION 10 - retry should work) */ | 1025 | /* env data present (ACTION 10 - retry should work) */ |
1016 | if (sense[2] & SNS2_ENV_DATA_PRESENT) { | 1026 | if (sense[2] & SNS2_ENV_DATA_PRESENT) { |
1017 | 1027 | ||
1018 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1028 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1019 | "Command Reject - environmental data present"); | 1029 | "Command Reject - environmental data present"); |
1020 | 1030 | ||
1021 | dasd_3990_handle_env_data(erp, sense); | 1031 | dasd_3990_handle_env_data(erp, sense); |
@@ -1023,9 +1033,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) | |||
1023 | erp->retries = 5; | 1033 | erp->retries = 5; |
1024 | 1034 | ||
1025 | } else { | 1035 | } else { |
1026 | /* fatal error - set status to FAILED */ | 1036 | /* fatal error - set status to FAILED |
1027 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1037 | internal error 09 - Command Reject */ |
1028 | "Command Reject - Fatal error"); | 1038 | dev_err(&device->cdev->dev, "An error occurred in the DASD " |
1039 | "device driver, reason=%s\n", "09"); | ||
1029 | 1040 | ||
1030 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 1041 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
1031 | } | 1042 | } |
@@ -1061,7 +1072,7 @@ dasd_3990_erp_bus_out(struct dasd_ccw_req * erp) | |||
1061 | } else { | 1072 | } else { |
1062 | 1073 | ||
1063 | /* issue a message and wait for 'device ready' interrupt */ | 1074 | /* issue a message and wait for 'device ready' interrupt */ |
1064 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1075 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1065 | "bus out parity error or BOPC requested by " | 1076 | "bus out parity error or BOPC requested by " |
1066 | "channel"); | 1077 | "channel"); |
1067 | 1078 | ||
@@ -1093,21 +1104,19 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) | |||
1093 | erp->function = dasd_3990_erp_equip_check; | 1104 | erp->function = dasd_3990_erp_equip_check; |
1094 | 1105 | ||
1095 | if (sense[1] & SNS1_WRITE_INHIBITED) { | 1106 | if (sense[1] & SNS1_WRITE_INHIBITED) { |
1107 | dev_info(&device->cdev->dev, | ||
1108 | "Write inhibited path encountered\n"); | ||
1096 | 1109 | ||
1097 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1110 | /* vary path offline |
1098 | "Write inhibited path encountered"); | 1111 | internal error 04 - Path should be varied off-line.*/ |
1099 | 1112 | dev_err(&device->cdev->dev, "An error occurred in the DASD " | |
1100 | /* vary path offline */ | 1113 | "device driver, reason=%s\n", "04"); |
1101 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
1102 | "Path should be varied off-line. " | ||
1103 | "This is not implemented yet \n - please report " | ||
1104 | "to linux390@de.ibm.com"); | ||
1105 | 1114 | ||
1106 | erp = dasd_3990_erp_action_1(erp); | 1115 | erp = dasd_3990_erp_action_1(erp); |
1107 | 1116 | ||
1108 | } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { | 1117 | } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { |
1109 | 1118 | ||
1110 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1119 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1111 | "Equipment Check - " "environmental data present"); | 1120 | "Equipment Check - " "environmental data present"); |
1112 | 1121 | ||
1113 | dasd_3990_handle_env_data(erp, sense); | 1122 | dasd_3990_handle_env_data(erp, sense); |
@@ -1116,7 +1125,7 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) | |||
1116 | 1125 | ||
1117 | } else if (sense[1] & SNS1_PERM_ERR) { | 1126 | } else if (sense[1] & SNS1_PERM_ERR) { |
1118 | 1127 | ||
1119 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1128 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1120 | "Equipment Check - retry exhausted or " | 1129 | "Equipment Check - retry exhausted or " |
1121 | "undesirable"); | 1130 | "undesirable"); |
1122 | 1131 | ||
@@ -1125,7 +1134,7 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) | |||
1125 | } else { | 1134 | } else { |
1126 | /* all other equipment checks - Action 5 */ | 1135 | /* all other equipment checks - Action 5 */ |
1127 | /* rest is done when retries == 0 */ | 1136 | /* rest is done when retries == 0 */ |
1128 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1137 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1129 | "Equipment check or processing error"); | 1138 | "Equipment check or processing error"); |
1130 | 1139 | ||
1131 | erp = dasd_3990_erp_action_5(erp); | 1140 | erp = dasd_3990_erp_action_5(erp); |
@@ -1156,9 +1165,9 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) | |||
1156 | if (sense[2] & SNS2_CORRECTABLE) { /* correctable data check */ | 1165 | if (sense[2] & SNS2_CORRECTABLE) { /* correctable data check */ |
1157 | 1166 | ||
1158 | /* issue message that the data has been corrected */ | 1167 | /* issue message that the data has been corrected */ |
1159 | DEV_MESSAGE(KERN_EMERG, device, "%s", | 1168 | dev_emerg(&device->cdev->dev, |
1160 | "Data recovered during retry with PCI " | 1169 | "Data recovered during retry with PCI " |
1161 | "fetch mode active"); | 1170 | "fetch mode active\n"); |
1162 | 1171 | ||
1163 | /* not possible to handle this situation in Linux */ | 1172 | /* not possible to handle this situation in Linux */ |
1164 | panic("No way to inform application about the possibly " | 1173 | 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) | |||
1166 | 1175 | ||
1167 | } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { | 1176 | } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { |
1168 | 1177 | ||
1169 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1178 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1170 | "Uncorrectable data check recovered secondary " | 1179 | "Uncorrectable data check recovered secondary " |
1171 | "addr of duplex pair"); | 1180 | "addr of duplex pair"); |
1172 | 1181 | ||
@@ -1174,7 +1183,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) | |||
1174 | 1183 | ||
1175 | } else if (sense[1] & SNS1_PERM_ERR) { | 1184 | } else if (sense[1] & SNS1_PERM_ERR) { |
1176 | 1185 | ||
1177 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1186 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1178 | "Uncorrectable data check with internal " | 1187 | "Uncorrectable data check with internal " |
1179 | "retry exhausted"); | 1188 | "retry exhausted"); |
1180 | 1189 | ||
@@ -1182,7 +1191,7 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) | |||
1182 | 1191 | ||
1183 | } else { | 1192 | } else { |
1184 | /* all other data checks */ | 1193 | /* all other data checks */ |
1185 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1194 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1186 | "Uncorrectable data check with retry count " | 1195 | "Uncorrectable data check with retry count " |
1187 | "exhausted..."); | 1196 | "exhausted..."); |
1188 | 1197 | ||
@@ -1212,7 +1221,7 @@ dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense) | |||
1212 | 1221 | ||
1213 | erp->function = dasd_3990_erp_overrun; | 1222 | erp->function = dasd_3990_erp_overrun; |
1214 | 1223 | ||
1215 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1224 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1216 | "Overrun - service overrun or overrun" | 1225 | "Overrun - service overrun or overrun" |
1217 | " error requested by channel"); | 1226 | " error requested by channel"); |
1218 | 1227 | ||
@@ -1243,7 +1252,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) | |||
1243 | 1252 | ||
1244 | if (sense[2] & SNS2_ENV_DATA_PRESENT) { | 1253 | if (sense[2] & SNS2_ENV_DATA_PRESENT) { |
1245 | 1254 | ||
1246 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1255 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1247 | "Track format error when destaging or " | 1256 | "Track format error when destaging or " |
1248 | "staging data"); | 1257 | "staging data"); |
1249 | 1258 | ||
@@ -1252,8 +1261,10 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) | |||
1252 | erp = dasd_3990_erp_action_4(erp, sense); | 1261 | erp = dasd_3990_erp_action_4(erp, sense); |
1253 | 1262 | ||
1254 | } else { | 1263 | } else { |
1255 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1264 | /* internal error 06 - The track format is not valid*/ |
1256 | "Invalid Track Format - Fatal error"); | 1265 | dev_err(&device->cdev->dev, |
1266 | "An error occurred in the DASD device driver, " | ||
1267 | "reason=%s\n", "06"); | ||
1257 | 1268 | ||
1258 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 1269 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
1259 | } | 1270 | } |
@@ -1279,8 +1290,8 @@ dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense) | |||
1279 | 1290 | ||
1280 | struct dasd_device *device = default_erp->startdev; | 1291 | struct dasd_device *device = default_erp->startdev; |
1281 | 1292 | ||
1282 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1293 | dev_err(&device->cdev->dev, |
1283 | "End-of-Cylinder - must never happen"); | 1294 | "The cylinder data for accessing the DASD is inconsistent\n"); |
1284 | 1295 | ||
1285 | /* implement action 7 - BUG */ | 1296 | /* implement action 7 - BUG */ |
1286 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); | 1297 | 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) | |||
1306 | 1317 | ||
1307 | erp->function = dasd_3990_erp_env_data; | 1318 | erp->function = dasd_3990_erp_env_data; |
1308 | 1319 | ||
1309 | DEV_MESSAGE(KERN_DEBUG, device, "%s", "Environmental data present"); | 1320 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Environmental data present"); |
1310 | 1321 | ||
1311 | dasd_3990_handle_env_data(erp, sense); | 1322 | dasd_3990_handle_env_data(erp, sense); |
1312 | 1323 | ||
@@ -1339,8 +1350,8 @@ dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense) | |||
1339 | 1350 | ||
1340 | struct dasd_device *device = default_erp->startdev; | 1351 | struct dasd_device *device = default_erp->startdev; |
1341 | 1352 | ||
1342 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1353 | dev_err(&device->cdev->dev, |
1343 | "No Record Found - Fatal error "); | 1354 | "The specified record was not found\n"); |
1344 | 1355 | ||
1345 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); | 1356 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); |
1346 | 1357 | ||
@@ -1365,7 +1376,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) | |||
1365 | 1376 | ||
1366 | struct dasd_device *device = erp->startdev; | 1377 | struct dasd_device *device = erp->startdev; |
1367 | 1378 | ||
1368 | DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected"); | 1379 | dev_err(&device->cdev->dev, "Accessing the DASD failed because of " |
1380 | "a hardware error\n"); | ||
1369 | 1381 | ||
1370 | return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 1382 | return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
1371 | 1383 | ||
@@ -1394,7 +1406,7 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( | |||
1394 | if (cqr->block && | 1406 | if (cqr->block && |
1395 | (cqr->block->base != cqr->startdev)) { | 1407 | (cqr->block->base != cqr->startdev)) { |
1396 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { | 1408 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { |
1397 | DEV_MESSAGE(KERN_ERR, cqr->startdev, | 1409 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, |
1398 | "ERP on alias device for request %p," | 1410 | "ERP on alias device for request %p," |
1399 | " recover on base device %s", cqr, | 1411 | " recover on base device %s", cqr, |
1400 | dev_name(&cqr->block->base->cdev->dev)); | 1412 | dev_name(&cqr->block->base->cdev->dev)); |
@@ -1511,7 +1523,7 @@ dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) | |||
1511 | erp->retries = 256; | 1523 | erp->retries = 256; |
1512 | erp->function = dasd_3990_erp_action_10_32; | 1524 | erp->function = dasd_3990_erp_action_10_32; |
1513 | 1525 | ||
1514 | DEV_MESSAGE(KERN_DEBUG, device, "%s", "Perform logging requested"); | 1526 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Perform logging requested"); |
1515 | 1527 | ||
1516 | return erp; | 1528 | return erp; |
1517 | 1529 | ||
@@ -1549,7 +1561,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1549 | char *LO_data; /* LO_eckd_data_t */ | 1561 | char *LO_data; /* LO_eckd_data_t */ |
1550 | struct ccw1 *ccw, *oldccw; | 1562 | struct ccw1 *ccw, *oldccw; |
1551 | 1563 | ||
1552 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1564 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1553 | "Write not finished because of unexpected condition"); | 1565 | "Write not finished because of unexpected condition"); |
1554 | 1566 | ||
1555 | default_erp->function = dasd_3990_erp_action_1B_32; | 1567 | 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) | |||
1561 | cqr = cqr->refers; | 1573 | cqr = cqr->refers; |
1562 | } | 1574 | } |
1563 | 1575 | ||
1576 | if (scsw_is_tm(&cqr->irb.scsw)) { | ||
1577 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | ||
1578 | "32 bit sense, action 1B is not defined" | ||
1579 | " in transport mode - just retry"); | ||
1580 | return default_erp; | ||
1581 | } | ||
1582 | |||
1564 | /* for imprecise ending just do default erp */ | 1583 | /* for imprecise ending just do default erp */ |
1565 | if (sense[1] & 0x01) { | 1584 | if (sense[1] & 0x01) { |
1566 | 1585 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | |
1567 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | ||
1568 | "Imprecise ending is set - just retry"); | 1586 | "Imprecise ending is set - just retry"); |
1569 | 1587 | ||
1570 | return default_erp; | 1588 | return default_erp; |
@@ -1575,8 +1593,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1575 | cpa = default_erp->refers->irb.scsw.cmd.cpa; | 1593 | cpa = default_erp->refers->irb.scsw.cmd.cpa; |
1576 | 1594 | ||
1577 | if (cpa == 0) { | 1595 | if (cpa == 0) { |
1578 | 1596 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | |
1579 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | ||
1580 | "Unable to determine address of the CCW " | 1597 | "Unable to determine address of the CCW " |
1581 | "to be restarted"); | 1598 | "to be restarted"); |
1582 | 1599 | ||
@@ -1590,7 +1607,9 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1590 | sizeof(struct LO_eckd_data), device); | 1607 | sizeof(struct LO_eckd_data), device); |
1591 | 1608 | ||
1592 | if (IS_ERR(erp)) { | 1609 | if (IS_ERR(erp)) { |
1593 | DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP"); | 1610 | /* internal error 01 - Unable to allocate ERP */ |
1611 | dev_err(&device->cdev->dev, "An error occurred in the DASD " | ||
1612 | "device driver, reason=%s\n", "01"); | ||
1594 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); | 1613 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); |
1595 | } | 1614 | } |
1596 | 1615 | ||
@@ -1599,7 +1618,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1599 | oldccw = cqr->cpaddr; | 1618 | oldccw = cqr->cpaddr; |
1600 | if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { | 1619 | if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { |
1601 | PFX_data = cqr->data; | 1620 | PFX_data = cqr->data; |
1602 | memcpy(DE_data, &PFX_data->define_extend, | 1621 | memcpy(DE_data, &PFX_data->define_extent, |
1603 | sizeof(struct DE_eckd_data)); | 1622 | sizeof(struct DE_eckd_data)); |
1604 | } else | 1623 | } else |
1605 | memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data)); | 1624 | 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) | |||
1608 | LO_data = erp->data + sizeof(struct DE_eckd_data); | 1627 | LO_data = erp->data + sizeof(struct DE_eckd_data); |
1609 | 1628 | ||
1610 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { | 1629 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { |
1611 | 1630 | /* should not */ | |
1612 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
1613 | "BUG - this should not happen"); | ||
1614 | |||
1615 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); | 1631 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); |
1616 | } | 1632 | } |
1617 | 1633 | ||
@@ -1701,7 +1717,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1701 | char *LO_data; /* struct LO_eckd_data */ | 1717 | char *LO_data; /* struct LO_eckd_data */ |
1702 | struct ccw1 *ccw; | 1718 | struct ccw1 *ccw; |
1703 | 1719 | ||
1704 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1720 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1705 | "Write not finished because of unexpected condition" | 1721 | "Write not finished because of unexpected condition" |
1706 | " - follow on"); | 1722 | " - follow on"); |
1707 | 1723 | ||
@@ -1712,10 +1728,16 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1712 | cqr = cqr->refers; | 1728 | cqr = cqr->refers; |
1713 | } | 1729 | } |
1714 | 1730 | ||
1731 | if (scsw_is_tm(&cqr->irb.scsw)) { | ||
1732 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | ||
1733 | "32 bit sense, action 1B, update," | ||
1734 | " in transport mode - just retry"); | ||
1735 | return previous_erp; | ||
1736 | } | ||
1737 | |||
1715 | /* for imprecise ending just do default erp */ | 1738 | /* for imprecise ending just do default erp */ |
1716 | if (sense[1] & 0x01) { | 1739 | if (sense[1] & 0x01) { |
1717 | 1740 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | |
1718 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | ||
1719 | "Imprecise ending is set - just retry"); | 1741 | "Imprecise ending is set - just retry"); |
1720 | 1742 | ||
1721 | previous_erp->status = DASD_CQR_FILLED; | 1743 | previous_erp->status = DASD_CQR_FILLED; |
@@ -1728,10 +1750,10 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1728 | cpa = previous_erp->irb.scsw.cmd.cpa; | 1750 | cpa = previous_erp->irb.scsw.cmd.cpa; |
1729 | 1751 | ||
1730 | if (cpa == 0) { | 1752 | if (cpa == 0) { |
1731 | 1753 | /* internal error 02 - | |
1732 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1754 | Unable to determine address of the CCW to be restarted */ |
1733 | "Unable to determine address of the CCW " | 1755 | dev_err(&device->cdev->dev, "An error occurred in the DASD " |
1734 | "to be restarted"); | 1756 | "device driver, reason=%s\n", "02"); |
1735 | 1757 | ||
1736 | previous_erp->status = DASD_CQR_FAILED; | 1758 | previous_erp->status = DASD_CQR_FAILED; |
1737 | 1759 | ||
@@ -1744,10 +1766,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1744 | LO_data = erp->data + sizeof(struct DE_eckd_data); | 1766 | LO_data = erp->data + sizeof(struct DE_eckd_data); |
1745 | 1767 | ||
1746 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { | 1768 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { |
1747 | 1769 | /* should not happen */ | |
1748 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
1749 | "BUG - this should not happen"); | ||
1750 | |||
1751 | previous_erp->status = DASD_CQR_FAILED; | 1770 | previous_erp->status = DASD_CQR_FAILED; |
1752 | 1771 | ||
1753 | return previous_erp; | 1772 | return previous_erp; |
@@ -1935,14 +1954,13 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense) | |||
1935 | 1954 | ||
1936 | if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { | 1955 | if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { |
1937 | 1956 | ||
1938 | /* set to suspended duplex state then restart */ | 1957 | /* set to suspended duplex state then restart |
1958 | internal error 05 - Set device to suspended duplex state | ||
1959 | should be done */ | ||
1939 | struct dasd_device *device = erp->startdev; | 1960 | struct dasd_device *device = erp->startdev; |
1940 | 1961 | dev_err(&device->cdev->dev, | |
1941 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1962 | "An error occurred in the DASD device driver, " |
1942 | "Set device to suspended duplex state should be " | 1963 | "reason=%s\n", "05"); |
1943 | "done!\n" | ||
1944 | "This is not implemented yet (for compound ERP)" | ||
1945 | " - please report to linux390@de.ibm.com"); | ||
1946 | 1964 | ||
1947 | } | 1965 | } |
1948 | 1966 | ||
@@ -2012,15 +2030,14 @@ dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense) | |||
2012 | { | 2030 | { |
2013 | /* print message according to log or message to operator mode */ | 2031 | /* print message according to log or message to operator mode */ |
2014 | if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) { | 2032 | if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) { |
2015 | |||
2016 | /* print SIM SRC from RefCode */ | 2033 | /* print SIM SRC from RefCode */ |
2017 | DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: " | 2034 | dev_err(&device->cdev->dev, "SIM - SRC: " |
2018 | "%02x%02x%02x%02x", sense[22], | 2035 | "%02x%02x%02x%02x\n", sense[22], |
2019 | sense[23], sense[11], sense[12]); | 2036 | sense[23], sense[11], sense[12]); |
2020 | } else if (sense[24] & DASD_SIM_LOG) { | 2037 | } else if (sense[24] & DASD_SIM_LOG) { |
2021 | /* print SIM SRC Refcode */ | 2038 | /* print SIM SRC Refcode */ |
2022 | DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: " | 2039 | dev_warn(&device->cdev->dev, "log SIM - SRC: " |
2023 | "%02x%02x%02x%02x", sense[22], | 2040 | "%02x%02x%02x%02x\n", sense[22], |
2024 | sense[23], sense[11], sense[12]); | 2041 | sense[23], sense[11], sense[12]); |
2025 | } | 2042 | } |
2026 | } | 2043 | } |
@@ -2063,14 +2080,14 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2063 | switch (sense[25]) { | 2080 | switch (sense[25]) { |
2064 | 2081 | ||
2065 | case 0x00: /* success - use default ERP for retries */ | 2082 | case 0x00: /* success - use default ERP for retries */ |
2066 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 2083 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", |
2067 | "ERP called for successful request" | 2084 | "ERP called for successful request" |
2068 | " - just retry"); | 2085 | " - just retry"); |
2069 | break; | 2086 | break; |
2070 | 2087 | ||
2071 | case 0x01: /* fatal error */ | 2088 | case 0x01: /* fatal error */ |
2072 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2089 | dev_err(&device->cdev->dev, |
2073 | "Retry not recommended - Fatal error"); | 2090 | "ERP failed for the DASD\n"); |
2074 | 2091 | ||
2075 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 2092 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
2076 | break; | 2093 | break; |
@@ -2080,13 +2097,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2080 | erp = dasd_3990_erp_int_req(erp); | 2097 | erp = dasd_3990_erp_int_req(erp); |
2081 | break; | 2098 | break; |
2082 | 2099 | ||
2083 | case 0x0F: /* length mismatch during update write command */ | 2100 | case 0x0F: /* length mismatch during update write command |
2084 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2101 | internal error 08 - update write command error*/ |
2085 | "update write command error - should not " | 2102 | dev_err(&device->cdev->dev, "An error occurred in the " |
2086 | "happen;\n" | 2103 | "DASD device driver, reason=%s\n", "08"); |
2087 | "Please send this message together with " | ||
2088 | "the above sense data to linux390@de." | ||
2089 | "ibm.com"); | ||
2090 | 2104 | ||
2091 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 2105 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
2092 | break; | 2106 | break; |
@@ -2095,13 +2109,12 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2095 | erp = dasd_3990_erp_action_10_32(erp, sense); | 2109 | erp = dasd_3990_erp_action_10_32(erp, sense); |
2096 | break; | 2110 | break; |
2097 | 2111 | ||
2098 | case 0x15: /* next track outside defined extend */ | 2112 | case 0x15: /* next track outside defined extend |
2099 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2113 | internal error 07 - The next track is not |
2100 | "next track outside defined extend - " | 2114 | within the defined storage extent */ |
2101 | "should not happen;\n" | 2115 | dev_err(&device->cdev->dev, |
2102 | "Please send this message together with " | 2116 | "An error occurred in the DASD device driver, " |
2103 | "the above sense data to linux390@de." | 2117 | "reason=%s\n", "07"); |
2104 | "ibm.com"); | ||
2105 | 2118 | ||
2106 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 2119 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
2107 | break; | 2120 | break; |
@@ -2112,9 +2125,9 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2112 | break; | 2125 | break; |
2113 | 2126 | ||
2114 | case 0x1C: /* invalid data */ | 2127 | case 0x1C: /* invalid data */ |
2115 | DEV_MESSAGE(KERN_EMERG, device, "%s", | 2128 | dev_emerg(&device->cdev->dev, |
2116 | "Data recovered during retry with PCI " | 2129 | "Data recovered during retry with PCI " |
2117 | "fetch mode active"); | 2130 | "fetch mode active\n"); |
2118 | 2131 | ||
2119 | /* not possible to handle this situation in Linux */ | 2132 | /* not possible to handle this situation in Linux */ |
2120 | panic | 2133 | panic |
@@ -2123,7 +2136,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2123 | break; | 2136 | break; |
2124 | 2137 | ||
2125 | case 0x1D: /* state-change pending */ | 2138 | case 0x1D: /* state-change pending */ |
2126 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 2139 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2127 | "A State change pending condition exists " | 2140 | "A State change pending condition exists " |
2128 | "for the subsystem or device"); | 2141 | "for the subsystem or device"); |
2129 | 2142 | ||
@@ -2131,7 +2144,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2131 | break; | 2144 | break; |
2132 | 2145 | ||
2133 | case 0x1E: /* busy */ | 2146 | case 0x1E: /* busy */ |
2134 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 2147 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2135 | "Busy condition exists " | 2148 | "Busy condition exists " |
2136 | "for the subsystem or device"); | 2149 | "for the subsystem or device"); |
2137 | erp = dasd_3990_erp_action_4(erp, sense); | 2150 | erp = dasd_3990_erp_action_4(erp, sense); |
@@ -2171,9 +2184,9 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) | |||
2171 | { | 2184 | { |
2172 | struct dasd_device *device = erp->startdev; | 2185 | struct dasd_device *device = erp->startdev; |
2173 | 2186 | ||
2174 | if (erp->refers->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | 2187 | if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |
2175 | | SCHN_STAT_CHN_CTRL_CHK)) { | 2188 | | SCHN_STAT_CHN_CTRL_CHK)) { |
2176 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 2189 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2177 | "channel or interface control check"); | 2190 | "channel or interface control check"); |
2178 | erp = dasd_3990_erp_action_4(erp, NULL); | 2191 | erp = dasd_3990_erp_action_4(erp, NULL); |
2179 | } | 2192 | } |
@@ -2193,21 +2206,23 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) | |||
2193 | * erp_new contens was possibly modified | 2206 | * erp_new contens was possibly modified |
2194 | */ | 2207 | */ |
2195 | static struct dasd_ccw_req * | 2208 | static struct dasd_ccw_req * |
2196 | dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | 2209 | dasd_3990_erp_inspect(struct dasd_ccw_req *erp) |
2197 | { | 2210 | { |
2198 | 2211 | ||
2199 | struct dasd_ccw_req *erp_new = NULL; | 2212 | struct dasd_ccw_req *erp_new = NULL; |
2200 | /* sense data are located in the refers record of the */ | 2213 | char *sense; |
2201 | /* already set up new ERP ! */ | ||
2202 | char *sense = erp->refers->irb.ecw; | ||
2203 | 2214 | ||
2204 | /* if this problem occured on an alias retry on base */ | 2215 | /* if this problem occured on an alias retry on base */ |
2205 | erp_new = dasd_3990_erp_inspect_alias(erp); | 2216 | erp_new = dasd_3990_erp_inspect_alias(erp); |
2206 | if (erp_new) | 2217 | if (erp_new) |
2207 | return erp_new; | 2218 | return erp_new; |
2208 | 2219 | ||
2209 | /* check if no concurrent sens is available */ | 2220 | /* sense data are located in the refers record of the |
2210 | if (!erp->refers->irb.esw.esw0.erw.cons) | 2221 | * already set up new ERP ! |
2222 | * check if concurrent sens is available | ||
2223 | */ | ||
2224 | sense = dasd_get_sense(&erp->refers->irb); | ||
2225 | if (!sense) | ||
2211 | erp_new = dasd_3990_erp_control_check(erp); | 2226 | erp_new = dasd_3990_erp_control_check(erp); |
2212 | /* distinguish between 24 and 32 byte sense data */ | 2227 | /* distinguish between 24 and 32 byte sense data */ |
2213 | else if (sense[27] & DASD_SENSE_BIT_0) { | 2228 | else if (sense[27] & DASD_SENSE_BIT_0) { |
@@ -2231,7 +2246,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2231 | * DESCRIPTION | 2246 | * DESCRIPTION |
2232 | * This funtion adds an additional request block (ERP) to the head of | 2247 | * This funtion adds an additional request block (ERP) to the head of |
2233 | * the given cqr (or erp). | 2248 | * the given cqr (or erp). |
2234 | * This erp is initialized as an default erp (retry TIC) | 2249 | * For a command mode cqr the erp is initialized as an default erp |
2250 | * (retry TIC). | ||
2251 | * For transport mode we make a copy of the original TCW (points to | ||
2252 | * the original TCCB, TIDALs, etc.) but give it a fresh | ||
2253 | * TSB so the original sense data will not be changed. | ||
2235 | * | 2254 | * |
2236 | * PARAMETER | 2255 | * PARAMETER |
2237 | * cqr head of the current ERP-chain (or single cqr if | 2256 | * cqr head of the current ERP-chain (or single cqr if |
@@ -2239,25 +2258,35 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2239 | * RETURN VALUES | 2258 | * RETURN VALUES |
2240 | * erp pointer to new ERP-chain head | 2259 | * erp pointer to new ERP-chain head |
2241 | */ | 2260 | */ |
2242 | static struct dasd_ccw_req * | 2261 | static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) |
2243 | dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | ||
2244 | { | 2262 | { |
2245 | 2263 | ||
2246 | struct dasd_device *device = cqr->startdev; | 2264 | struct dasd_device *device = cqr->startdev; |
2247 | struct ccw1 *ccw; | 2265 | struct ccw1 *ccw; |
2248 | |||
2249 | /* allocate additional request block */ | ||
2250 | struct dasd_ccw_req *erp; | 2266 | struct dasd_ccw_req *erp; |
2267 | int cplength, datasize; | ||
2268 | struct tcw *tcw; | ||
2269 | struct tsb *tsb; | ||
2270 | |||
2271 | if (cqr->cpmode == 1) { | ||
2272 | cplength = 0; | ||
2273 | datasize = sizeof(struct tcw) + sizeof(struct tsb); | ||
2274 | } else { | ||
2275 | cplength = 2; | ||
2276 | datasize = 0; | ||
2277 | } | ||
2251 | 2278 | ||
2252 | erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, device); | 2279 | /* allocate additional request block */ |
2280 | erp = dasd_alloc_erp_request((char *) &cqr->magic, | ||
2281 | cplength, datasize, device); | ||
2253 | if (IS_ERR(erp)) { | 2282 | if (IS_ERR(erp)) { |
2254 | if (cqr->retries <= 0) { | 2283 | if (cqr->retries <= 0) { |
2255 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2284 | DBF_DEV_EVENT(DBF_ERR, device, "%s", |
2256 | "Unable to allocate ERP request"); | 2285 | "Unable to allocate ERP request"); |
2257 | cqr->status = DASD_CQR_FAILED; | 2286 | cqr->status = DASD_CQR_FAILED; |
2258 | cqr->stopclk = get_clock (); | 2287 | cqr->stopclk = get_clock (); |
2259 | } else { | 2288 | } else { |
2260 | DEV_MESSAGE (KERN_ERR, device, | 2289 | DBF_DEV_EVENT(DBF_ERR, device, |
2261 | "Unable to allocate ERP request " | 2290 | "Unable to allocate ERP request " |
2262 | "(%i retries left)", | 2291 | "(%i retries left)", |
2263 | cqr->retries); | 2292 | cqr->retries); |
@@ -2266,13 +2295,24 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2266 | return cqr; | 2295 | return cqr; |
2267 | } | 2296 | } |
2268 | 2297 | ||
2269 | /* initialize request with default TIC to current ERP/CQR */ | 2298 | if (cqr->cpmode == 1) { |
2270 | ccw = erp->cpaddr; | 2299 | /* make a shallow copy of the original tcw but set new tsb */ |
2271 | ccw->cmd_code = CCW_CMD_NOOP; | 2300 | erp->cpmode = 1; |
2272 | ccw->flags = CCW_FLAG_CC; | 2301 | erp->cpaddr = erp->data; |
2273 | ccw++; | 2302 | tcw = erp->data; |
2274 | ccw->cmd_code = CCW_CMD_TIC; | 2303 | tsb = (struct tsb *) &tcw[1]; |
2275 | ccw->cda = (long)(cqr->cpaddr); | 2304 | *tcw = *((struct tcw *)cqr->cpaddr); |
2305 | tcw->tsb = (long)tsb; | ||
2306 | } else { | ||
2307 | /* initialize request with default TIC to current ERP/CQR */ | ||
2308 | ccw = erp->cpaddr; | ||
2309 | ccw->cmd_code = CCW_CMD_NOOP; | ||
2310 | ccw->flags = CCW_FLAG_CC; | ||
2311 | ccw++; | ||
2312 | ccw->cmd_code = CCW_CMD_TIC; | ||
2313 | ccw->cda = (long)(cqr->cpaddr); | ||
2314 | } | ||
2315 | |||
2276 | erp->function = dasd_3990_erp_add_erp; | 2316 | erp->function = dasd_3990_erp_add_erp; |
2277 | erp->refers = cqr; | 2317 | erp->refers = cqr; |
2278 | erp->startdev = device; | 2318 | erp->startdev = device; |
@@ -2282,7 +2322,6 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2282 | erp->expires = 0; | 2322 | erp->expires = 0; |
2283 | erp->retries = 256; | 2323 | erp->retries = 256; |
2284 | erp->buildclk = get_clock(); | 2324 | erp->buildclk = get_clock(); |
2285 | |||
2286 | erp->status = DASD_CQR_FILLED; | 2325 | erp->status = DASD_CQR_FILLED; |
2287 | 2326 | ||
2288 | return erp; | 2327 | return erp; |
@@ -2340,28 +2379,33 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr) | |||
2340 | * match 'boolean' for match found | 2379 | * match 'boolean' for match found |
2341 | * returns 1 if match found, otherwise 0. | 2380 | * returns 1 if match found, otherwise 0. |
2342 | */ | 2381 | */ |
2343 | static int | 2382 | static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, |
2344 | dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) | 2383 | struct dasd_ccw_req *cqr2) |
2345 | { | 2384 | { |
2385 | char *sense1, *sense2; | ||
2346 | 2386 | ||
2347 | if (cqr1->startdev != cqr2->startdev) | 2387 | if (cqr1->startdev != cqr2->startdev) |
2348 | return 0; | 2388 | return 0; |
2349 | 2389 | ||
2350 | if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons) | 2390 | sense1 = dasd_get_sense(&cqr1->irb); |
2351 | return 0; | 2391 | sense2 = dasd_get_sense(&cqr2->irb); |
2352 | 2392 | ||
2353 | if ((cqr1->irb.esw.esw0.erw.cons == 0) && | 2393 | /* one request has sense data, the other not -> no match, return 0 */ |
2354 | (cqr2->irb.esw.esw0.erw.cons == 0)) { | 2394 | if (!sense1 != !sense2) |
2355 | if ((cqr1->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | | 2395 | return 0; |
2356 | SCHN_STAT_CHN_CTRL_CHK)) == | 2396 | /* no sense data in both cases -> check cstat for IFCC */ |
2357 | (cqr2->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | | 2397 | if (!sense1 && !sense2) { |
2358 | SCHN_STAT_CHN_CTRL_CHK))) | 2398 | if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | |
2399 | SCHN_STAT_CHN_CTRL_CHK)) == | ||
2400 | (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | | ||
2401 | SCHN_STAT_CHN_CTRL_CHK))) | ||
2359 | return 1; /* match with ifcc*/ | 2402 | return 1; /* match with ifcc*/ |
2360 | } | 2403 | } |
2361 | /* check sense data; byte 0-2,25,27 */ | 2404 | /* check sense data; byte 0-2,25,27 */ |
2362 | if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && | 2405 | if (!(sense1 && sense2 && |
2363 | (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && | 2406 | (memcmp(sense1, sense2, 3) == 0) && |
2364 | (cqr1->irb.ecw[25] == cqr2->irb.ecw[25]))) { | 2407 | (sense1[27] == sense2[27]) && |
2408 | (sense1[25] == sense2[25]))) { | ||
2365 | 2409 | ||
2366 | return 0; /* sense doesn't match */ | 2410 | return 0; /* sense doesn't match */ |
2367 | } | 2411 | } |
@@ -2434,7 +2478,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2434 | { | 2478 | { |
2435 | 2479 | ||
2436 | struct dasd_device *device = erp->startdev; | 2480 | struct dasd_device *device = erp->startdev; |
2437 | char *sense = erp->irb.ecw; | 2481 | char *sense = dasd_get_sense(&erp->irb); |
2438 | 2482 | ||
2439 | /* check for 24 byte sense ERP */ | 2483 | /* check for 24 byte sense ERP */ |
2440 | if ((erp->function == dasd_3990_erp_bus_out) || | 2484 | if ((erp->function == dasd_3990_erp_bus_out) || |
@@ -2449,7 +2493,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2449 | /* prepare erp for retry on different channel path */ | 2493 | /* prepare erp for retry on different channel path */ |
2450 | erp = dasd_3990_erp_action_1(erp); | 2494 | erp = dasd_3990_erp_action_1(erp); |
2451 | 2495 | ||
2452 | if (!(sense[2] & DASD_SENSE_BIT_0)) { | 2496 | if (sense && !(sense[2] & DASD_SENSE_BIT_0)) { |
2453 | 2497 | ||
2454 | /* issue a Diagnostic Control command with an | 2498 | /* issue a Diagnostic Control command with an |
2455 | * Inhibit Write subcommand */ | 2499 | * Inhibit Write subcommand */ |
@@ -2471,7 +2515,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2471 | break; | 2515 | break; |
2472 | } | 2516 | } |
2473 | default: | 2517 | default: |
2474 | DEV_MESSAGE(KERN_DEBUG, device, | 2518 | DBF_DEV_EVENT(DBF_WARNING, device, |
2475 | "invalid subcommand modifier 0x%x " | 2519 | "invalid subcommand modifier 0x%x " |
2476 | "for Diagnostic Control Command", | 2520 | "for Diagnostic Control Command", |
2477 | sense[25]); | 2521 | sense[25]); |
@@ -2479,19 +2523,21 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2479 | } | 2523 | } |
2480 | 2524 | ||
2481 | /* check for 32 byte sense ERP */ | 2525 | /* check for 32 byte sense ERP */ |
2482 | } else if ((erp->function == dasd_3990_erp_compound_retry) || | 2526 | } else if (sense && |
2483 | (erp->function == dasd_3990_erp_compound_path) || | 2527 | ((erp->function == dasd_3990_erp_compound_retry) || |
2484 | (erp->function == dasd_3990_erp_compound_code) || | 2528 | (erp->function == dasd_3990_erp_compound_path) || |
2485 | (erp->function == dasd_3990_erp_compound_config)) { | 2529 | (erp->function == dasd_3990_erp_compound_code) || |
2530 | (erp->function == dasd_3990_erp_compound_config))) { | ||
2486 | 2531 | ||
2487 | erp = dasd_3990_erp_compound(erp, sense); | 2532 | erp = dasd_3990_erp_compound(erp, sense); |
2488 | 2533 | ||
2489 | } else { | 2534 | } else { |
2490 | /* No retry left and no additional special handling */ | 2535 | /* |
2491 | /*necessary */ | 2536 | * No retry left and no additional special handling |
2492 | DEV_MESSAGE(KERN_ERR, device, | 2537 | * necessary |
2493 | "no retries left for erp %p - " | 2538 | */ |
2494 | "set status to FAILED", erp); | 2539 | dev_err(&device->cdev->dev, |
2540 | "ERP %p has run out of retries and failed\n", erp); | ||
2495 | 2541 | ||
2496 | erp->status = DASD_CQR_FAILED; | 2542 | erp->status = DASD_CQR_FAILED; |
2497 | } | 2543 | } |
@@ -2548,24 +2594,25 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2548 | 2594 | ||
2549 | if (erp->retries > 0) { | 2595 | if (erp->retries > 0) { |
2550 | 2596 | ||
2551 | char *sense = erp->refers->irb.ecw; | 2597 | char *sense = dasd_get_sense(&erp->refers->irb); |
2552 | 2598 | ||
2553 | /* check for special retries */ | 2599 | /* check for special retries */ |
2554 | if (erp->function == dasd_3990_erp_action_4) { | 2600 | if (sense && erp->function == dasd_3990_erp_action_4) { |
2555 | 2601 | ||
2556 | erp = dasd_3990_erp_action_4(erp, sense); | 2602 | erp = dasd_3990_erp_action_4(erp, sense); |
2557 | 2603 | ||
2558 | } else if (erp->function == dasd_3990_erp_action_1B_32) { | 2604 | } else if (sense && |
2605 | erp->function == dasd_3990_erp_action_1B_32) { | ||
2559 | 2606 | ||
2560 | erp = dasd_3990_update_1B(erp, sense); | 2607 | erp = dasd_3990_update_1B(erp, sense); |
2561 | 2608 | ||
2562 | } else if (erp->function == dasd_3990_erp_int_req) { | 2609 | } else if (sense && erp->function == dasd_3990_erp_int_req) { |
2563 | 2610 | ||
2564 | erp = dasd_3990_erp_int_req(erp); | 2611 | erp = dasd_3990_erp_int_req(erp); |
2565 | 2612 | ||
2566 | } else { | 2613 | } else { |
2567 | /* simple retry */ | 2614 | /* simple retry */ |
2568 | DEV_MESSAGE(KERN_DEBUG, device, | 2615 | DBF_DEV_EVENT(DBF_DEBUG, device, |
2569 | "%i retries left for erp %p", | 2616 | "%i retries left for erp %p", |
2570 | erp->retries, erp); | 2617 | erp->retries, erp); |
2571 | 2618 | ||
@@ -2609,24 +2656,24 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2609 | 2656 | ||
2610 | if (device->features & DASD_FEATURE_ERPLOG) { | 2657 | if (device->features & DASD_FEATURE_ERPLOG) { |
2611 | /* print current erp_chain */ | 2658 | /* print current erp_chain */ |
2612 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2659 | dev_err(&device->cdev->dev, |
2613 | "ERP chain at BEGINNING of ERP-ACTION"); | 2660 | "ERP chain at BEGINNING of ERP-ACTION\n"); |
2614 | for (temp_erp = cqr; | 2661 | for (temp_erp = cqr; |
2615 | temp_erp != NULL; temp_erp = temp_erp->refers) { | 2662 | temp_erp != NULL; temp_erp = temp_erp->refers) { |
2616 | 2663 | ||
2617 | DEV_MESSAGE(KERN_ERR, device, | 2664 | dev_err(&device->cdev->dev, |
2618 | " erp %p (%02x) refers to %p", | 2665 | "ERP %p (%02x) refers to %p\n", |
2619 | temp_erp, temp_erp->status, | 2666 | temp_erp, temp_erp->status, |
2620 | temp_erp->refers); | 2667 | temp_erp->refers); |
2621 | } | 2668 | } |
2622 | } | 2669 | } |
2623 | 2670 | ||
2624 | /* double-check if current erp/cqr was successful */ | 2671 | /* double-check if current erp/cqr was successful */ |
2625 | if ((cqr->irb.scsw.cmd.cstat == 0x00) && | 2672 | if ((scsw_cstat(&cqr->irb.scsw) == 0x00) && |
2626 | (cqr->irb.scsw.cmd.dstat == | 2673 | (scsw_dstat(&cqr->irb.scsw) == |
2627 | (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { | 2674 | (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { |
2628 | 2675 | ||
2629 | DEV_MESSAGE(KERN_DEBUG, device, | 2676 | DBF_DEV_EVENT(DBF_DEBUG, device, |
2630 | "ERP called for successful request %p" | 2677 | "ERP called for successful request %p" |
2631 | " - NO ERP necessary", cqr); | 2678 | " - NO ERP necessary", cqr); |
2632 | 2679 | ||
@@ -2648,13 +2695,13 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2648 | 2695 | ||
2649 | if (device->features & DASD_FEATURE_ERPLOG) { | 2696 | if (device->features & DASD_FEATURE_ERPLOG) { |
2650 | /* print current erp_chain */ | 2697 | /* print current erp_chain */ |
2651 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2698 | dev_err(&device->cdev->dev, |
2652 | "ERP chain at END of ERP-ACTION"); | 2699 | "ERP chain at END of ERP-ACTION\n"); |
2653 | for (temp_erp = erp; | 2700 | for (temp_erp = erp; |
2654 | temp_erp != NULL; temp_erp = temp_erp->refers) { | 2701 | temp_erp != NULL; temp_erp = temp_erp->refers) { |
2655 | 2702 | ||
2656 | DEV_MESSAGE(KERN_ERR, device, | 2703 | dev_err(&device->cdev->dev, |
2657 | " erp %p (%02x) refers to %p", | 2704 | "ERP %p (%02x) refers to %p\n", |
2658 | temp_erp, temp_erp->status, | 2705 | temp_erp, temp_erp->status, |
2659 | temp_erp->refers); | 2706 | temp_erp->refers); |
2660 | } | 2707 | } |
@@ -2667,6 +2714,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2667 | list_add_tail(&erp->blocklist, &cqr->blocklist); | 2714 | list_add_tail(&erp->blocklist, &cqr->blocklist); |
2668 | } | 2715 | } |
2669 | 2716 | ||
2717 | |||
2718 | |||
2670 | return erp; | 2719 | return erp; |
2671 | 2720 | ||
2672 | } /* end dasd_3990_erp_action */ | 2721 | } /* end dasd_3990_erp_action */ |
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 20676cdef4a5..5b7bbc87593b 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> | 5 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define KMSG_COMPONENT "dasd" | ||
9 | |||
8 | #include <linux/list.h> | 10 | #include <linux/list.h> |
9 | #include <asm/ebcdic.h> | 11 | #include <asm/ebcdic.h> |
10 | #include "dasd_int.h" | 12 | #include "dasd_int.h" |
@@ -503,7 +505,7 @@ static void lcu_update_work(struct work_struct *work) | |||
503 | */ | 505 | */ |
504 | spin_lock_irqsave(&lcu->lock, flags); | 506 | spin_lock_irqsave(&lcu->lock, flags); |
505 | if (rc || (lcu->flags & NEED_UAC_UPDATE)) { | 507 | if (rc || (lcu->flags & NEED_UAC_UPDATE)) { |
506 | DEV_MESSAGE(KERN_WARNING, device, "could not update" | 508 | DBF_DEV_EVENT(DBF_WARNING, device, "could not update" |
507 | " alias data in lcu (rc = %d), retry later", rc); | 509 | " alias data in lcu (rc = %d), retry later", rc); |
508 | schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); | 510 | schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); |
509 | } else { | 511 | } else { |
@@ -646,14 +648,16 @@ static int reset_summary_unit_check(struct alias_lcu *lcu, | |||
646 | { | 648 | { |
647 | struct dasd_ccw_req *cqr; | 649 | struct dasd_ccw_req *cqr; |
648 | int rc = 0; | 650 | int rc = 0; |
651 | struct ccw1 *ccw; | ||
649 | 652 | ||
650 | cqr = lcu->rsu_cqr; | 653 | cqr = lcu->rsu_cqr; |
651 | strncpy((char *) &cqr->magic, "ECKD", 4); | 654 | strncpy((char *) &cqr->magic, "ECKD", 4); |
652 | ASCEBC((char *) &cqr->magic, 4); | 655 | ASCEBC((char *) &cqr->magic, 4); |
653 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RSCK; | 656 | ccw = cqr->cpaddr; |
654 | cqr->cpaddr->flags = 0 ; | 657 | ccw->cmd_code = DASD_ECKD_CCW_RSCK; |
655 | cqr->cpaddr->count = 16; | 658 | ccw->flags = 0 ; |
656 | cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; | 659 | ccw->count = 16; |
660 | ccw->cda = (__u32)(addr_t) cqr->data; | ||
657 | ((char *)cqr->data)[0] = reason; | 661 | ((char *)cqr->data)[0] = reason; |
658 | 662 | ||
659 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 663 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
@@ -855,16 +859,25 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, | |||
855 | struct alias_lcu *lcu; | 859 | struct alias_lcu *lcu; |
856 | char reason; | 860 | char reason; |
857 | struct dasd_eckd_private *private; | 861 | struct dasd_eckd_private *private; |
862 | char *sense; | ||
858 | 863 | ||
859 | private = (struct dasd_eckd_private *) device->private; | 864 | private = (struct dasd_eckd_private *) device->private; |
860 | 865 | ||
861 | reason = irb->ecw[8]; | 866 | sense = dasd_get_sense(irb); |
862 | DEV_MESSAGE(KERN_WARNING, device, "%s %x", | 867 | if (sense) { |
863 | "eckd handle summary unit check: reason", reason); | 868 | reason = sense[8]; |
869 | DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x", | ||
870 | "eckd handle summary unit check: reason", reason); | ||
871 | } else { | ||
872 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | ||
873 | "eckd handle summary unit check:" | ||
874 | " no reason code available"); | ||
875 | return; | ||
876 | } | ||
864 | 877 | ||
865 | lcu = private->lcu; | 878 | lcu = private->lcu; |
866 | if (!lcu) { | 879 | if (!lcu) { |
867 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 880 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
868 | "device not ready to handle summary" | 881 | "device not ready to handle summary" |
869 | " unit check (no lcu structure)"); | 882 | " unit check (no lcu structure)"); |
870 | return; | 883 | return; |
@@ -877,7 +890,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, | |||
877 | * the next interrupt on a different device | 890 | * the next interrupt on a different device |
878 | */ | 891 | */ |
879 | if (list_empty(&device->alias_list)) { | 892 | if (list_empty(&device->alias_list)) { |
880 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 893 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
881 | "device is in offline processing," | 894 | "device is in offline processing," |
882 | " don't do summary unit check handling"); | 895 | " don't do summary unit check handling"); |
883 | spin_unlock(&lcu->lock); | 896 | spin_unlock(&lcu->lock); |
@@ -885,7 +898,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, | |||
885 | } | 898 | } |
886 | if (lcu->suc_data.device) { | 899 | if (lcu->suc_data.device) { |
887 | /* already scheduled or running */ | 900 | /* already scheduled or running */ |
888 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 901 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
889 | "previous instance of summary unit check worker" | 902 | "previous instance of summary unit check worker" |
890 | " still pending"); | 903 | " still pending"); |
891 | spin_unlock(&lcu->lock); | 904 | spin_unlock(&lcu->lock); |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 34339902efb9..e77666c8e6c0 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -13,6 +13,8 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #define KMSG_COMPONENT "dasd" | ||
17 | |||
16 | #include <linux/ctype.h> | 18 | #include <linux/ctype.h> |
17 | #include <linux/init.h> | 19 | #include <linux/init.h> |
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -67,6 +69,8 @@ int dasd_probeonly = 0; /* is true, when probeonly mode is active */ | |||
67 | int dasd_autodetect = 0; /* is true, when autodetection is active */ | 69 | int dasd_autodetect = 0; /* is true, when autodetection is active */ |
68 | int dasd_nopav = 0; /* is true, when PAV is disabled */ | 70 | int dasd_nopav = 0; /* is true, when PAV is disabled */ |
69 | EXPORT_SYMBOL_GPL(dasd_nopav); | 71 | EXPORT_SYMBOL_GPL(dasd_nopav); |
72 | int dasd_nofcx; /* disable High Performance Ficon */ | ||
73 | EXPORT_SYMBOL_GPL(dasd_nofcx); | ||
70 | 74 | ||
71 | /* | 75 | /* |
72 | * char *dasd[] is intended to hold the ranges supplied by the dasd= statement | 76 | * char *dasd[] is intended to hold the ranges supplied by the dasd= statement |
@@ -125,6 +129,7 @@ __setup ("dasd=", dasd_call_setup); | |||
125 | * Read a device busid/devno from a string. | 129 | * Read a device busid/devno from a string. |
126 | */ | 130 | */ |
127 | static int | 131 | static int |
132 | |||
128 | dasd_busid(char **str, int *id0, int *id1, int *devno) | 133 | dasd_busid(char **str, int *id0, int *id1, int *devno) |
129 | { | 134 | { |
130 | int val, old_style; | 135 | int val, old_style; |
@@ -132,8 +137,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno) | |||
132 | /* Interpret ipldev busid */ | 137 | /* Interpret ipldev busid */ |
133 | if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) { | 138 | if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) { |
134 | if (ipl_info.type != IPL_TYPE_CCW) { | 139 | if (ipl_info.type != IPL_TYPE_CCW) { |
135 | MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw " | 140 | pr_err("The IPL device is not a CCW device\n"); |
136 | "device"); | ||
137 | return -EINVAL; | 141 | return -EINVAL; |
138 | } | 142 | } |
139 | *id0 = 0; | 143 | *id0 = 0; |
@@ -209,9 +213,8 @@ dasd_feature_list(char *str, char **endp) | |||
209 | else if (len == 8 && !strncmp(str, "failfast", 8)) | 213 | else if (len == 8 && !strncmp(str, "failfast", 8)) |
210 | features |= DASD_FEATURE_FAILFAST; | 214 | features |= DASD_FEATURE_FAILFAST; |
211 | else { | 215 | else { |
212 | MESSAGE(KERN_WARNING, | 216 | pr_warning("%*s is not a supported device option\n", |
213 | "unsupported feature: %*s, " | 217 | len, str); |
214 | "ignoring setting", len, str); | ||
215 | rc = -EINVAL; | 218 | rc = -EINVAL; |
216 | } | 219 | } |
217 | str += len; | 220 | str += len; |
@@ -220,8 +223,8 @@ dasd_feature_list(char *str, char **endp) | |||
220 | str++; | 223 | str++; |
221 | } | 224 | } |
222 | if (*str != ')') { | 225 | if (*str != ')') { |
223 | MESSAGE(KERN_WARNING, "%s", | 226 | pr_warning("A closing parenthesis ')' is missing in the " |
224 | "missing ')' in dasd parameter string\n"); | 227 | "dasd= parameter\n"); |
225 | rc = -EINVAL; | 228 | rc = -EINVAL; |
226 | } else | 229 | } else |
227 | str++; | 230 | str++; |
@@ -253,25 +256,29 @@ dasd_parse_keyword( char *parsestring ) { | |||
253 | } | 256 | } |
254 | if (strncmp("autodetect", parsestring, length) == 0) { | 257 | if (strncmp("autodetect", parsestring, length) == 0) { |
255 | dasd_autodetect = 1; | 258 | dasd_autodetect = 1; |
256 | MESSAGE (KERN_INFO, "%s", | 259 | pr_info("The autodetection mode has been activated\n"); |
257 | "turning to autodetection mode"); | ||
258 | return residual_str; | 260 | return residual_str; |
259 | } | 261 | } |
260 | if (strncmp("probeonly", parsestring, length) == 0) { | 262 | if (strncmp("probeonly", parsestring, length) == 0) { |
261 | dasd_probeonly = 1; | 263 | dasd_probeonly = 1; |
262 | MESSAGE(KERN_INFO, "%s", | 264 | pr_info("The probeonly mode has been activated\n"); |
263 | "turning to probeonly mode"); | ||
264 | return residual_str; | 265 | return residual_str; |
265 | } | 266 | } |
266 | if (strncmp("nopav", parsestring, length) == 0) { | 267 | if (strncmp("nopav", parsestring, length) == 0) { |
267 | if (MACHINE_IS_VM) | 268 | if (MACHINE_IS_VM) |
268 | MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM"); | 269 | pr_info("'nopav' is not supported on z/VM\n"); |
269 | else { | 270 | else { |
270 | dasd_nopav = 1; | 271 | dasd_nopav = 1; |
271 | MESSAGE(KERN_INFO, "%s", "disable PAV mode"); | 272 | pr_info("PAV support has be deactivated\n"); |
272 | } | 273 | } |
273 | return residual_str; | 274 | return residual_str; |
274 | } | 275 | } |
276 | if (strncmp("nofcx", parsestring, length) == 0) { | ||
277 | dasd_nofcx = 1; | ||
278 | pr_info("High Performance FICON support has been " | ||
279 | "deactivated\n"); | ||
280 | return residual_str; | ||
281 | } | ||
275 | if (strncmp("fixedbuffers", parsestring, length) == 0) { | 282 | if (strncmp("fixedbuffers", parsestring, length) == 0) { |
276 | if (dasd_page_cache) | 283 | if (dasd_page_cache) |
277 | return residual_str; | 284 | return residual_str; |
@@ -280,10 +287,10 @@ dasd_parse_keyword( char *parsestring ) { | |||
280 | PAGE_SIZE, SLAB_CACHE_DMA, | 287 | PAGE_SIZE, SLAB_CACHE_DMA, |
281 | NULL); | 288 | NULL); |
282 | if (!dasd_page_cache) | 289 | if (!dasd_page_cache) |
283 | MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " | 290 | DBF_EVENT(DBF_WARNING, "%s", "Failed to create slab, " |
284 | "fixed buffer mode disabled."); | 291 | "fixed buffer mode disabled."); |
285 | else | 292 | else |
286 | MESSAGE (KERN_INFO, "%s", | 293 | DBF_EVENT(DBF_INFO, "%s", |
287 | "turning on fixed buffer mode"); | 294 | "turning on fixed buffer mode"); |
288 | return residual_str; | 295 | return residual_str; |
289 | } | 296 | } |
@@ -321,7 +328,7 @@ dasd_parse_range( char *parsestring ) { | |||
321 | (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) | 328 | (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) |
322 | rc = -EINVAL; | 329 | rc = -EINVAL; |
323 | if (rc) { | 330 | if (rc) { |
324 | MESSAGE(KERN_ERR, "Invalid device range %s", parsestring); | 331 | pr_err("%s is not a valid device range\n", parsestring); |
325 | return ERR_PTR(rc); | 332 | return ERR_PTR(rc); |
326 | } | 333 | } |
327 | features = dasd_feature_list(str, &str); | 334 | features = dasd_feature_list(str, &str); |
@@ -340,8 +347,8 @@ dasd_parse_range( char *parsestring ) { | |||
340 | return str + 1; | 347 | return str + 1; |
341 | if (*str == '\0') | 348 | if (*str == '\0') |
342 | return str; | 349 | return str; |
343 | MESSAGE(KERN_WARNING, | 350 | pr_warning("The dasd= parameter value %s has an invalid ending\n", |
344 | "junk at end of dasd parameter string: %s\n", str); | 351 | str); |
345 | return ERR_PTR(-EINVAL); | 352 | return ERR_PTR(-EINVAL); |
346 | } | 353 | } |
347 | 354 | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index ef2a56952054..b9a7f7733446 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "dasd" | ||
12 | |||
11 | #include <linux/stddef.h> | 13 | #include <linux/stddef.h> |
12 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
13 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
@@ -144,8 +146,8 @@ dasd_diag_erp(struct dasd_device *device) | |||
144 | mdsk_term_io(device); | 146 | mdsk_term_io(device); |
145 | rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); | 147 | rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); |
146 | if (rc) | 148 | if (rc) |
147 | DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, " | 149 | dev_warn(&device->cdev->dev, "DIAG ERP failed with " |
148 | "rc=%d", rc); | 150 | "rc=%d\n", rc); |
149 | } | 151 | } |
150 | 152 | ||
151 | /* Start a given request at the device. Return zero on success, non-zero | 153 | /* 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) | |||
160 | 162 | ||
161 | device = cqr->startdev; | 163 | device = cqr->startdev; |
162 | if (cqr->retries < 0) { | 164 | if (cqr->retries < 0) { |
163 | DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p " | 165 | DBF_DEV_EVENT(DBF_ERR, device, "DIAG start_IO: request %p " |
164 | "- no retry left)", cqr); | 166 | "- no retry left)", cqr); |
165 | cqr->status = DASD_CQR_ERROR; | 167 | cqr->status = DASD_CQR_ERROR; |
166 | return -EIO; | 168 | return -EIO; |
@@ -195,7 +197,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) | |||
195 | break; | 197 | break; |
196 | default: /* Error condition */ | 198 | default: /* Error condition */ |
197 | cqr->status = DASD_CQR_QUEUED; | 199 | cqr->status = DASD_CQR_QUEUED; |
198 | DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc); | 200 | DBF_DEV_EVENT(DBF_WARNING, device, "dia250 returned rc=%d", rc); |
199 | dasd_diag_erp(device); | 201 | dasd_diag_erp(device); |
200 | rc = -EIO; | 202 | rc = -EIO; |
201 | break; | 203 | break; |
@@ -243,13 +245,14 @@ dasd_ext_handler(__u16 code) | |||
243 | return; | 245 | return; |
244 | } | 246 | } |
245 | if (!ip) { /* no intparm: unsolicited interrupt */ | 247 | if (!ip) { /* no intparm: unsolicited interrupt */ |
246 | MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); | 248 | DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " |
249 | "interrupt"); | ||
247 | return; | 250 | return; |
248 | } | 251 | } |
249 | cqr = (struct dasd_ccw_req *) ip; | 252 | cqr = (struct dasd_ccw_req *) ip; |
250 | device = (struct dasd_device *) cqr->startdev; | 253 | device = (struct dasd_device *) cqr->startdev; |
251 | if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { | 254 | if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { |
252 | DEV_MESSAGE(KERN_WARNING, device, | 255 | DBF_DEV_EVENT(DBF_WARNING, device, |
253 | " magic number of dasd_ccw_req 0x%08X doesn't" | 256 | " magic number of dasd_ccw_req 0x%08X doesn't" |
254 | " match discipline 0x%08X", | 257 | " match discipline 0x%08X", |
255 | cqr->magic, *(int *) (&device->discipline->name)); | 258 | cqr->magic, *(int *) (&device->discipline->name)); |
@@ -281,15 +284,11 @@ dasd_ext_handler(__u16 code) | |||
281 | rc = dasd_start_diag(next); | 284 | rc = dasd_start_diag(next); |
282 | if (rc == 0) | 285 | if (rc == 0) |
283 | expires = next->expires; | 286 | expires = next->expires; |
284 | else if (rc != -EACCES) | ||
285 | DEV_MESSAGE(KERN_WARNING, device, "%s", | ||
286 | "Interrupt fastpath " | ||
287 | "failed!"); | ||
288 | } | 287 | } |
289 | } | 288 | } |
290 | } else { | 289 | } else { |
291 | cqr->status = DASD_CQR_QUEUED; | 290 | cqr->status = DASD_CQR_QUEUED; |
292 | DEV_MESSAGE(KERN_WARNING, device, "interrupt status for " | 291 | DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for " |
293 | "request %p was %d (%d retries left)", cqr, status, | 292 | "request %p was %d (%d retries left)", cqr, status, |
294 | cqr->retries); | 293 | cqr->retries); |
295 | dasd_diag_erp(device); | 294 | dasd_diag_erp(device); |
@@ -322,8 +321,9 @@ dasd_diag_check_device(struct dasd_device *device) | |||
322 | if (private == NULL) { | 321 | if (private == NULL) { |
323 | private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); | 322 | private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); |
324 | if (private == NULL) { | 323 | if (private == NULL) { |
325 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 324 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
326 | "memory allocation failed for private data"); | 325 | "Allocating memory for private DASD data " |
326 | "failed\n"); | ||
327 | return -ENOMEM; | 327 | return -ENOMEM; |
328 | } | 328 | } |
329 | ccw_device_get_id(device->cdev, &private->dev_id); | 329 | ccw_device_get_id(device->cdev, &private->dev_id); |
@@ -331,7 +331,7 @@ dasd_diag_check_device(struct dasd_device *device) | |||
331 | } | 331 | } |
332 | block = dasd_alloc_block(); | 332 | block = dasd_alloc_block(); |
333 | if (IS_ERR(block)) { | 333 | if (IS_ERR(block)) { |
334 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 334 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
335 | "could not allocate dasd block structure"); | 335 | "could not allocate dasd block structure"); |
336 | device->private = NULL; | 336 | device->private = NULL; |
337 | kfree(private); | 337 | kfree(private); |
@@ -347,7 +347,7 @@ dasd_diag_check_device(struct dasd_device *device) | |||
347 | 347 | ||
348 | rc = diag210((struct diag210 *) rdc_data); | 348 | rc = diag210((struct diag210 *) rdc_data); |
349 | if (rc) { | 349 | if (rc) { |
350 | DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device " | 350 | DBF_DEV_EVENT(DBF_WARNING, device, "failed to retrieve device " |
351 | "information (rc=%d)", rc); | 351 | "information (rc=%d)", rc); |
352 | rc = -EOPNOTSUPP; | 352 | rc = -EOPNOTSUPP; |
353 | goto out; | 353 | goto out; |
@@ -362,8 +362,8 @@ dasd_diag_check_device(struct dasd_device *device) | |||
362 | private->pt_block = 2; | 362 | private->pt_block = 2; |
363 | break; | 363 | break; |
364 | default: | 364 | default: |
365 | DEV_MESSAGE(KERN_WARNING, device, "unsupported device class " | 365 | dev_warn(&device->cdev->dev, "Device type %d is not supported " |
366 | "(class=%d)", private->rdc_data.vdev_class); | 366 | "in DIAG mode\n", private->rdc_data.vdev_class); |
367 | rc = -EOPNOTSUPP; | 367 | rc = -EOPNOTSUPP; |
368 | goto out; | 368 | goto out; |
369 | } | 369 | } |
@@ -380,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device) | |||
380 | /* figure out blocksize of device */ | 380 | /* figure out blocksize of device */ |
381 | label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL); | 381 | label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL); |
382 | if (label == NULL) { | 382 | if (label == NULL) { |
383 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 383 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
384 | "No memory to allocate initialization request"); | 384 | "No memory to allocate initialization request"); |
385 | rc = -ENOMEM; | 385 | rc = -ENOMEM; |
386 | goto out; | 386 | goto out; |
@@ -404,8 +404,8 @@ dasd_diag_check_device(struct dasd_device *device) | |||
404 | private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; | 404 | private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; |
405 | rc = dia250(&private->iob, RW_BIO); | 405 | rc = dia250(&private->iob, RW_BIO); |
406 | if (rc == 3) { | 406 | if (rc == 3) { |
407 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 407 | dev_warn(&device->cdev->dev, |
408 | "DIAG call failed"); | 408 | "A 64-bit DIAG call failed\n"); |
409 | rc = -EOPNOTSUPP; | 409 | rc = -EOPNOTSUPP; |
410 | goto out_label; | 410 | goto out_label; |
411 | } | 411 | } |
@@ -414,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device) | |||
414 | break; | 414 | break; |
415 | } | 415 | } |
416 | if (bsize > PAGE_SIZE) { | 416 | if (bsize > PAGE_SIZE) { |
417 | DEV_MESSAGE(KERN_WARNING, device, "device access failed " | 417 | dev_warn(&device->cdev->dev, "Accessing the DASD failed because" |
418 | "(rc=%d)", rc); | 418 | " of an incorrect format (rc=%d)\n", rc); |
419 | rc = -EIO; | 419 | rc = -EIO; |
420 | goto out_label; | 420 | goto out_label; |
421 | } | 421 | } |
@@ -433,15 +433,15 @@ dasd_diag_check_device(struct dasd_device *device) | |||
433 | block->s2b_shift++; | 433 | block->s2b_shift++; |
434 | rc = mdsk_init_io(device, block->bp_block, 0, NULL); | 434 | rc = mdsk_init_io(device, block->bp_block, 0, NULL); |
435 | if (rc) { | 435 | if (rc) { |
436 | DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization " | 436 | dev_warn(&device->cdev->dev, "DIAG initialization " |
437 | "failed (rc=%d)", rc); | 437 | "failed with rc=%d\n", rc); |
438 | rc = -EIO; | 438 | rc = -EIO; |
439 | } else { | 439 | } else { |
440 | DEV_MESSAGE(KERN_INFO, device, | 440 | dev_info(&device->cdev->dev, |
441 | "(%ld B/blk): %ldkB", | 441 | "New DASD with %ld byte/block, total size %ld KB\n", |
442 | (unsigned long) block->bp_block, | 442 | (unsigned long) block->bp_block, |
443 | (unsigned long) (block->blocks << | 443 | (unsigned long) (block->blocks << |
444 | block->s2b_shift) >> 1); | 444 | block->s2b_shift) >> 1); |
445 | } | 445 | } |
446 | out_label: | 446 | out_label: |
447 | free_page((long) label); | 447 | free_page((long) label); |
@@ -595,7 +595,7 @@ static void | |||
595 | dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | 595 | dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, |
596 | struct irb *stat) | 596 | struct irb *stat) |
597 | { | 597 | { |
598 | DEV_MESSAGE(KERN_ERR, device, "%s", | 598 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
599 | "dump sense not available for DIAG data"); | 599 | "dump sense not available for DIAG data"); |
600 | } | 600 | } |
601 | 601 | ||
@@ -621,10 +621,8 @@ static int __init | |||
621 | dasd_diag_init(void) | 621 | dasd_diag_init(void) |
622 | { | 622 | { |
623 | if (!MACHINE_IS_VM) { | 623 | if (!MACHINE_IS_VM) { |
624 | MESSAGE_LOG(KERN_INFO, | 624 | pr_info("Discipline %s cannot be used without z/VM\n", |
625 | "Machine is not VM: %s " | 625 | dasd_diag_discipline.name); |
626 | "discipline not initializing", | ||
627 | dasd_diag_discipline.name); | ||
628 | return -ENODEV; | 626 | return -ENODEV; |
629 | } | 627 | } |
630 | ASCEBC(dasd_diag_discipline.ebcname, 4); | 628 | ASCEBC(dasd_diag_discipline.ebcname, 4); |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index bdb87998f364..21254793c604 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "dasd" | ||
15 | |||
14 | #include <linux/stddef.h> | 16 | #include <linux/stddef.h> |
15 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
16 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
@@ -27,9 +29,12 @@ | |||
27 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
28 | #include <asm/cio.h> | 30 | #include <asm/cio.h> |
29 | #include <asm/ccwdev.h> | 31 | #include <asm/ccwdev.h> |
32 | #include <asm/itcw.h> | ||
30 | 33 | ||
31 | #include "dasd_int.h" | 34 | #include "dasd_int.h" |
32 | #include "dasd_eckd.h" | 35 | #include "dasd_eckd.h" |
36 | #include "../cio/chsc.h" | ||
37 | |||
33 | 38 | ||
34 | #ifdef PRINTK_HEADER | 39 | #ifdef PRINTK_HEADER |
35 | #undef PRINTK_HEADER | 40 | #undef PRINTK_HEADER |
@@ -84,7 +89,7 @@ dasd_eckd_probe (struct ccw_device *cdev) | |||
84 | /* set ECKD specific ccw-device options */ | 89 | /* set ECKD specific ccw-device options */ |
85 | ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); | 90 | ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); |
86 | if (ret) { | 91 | if (ret) { |
87 | printk(KERN_WARNING | 92 | DBF_EVENT(DBF_WARNING, |
88 | "dasd_eckd_probe: could not set ccw-device options " | 93 | "dasd_eckd_probe: could not set ccw-device options " |
89 | "for %s\n", dev_name(&cdev->dev)); | 94 | "for %s\n", dev_name(&cdev->dev)); |
90 | return ret; | 95 | return ret; |
@@ -159,6 +164,14 @@ recs_per_track(struct dasd_eckd_characteristics * rdc, | |||
159 | return 0; | 164 | return 0; |
160 | } | 165 | } |
161 | 166 | ||
167 | static void set_ch_t(struct ch_t *geo, __u32 cyl, __u8 head) | ||
168 | { | ||
169 | geo->cyl = (__u16) cyl; | ||
170 | geo->head = cyl >> 16; | ||
171 | geo->head <<= 4; | ||
172 | geo->head |= head; | ||
173 | } | ||
174 | |||
162 | static int | 175 | static int |
163 | check_XRC (struct ccw1 *de_ccw, | 176 | check_XRC (struct ccw1 *de_ccw, |
164 | struct DE_eckd_data *data, | 177 | struct DE_eckd_data *data, |
@@ -186,11 +199,12 @@ check_XRC (struct ccw1 *de_ccw, | |||
186 | } | 199 | } |
187 | 200 | ||
188 | static int | 201 | static int |
189 | define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | 202 | define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk, |
190 | int totrk, int cmd, struct dasd_device * device) | 203 | unsigned int totrk, int cmd, struct dasd_device *device) |
191 | { | 204 | { |
192 | struct dasd_eckd_private *private; | 205 | struct dasd_eckd_private *private; |
193 | struct ch_t geo, beg, end; | 206 | u32 begcyl, endcyl; |
207 | u16 heads, beghead, endhead; | ||
194 | int rc = 0; | 208 | int rc = 0; |
195 | 209 | ||
196 | private = (struct dasd_eckd_private *) device->private; | 210 | private = (struct dasd_eckd_private *) device->private; |
@@ -236,7 +250,8 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | |||
236 | rc = check_XRC (ccw, data, device); | 250 | rc = check_XRC (ccw, data, device); |
237 | break; | 251 | break; |
238 | default: | 252 | default: |
239 | DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); | 253 | dev_err(&device->cdev->dev, |
254 | "0x%x is not a known command\n", cmd); | ||
240 | break; | 255 | break; |
241 | } | 256 | } |
242 | 257 | ||
@@ -248,27 +263,24 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | |||
248 | && !(private->uses_cdl && trk < 2)) | 263 | && !(private->uses_cdl && trk < 2)) |
249 | data->ga_extended |= 0x40; /* Regular Data Format Mode */ | 264 | data->ga_extended |= 0x40; /* Regular Data Format Mode */ |
250 | 265 | ||
251 | geo.cyl = private->rdc_data.no_cyl; | 266 | heads = private->rdc_data.trk_per_cyl; |
252 | geo.head = private->rdc_data.trk_per_cyl; | 267 | begcyl = trk / heads; |
253 | beg.cyl = trk / geo.head; | 268 | beghead = trk % heads; |
254 | beg.head = trk % geo.head; | 269 | endcyl = totrk / heads; |
255 | end.cyl = totrk / geo.head; | 270 | endhead = totrk % heads; |
256 | end.head = totrk % geo.head; | ||
257 | 271 | ||
258 | /* check for sequential prestage - enhance cylinder range */ | 272 | /* check for sequential prestage - enhance cylinder range */ |
259 | if (data->attributes.operation == DASD_SEQ_PRESTAGE || | 273 | if (data->attributes.operation == DASD_SEQ_PRESTAGE || |
260 | data->attributes.operation == DASD_SEQ_ACCESS) { | 274 | data->attributes.operation == DASD_SEQ_ACCESS) { |
261 | 275 | ||
262 | if (end.cyl + private->attrib.nr_cyl < geo.cyl) | 276 | if (endcyl + private->attrib.nr_cyl < private->real_cyl) |
263 | end.cyl += private->attrib.nr_cyl; | 277 | endcyl += private->attrib.nr_cyl; |
264 | else | 278 | else |
265 | end.cyl = (geo.cyl - 1); | 279 | endcyl = (private->real_cyl - 1); |
266 | } | 280 | } |
267 | 281 | ||
268 | data->beg_ext.cyl = beg.cyl; | 282 | set_ch_t(&data->beg_ext, begcyl, beghead); |
269 | data->beg_ext.head = beg.head; | 283 | set_ch_t(&data->end_ext, endcyl, endhead); |
270 | data->end_ext.cyl = end.cyl; | ||
271 | data->end_ext.head = end.head; | ||
272 | return rc; | 284 | return rc; |
273 | } | 285 | } |
274 | 286 | ||
@@ -283,29 +295,145 @@ static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata, | |||
283 | return 0; | 295 | return 0; |
284 | 296 | ||
285 | /* switch on System Time Stamp - needed for XRC Support */ | 297 | /* switch on System Time Stamp - needed for XRC Support */ |
286 | pfxdata->define_extend.ga_extended |= 0x08; /* 'Time Stamp Valid' */ | 298 | pfxdata->define_extent.ga_extended |= 0x08; /* 'Time Stamp Valid' */ |
287 | pfxdata->define_extend.ga_extended |= 0x02; /* 'Extended Parameter' */ | 299 | pfxdata->define_extent.ga_extended |= 0x02; /* 'Extended Parameter' */ |
288 | pfxdata->validity.time_stamp = 1; /* 'Time Stamp Valid' */ | 300 | pfxdata->validity.time_stamp = 1; /* 'Time Stamp Valid' */ |
289 | 301 | ||
290 | rc = get_sync_clock(&pfxdata->define_extend.ep_sys_time); | 302 | rc = get_sync_clock(&pfxdata->define_extent.ep_sys_time); |
291 | /* Ignore return code if sync clock is switched off. */ | 303 | /* Ignore return code if sync clock is switched off. */ |
292 | if (rc == -ENOSYS || rc == -EACCES) | 304 | if (rc == -ENOSYS || rc == -EACCES) |
293 | rc = 0; | 305 | rc = 0; |
294 | return rc; | 306 | return rc; |
295 | } | 307 | } |
296 | 308 | ||
297 | static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk, | 309 | static void fill_LRE_data(struct LRE_eckd_data *data, unsigned int trk, |
298 | int totrk, int cmd, struct dasd_device *basedev, | 310 | unsigned int rec_on_trk, int count, int cmd, |
299 | struct dasd_device *startdev) | 311 | struct dasd_device *device, unsigned int reclen, |
312 | unsigned int tlf) | ||
313 | { | ||
314 | struct dasd_eckd_private *private; | ||
315 | int sector; | ||
316 | int dn, d; | ||
317 | |||
318 | private = (struct dasd_eckd_private *) device->private; | ||
319 | |||
320 | memset(data, 0, sizeof(*data)); | ||
321 | sector = 0; | ||
322 | if (rec_on_trk) { | ||
323 | switch (private->rdc_data.dev_type) { | ||
324 | case 0x3390: | ||
325 | dn = ceil_quot(reclen + 6, 232); | ||
326 | d = 9 + ceil_quot(reclen + 6 * (dn + 1), 34); | ||
327 | sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8; | ||
328 | break; | ||
329 | case 0x3380: | ||
330 | d = 7 + ceil_quot(reclen + 12, 32); | ||
331 | sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7; | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | data->sector = sector; | ||
336 | /* note: meaning of count depends on the operation | ||
337 | * for record based I/O it's the number of records, but for | ||
338 | * track based I/O it's the number of tracks | ||
339 | */ | ||
340 | data->count = count; | ||
341 | switch (cmd) { | ||
342 | case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: | ||
343 | data->operation.orientation = 0x3; | ||
344 | data->operation.operation = 0x03; | ||
345 | break; | ||
346 | case DASD_ECKD_CCW_READ_HOME_ADDRESS: | ||
347 | data->operation.orientation = 0x3; | ||
348 | data->operation.operation = 0x16; | ||
349 | break; | ||
350 | case DASD_ECKD_CCW_WRITE_RECORD_ZERO: | ||
351 | data->operation.orientation = 0x1; | ||
352 | data->operation.operation = 0x03; | ||
353 | data->count++; | ||
354 | break; | ||
355 | case DASD_ECKD_CCW_READ_RECORD_ZERO: | ||
356 | data->operation.orientation = 0x3; | ||
357 | data->operation.operation = 0x16; | ||
358 | data->count++; | ||
359 | break; | ||
360 | case DASD_ECKD_CCW_WRITE: | ||
361 | case DASD_ECKD_CCW_WRITE_MT: | ||
362 | case DASD_ECKD_CCW_WRITE_KD: | ||
363 | case DASD_ECKD_CCW_WRITE_KD_MT: | ||
364 | data->auxiliary.length_valid = 0x1; | ||
365 | data->length = reclen; | ||
366 | data->operation.operation = 0x01; | ||
367 | break; | ||
368 | case DASD_ECKD_CCW_WRITE_CKD: | ||
369 | case DASD_ECKD_CCW_WRITE_CKD_MT: | ||
370 | data->auxiliary.length_valid = 0x1; | ||
371 | data->length = reclen; | ||
372 | data->operation.operation = 0x03; | ||
373 | break; | ||
374 | case DASD_ECKD_CCW_WRITE_TRACK_DATA: | ||
375 | data->auxiliary.length_valid = 0x1; | ||
376 | data->length = reclen; /* not tlf, as one might think */ | ||
377 | data->operation.operation = 0x3F; | ||
378 | data->extended_operation = 0x23; | ||
379 | break; | ||
380 | case DASD_ECKD_CCW_READ: | ||
381 | case DASD_ECKD_CCW_READ_MT: | ||
382 | case DASD_ECKD_CCW_READ_KD: | ||
383 | case DASD_ECKD_CCW_READ_KD_MT: | ||
384 | data->auxiliary.length_valid = 0x1; | ||
385 | data->length = reclen; | ||
386 | data->operation.operation = 0x06; | ||
387 | break; | ||
388 | case DASD_ECKD_CCW_READ_CKD: | ||
389 | case DASD_ECKD_CCW_READ_CKD_MT: | ||
390 | data->auxiliary.length_valid = 0x1; | ||
391 | data->length = reclen; | ||
392 | data->operation.operation = 0x16; | ||
393 | break; | ||
394 | case DASD_ECKD_CCW_READ_COUNT: | ||
395 | data->operation.operation = 0x06; | ||
396 | break; | ||
397 | case DASD_ECKD_CCW_READ_TRACK_DATA: | ||
398 | data->auxiliary.length_valid = 0x1; | ||
399 | data->length = tlf; | ||
400 | data->operation.operation = 0x0C; | ||
401 | break; | ||
402 | case DASD_ECKD_CCW_ERASE: | ||
403 | data->length = reclen; | ||
404 | data->auxiliary.length_valid = 0x1; | ||
405 | data->operation.operation = 0x0b; | ||
406 | break; | ||
407 | default: | ||
408 | DBF_DEV_EVENT(DBF_ERR, device, | ||
409 | "fill LRE unknown opcode 0x%x", cmd); | ||
410 | BUG(); | ||
411 | } | ||
412 | set_ch_t(&data->seek_addr, | ||
413 | trk / private->rdc_data.trk_per_cyl, | ||
414 | trk % private->rdc_data.trk_per_cyl); | ||
415 | data->search_arg.cyl = data->seek_addr.cyl; | ||
416 | data->search_arg.head = data->seek_addr.head; | ||
417 | data->search_arg.record = rec_on_trk; | ||
418 | } | ||
419 | |||
420 | static int prefix_LRE(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, | ||
421 | unsigned int trk, unsigned int totrk, int cmd, | ||
422 | struct dasd_device *basedev, struct dasd_device *startdev, | ||
423 | unsigned char format, unsigned int rec_on_trk, int count, | ||
424 | unsigned int blksize, unsigned int tlf) | ||
300 | { | 425 | { |
301 | struct dasd_eckd_private *basepriv, *startpriv; | 426 | struct dasd_eckd_private *basepriv, *startpriv; |
302 | struct DE_eckd_data *data; | 427 | struct DE_eckd_data *dedata; |
303 | struct ch_t geo, beg, end; | 428 | struct LRE_eckd_data *lredata; |
429 | u32 begcyl, endcyl; | ||
430 | u16 heads, beghead, endhead; | ||
304 | int rc = 0; | 431 | int rc = 0; |
305 | 432 | ||
306 | basepriv = (struct dasd_eckd_private *) basedev->private; | 433 | basepriv = (struct dasd_eckd_private *) basedev->private; |
307 | startpriv = (struct dasd_eckd_private *) startdev->private; | 434 | startpriv = (struct dasd_eckd_private *) startdev->private; |
308 | data = &pfxdata->define_extend; | 435 | dedata = &pfxdata->define_extent; |
436 | lredata = &pfxdata->locate_record; | ||
309 | 437 | ||
310 | ccw->cmd_code = DASD_ECKD_CCW_PFX; | 438 | ccw->cmd_code = DASD_ECKD_CCW_PFX; |
311 | ccw->flags = 0; | 439 | ccw->flags = 0; |
@@ -314,10 +442,16 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk, | |||
314 | 442 | ||
315 | memset(pfxdata, 0, sizeof(*pfxdata)); | 443 | memset(pfxdata, 0, sizeof(*pfxdata)); |
316 | /* prefix data */ | 444 | /* prefix data */ |
317 | pfxdata->format = 0; | 445 | if (format > 1) { |
446 | DBF_DEV_EVENT(DBF_ERR, basedev, | ||
447 | "PFX LRE unknown format 0x%x", format); | ||
448 | BUG(); | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | pfxdata->format = format; | ||
318 | pfxdata->base_address = basepriv->ned->unit_addr; | 452 | pfxdata->base_address = basepriv->ned->unit_addr; |
319 | pfxdata->base_lss = basepriv->ned->ID; | 453 | pfxdata->base_lss = basepriv->ned->ID; |
320 | pfxdata->validity.define_extend = 1; | 454 | pfxdata->validity.define_extent = 1; |
321 | 455 | ||
322 | /* private uid is kept up to date, conf_data may be outdated */ | 456 | /* private uid is kept up to date, conf_data may be outdated */ |
323 | if (startpriv->uid.type != UA_BASE_DEVICE) { | 457 | if (startpriv->uid.type != UA_BASE_DEVICE) { |
@@ -337,70 +471,94 @@ static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, int trk, | |||
337 | case DASD_ECKD_CCW_READ_KD: | 471 | case DASD_ECKD_CCW_READ_KD: |
338 | case DASD_ECKD_CCW_READ_KD_MT: | 472 | case DASD_ECKD_CCW_READ_KD_MT: |
339 | case DASD_ECKD_CCW_READ_COUNT: | 473 | case DASD_ECKD_CCW_READ_COUNT: |
340 | data->mask.perm = 0x1; | 474 | dedata->mask.perm = 0x1; |
341 | data->attributes.operation = basepriv->attrib.operation; | 475 | dedata->attributes.operation = basepriv->attrib.operation; |
476 | break; | ||
477 | case DASD_ECKD_CCW_READ_TRACK_DATA: | ||
478 | dedata->mask.perm = 0x1; | ||
479 | dedata->attributes.operation = basepriv->attrib.operation; | ||
480 | dedata->blk_size = 0; | ||
342 | break; | 481 | break; |
343 | case DASD_ECKD_CCW_WRITE: | 482 | case DASD_ECKD_CCW_WRITE: |
344 | case DASD_ECKD_CCW_WRITE_MT: | 483 | case DASD_ECKD_CCW_WRITE_MT: |
345 | case DASD_ECKD_CCW_WRITE_KD: | 484 | case DASD_ECKD_CCW_WRITE_KD: |
346 | case DASD_ECKD_CCW_WRITE_KD_MT: | 485 | case DASD_ECKD_CCW_WRITE_KD_MT: |
347 | data->mask.perm = 0x02; | 486 | dedata->mask.perm = 0x02; |
348 | data->attributes.operation = basepriv->attrib.operation; | 487 | dedata->attributes.operation = basepriv->attrib.operation; |
349 | rc = check_XRC_on_prefix(pfxdata, basedev); | 488 | rc = check_XRC_on_prefix(pfxdata, basedev); |
350 | break; | 489 | break; |
351 | case DASD_ECKD_CCW_WRITE_CKD: | 490 | case DASD_ECKD_CCW_WRITE_CKD: |
352 | case DASD_ECKD_CCW_WRITE_CKD_MT: | 491 | case DASD_ECKD_CCW_WRITE_CKD_MT: |
353 | data->attributes.operation = DASD_BYPASS_CACHE; | 492 | dedata->attributes.operation = DASD_BYPASS_CACHE; |
354 | rc = check_XRC_on_prefix(pfxdata, basedev); | 493 | rc = check_XRC_on_prefix(pfxdata, basedev); |
355 | break; | 494 | break; |
356 | case DASD_ECKD_CCW_ERASE: | 495 | case DASD_ECKD_CCW_ERASE: |
357 | case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: | 496 | case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: |
358 | case DASD_ECKD_CCW_WRITE_RECORD_ZERO: | 497 | case DASD_ECKD_CCW_WRITE_RECORD_ZERO: |
359 | data->mask.perm = 0x3; | 498 | dedata->mask.perm = 0x3; |
360 | data->mask.auth = 0x1; | 499 | dedata->mask.auth = 0x1; |
361 | data->attributes.operation = DASD_BYPASS_CACHE; | 500 | dedata->attributes.operation = DASD_BYPASS_CACHE; |
362 | rc = check_XRC_on_prefix(pfxdata, basedev); | 501 | rc = check_XRC_on_prefix(pfxdata, basedev); |
363 | break; | 502 | break; |
364 | default: | 503 | case DASD_ECKD_CCW_WRITE_TRACK_DATA: |
365 | DEV_MESSAGE(KERN_ERR, basedev, "unknown opcode 0x%x", cmd); | 504 | dedata->mask.perm = 0x02; |
505 | dedata->attributes.operation = basepriv->attrib.operation; | ||
506 | dedata->blk_size = blksize; | ||
507 | rc = check_XRC_on_prefix(pfxdata, basedev); | ||
366 | break; | 508 | break; |
509 | default: | ||
510 | DBF_DEV_EVENT(DBF_ERR, basedev, | ||
511 | "PFX LRE unknown opcode 0x%x", cmd); | ||
512 | BUG(); | ||
513 | return -EINVAL; | ||
367 | } | 514 | } |
368 | 515 | ||
369 | data->attributes.mode = 0x3; /* ECKD */ | 516 | dedata->attributes.mode = 0x3; /* ECKD */ |
370 | 517 | ||
371 | if ((basepriv->rdc_data.cu_type == 0x2105 || | 518 | if ((basepriv->rdc_data.cu_type == 0x2105 || |
372 | basepriv->rdc_data.cu_type == 0x2107 || | 519 | basepriv->rdc_data.cu_type == 0x2107 || |
373 | basepriv->rdc_data.cu_type == 0x1750) | 520 | basepriv->rdc_data.cu_type == 0x1750) |
374 | && !(basepriv->uses_cdl && trk < 2)) | 521 | && !(basepriv->uses_cdl && trk < 2)) |
375 | data->ga_extended |= 0x40; /* Regular Data Format Mode */ | 522 | dedata->ga_extended |= 0x40; /* Regular Data Format Mode */ |
376 | 523 | ||
377 | geo.cyl = basepriv->rdc_data.no_cyl; | 524 | heads = basepriv->rdc_data.trk_per_cyl; |
378 | geo.head = basepriv->rdc_data.trk_per_cyl; | 525 | begcyl = trk / heads; |
379 | beg.cyl = trk / geo.head; | 526 | beghead = trk % heads; |
380 | beg.head = trk % geo.head; | 527 | endcyl = totrk / heads; |
381 | end.cyl = totrk / geo.head; | 528 | endhead = totrk % heads; |
382 | end.head = totrk % geo.head; | ||
383 | 529 | ||
384 | /* check for sequential prestage - enhance cylinder range */ | 530 | /* check for sequential prestage - enhance cylinder range */ |
385 | if (data->attributes.operation == DASD_SEQ_PRESTAGE || | 531 | if (dedata->attributes.operation == DASD_SEQ_PRESTAGE || |
386 | data->attributes.operation == DASD_SEQ_ACCESS) { | 532 | dedata->attributes.operation == DASD_SEQ_ACCESS) { |
387 | 533 | ||
388 | if (end.cyl + basepriv->attrib.nr_cyl < geo.cyl) | 534 | if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl) |
389 | end.cyl += basepriv->attrib.nr_cyl; | 535 | endcyl += basepriv->attrib.nr_cyl; |
390 | else | 536 | else |
391 | end.cyl = (geo.cyl - 1); | 537 | endcyl = (basepriv->real_cyl - 1); |
538 | } | ||
539 | |||
540 | set_ch_t(&dedata->beg_ext, begcyl, beghead); | ||
541 | set_ch_t(&dedata->end_ext, endcyl, endhead); | ||
542 | |||
543 | if (format == 1) { | ||
544 | fill_LRE_data(lredata, trk, rec_on_trk, count, cmd, | ||
545 | basedev, blksize, tlf); | ||
392 | } | 546 | } |
393 | 547 | ||
394 | data->beg_ext.cyl = beg.cyl; | ||
395 | data->beg_ext.head = beg.head; | ||
396 | data->end_ext.cyl = end.cyl; | ||
397 | data->end_ext.head = end.head; | ||
398 | return rc; | 548 | return rc; |
399 | } | 549 | } |
400 | 550 | ||
551 | static int prefix(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, | ||
552 | unsigned int trk, unsigned int totrk, int cmd, | ||
553 | struct dasd_device *basedev, struct dasd_device *startdev) | ||
554 | { | ||
555 | return prefix_LRE(ccw, pfxdata, trk, totrk, cmd, basedev, startdev, | ||
556 | 0, 0, 0, 0, 0); | ||
557 | } | ||
558 | |||
401 | static void | 559 | static void |
402 | locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, | 560 | locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk, |
403 | int rec_on_trk, int no_rec, int cmd, | 561 | unsigned int rec_on_trk, int no_rec, int cmd, |
404 | struct dasd_device * device, int reclen) | 562 | struct dasd_device * device, int reclen) |
405 | { | 563 | { |
406 | struct dasd_eckd_private *private; | 564 | struct dasd_eckd_private *private; |
@@ -491,12 +649,14 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, | |||
491 | data->operation.operation = 0x0b; | 649 | data->operation.operation = 0x0b; |
492 | break; | 650 | break; |
493 | default: | 651 | default: |
494 | DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); | 652 | DBF_DEV_EVENT(DBF_ERR, device, "unknown locate record " |
495 | } | 653 | "opcode 0x%x", cmd); |
496 | data->seek_addr.cyl = data->search_arg.cyl = | 654 | } |
497 | trk / private->rdc_data.trk_per_cyl; | 655 | set_ch_t(&data->seek_addr, |
498 | data->seek_addr.head = data->search_arg.head = | 656 | trk / private->rdc_data.trk_per_cyl, |
499 | trk % private->rdc_data.trk_per_cyl; | 657 | trk % private->rdc_data.trk_per_cyl); |
658 | data->search_arg.cyl = data->seek_addr.cyl; | ||
659 | data->search_arg.head = data->seek_addr.head; | ||
500 | data->search_arg.record = rec_on_trk; | 660 | data->search_arg.record = rec_on_trk; |
501 | } | 661 | } |
502 | 662 | ||
@@ -585,8 +745,8 @@ static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, | |||
585 | cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device); | 745 | cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device); |
586 | 746 | ||
587 | if (IS_ERR(cqr)) { | 747 | if (IS_ERR(cqr)) { |
588 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 748 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
589 | "Could not allocate RCD request"); | 749 | "Could not allocate RCD request"); |
590 | return cqr; | 750 | return cqr; |
591 | } | 751 | } |
592 | 752 | ||
@@ -736,14 +896,16 @@ static int dasd_eckd_read_conf(struct dasd_device *device) | |||
736 | rc = dasd_eckd_read_conf_lpm(device, &conf_data, | 896 | rc = dasd_eckd_read_conf_lpm(device, &conf_data, |
737 | &conf_len, lpm); | 897 | &conf_len, lpm); |
738 | if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ | 898 | if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ |
739 | MESSAGE(KERN_WARNING, | 899 | DBF_EVENT(DBF_WARNING, |
740 | "Read configuration data returned " | 900 | "Read configuration data returned " |
741 | "error %d", rc); | 901 | "error %d for device: %s", rc, |
902 | dev_name(&device->cdev->dev)); | ||
742 | return rc; | 903 | return rc; |
743 | } | 904 | } |
744 | if (conf_data == NULL) { | 905 | if (conf_data == NULL) { |
745 | MESSAGE(KERN_WARNING, "%s", "No configuration " | 906 | DBF_EVENT(DBF_WARNING, "No configuration " |
746 | "data retrieved"); | 907 | "data retrieved for device: %s", |
908 | dev_name(&device->cdev->dev)); | ||
747 | continue; /* no error */ | 909 | continue; /* no error */ |
748 | } | 910 | } |
749 | /* save first valid configuration data */ | 911 | /* save first valid configuration data */ |
@@ -790,8 +952,9 @@ static int dasd_eckd_read_features(struct dasd_device *device) | |||
790 | sizeof(struct dasd_rssd_features)), | 952 | sizeof(struct dasd_rssd_features)), |
791 | device); | 953 | device); |
792 | if (IS_ERR(cqr)) { | 954 | if (IS_ERR(cqr)) { |
793 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 955 | DBF_EVENT(DBF_WARNING, "Could not allocate initialization " |
794 | "Could not allocate initialization request"); | 956 | "request for device: %s", |
957 | dev_name(&device->cdev->dev)); | ||
795 | return PTR_ERR(cqr); | 958 | return PTR_ERR(cqr); |
796 | } | 959 | } |
797 | cqr->startdev = device; | 960 | cqr->startdev = device; |
@@ -840,7 +1003,8 @@ static int dasd_eckd_read_features(struct dasd_device *device) | |||
840 | /* | 1003 | /* |
841 | * Build CP for Perform Subsystem Function - SSC. | 1004 | * Build CP for Perform Subsystem Function - SSC. |
842 | */ | 1005 | */ |
843 | static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device) | 1006 | static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, |
1007 | int enable_pav) | ||
844 | { | 1008 | { |
845 | struct dasd_ccw_req *cqr; | 1009 | struct dasd_ccw_req *cqr; |
846 | struct dasd_psf_ssc_data *psf_ssc_data; | 1010 | 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) | |||
851 | device); | 1015 | device); |
852 | 1016 | ||
853 | if (IS_ERR(cqr)) { | 1017 | if (IS_ERR(cqr)) { |
854 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1018 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
855 | "Could not allocate PSF-SSC request"); | 1019 | "Could not allocate PSF-SSC request"); |
856 | return cqr; | 1020 | return cqr; |
857 | } | 1021 | } |
858 | psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data; | 1022 | psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data; |
859 | psf_ssc_data->order = PSF_ORDER_SSC; | 1023 | psf_ssc_data->order = PSF_ORDER_SSC; |
860 | psf_ssc_data->suborder = 0x88; | 1024 | psf_ssc_data->suborder = 0x40; |
861 | psf_ssc_data->reserved[0] = 0x88; | 1025 | if (enable_pav) { |
862 | 1026 | psf_ssc_data->suborder |= 0x88; | |
1027 | psf_ssc_data->reserved[0] = 0x88; | ||
1028 | } | ||
863 | ccw = cqr->cpaddr; | 1029 | ccw = cqr->cpaddr; |
864 | ccw->cmd_code = DASD_ECKD_CCW_PSF; | 1030 | ccw->cmd_code = DASD_ECKD_CCW_PSF; |
865 | ccw->cda = (__u32)(addr_t)psf_ssc_data; | 1031 | 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) | |||
880 | * call might change behaviour of DASD devices. | 1046 | * call might change behaviour of DASD devices. |
881 | */ | 1047 | */ |
882 | static int | 1048 | static int |
883 | dasd_eckd_psf_ssc(struct dasd_device *device) | 1049 | dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav) |
884 | { | 1050 | { |
885 | struct dasd_ccw_req *cqr; | 1051 | struct dasd_ccw_req *cqr; |
886 | int rc; | 1052 | int rc; |
887 | 1053 | ||
888 | cqr = dasd_eckd_build_psf_ssc(device); | 1054 | cqr = dasd_eckd_build_psf_ssc(device, enable_pav); |
889 | if (IS_ERR(cqr)) | 1055 | if (IS_ERR(cqr)) |
890 | return PTR_ERR(cqr); | 1056 | return PTR_ERR(cqr); |
891 | 1057 | ||
@@ -904,19 +1070,20 @@ static int dasd_eckd_validate_server(struct dasd_device *device) | |||
904 | { | 1070 | { |
905 | int rc; | 1071 | int rc; |
906 | struct dasd_eckd_private *private; | 1072 | struct dasd_eckd_private *private; |
1073 | int enable_pav; | ||
907 | 1074 | ||
908 | /* Currently PAV is the only reason to 'validate' server on LPAR */ | ||
909 | if (dasd_nopav || MACHINE_IS_VM) | 1075 | if (dasd_nopav || MACHINE_IS_VM) |
910 | return 0; | 1076 | enable_pav = 0; |
911 | 1077 | else | |
912 | rc = dasd_eckd_psf_ssc(device); | 1078 | enable_pav = 1; |
1079 | rc = dasd_eckd_psf_ssc(device, enable_pav); | ||
913 | /* may be requested feature is not available on server, | 1080 | /* may be requested feature is not available on server, |
914 | * therefore just report error and go ahead */ | 1081 | * therefore just report error and go ahead */ |
915 | private = (struct dasd_eckd_private *) device->private; | 1082 | private = (struct dasd_eckd_private *) device->private; |
916 | DEV_MESSAGE(KERN_INFO, device, | 1083 | DBF_EVENT(DBF_WARNING, "PSF-SSC on storage subsystem %s.%s.%04x " |
917 | "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d", | 1084 | "returned rc=%d for device: %s", |
918 | private->uid.vendor, private->uid.serial, | 1085 | private->uid.vendor, private->uid.serial, |
919 | private->uid.ssid, rc); | 1086 | private->uid.ssid, rc, dev_name(&device->cdev->dev)); |
920 | /* RE-Read Configuration Data */ | 1087 | /* RE-Read Configuration Data */ |
921 | return dasd_eckd_read_conf(device); | 1088 | return dasd_eckd_read_conf(device); |
922 | } | 1089 | } |
@@ -938,9 +1105,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
938 | private = kzalloc(sizeof(struct dasd_eckd_private), | 1105 | private = kzalloc(sizeof(struct dasd_eckd_private), |
939 | GFP_KERNEL | GFP_DMA); | 1106 | GFP_KERNEL | GFP_DMA); |
940 | if (private == NULL) { | 1107 | if (private == NULL) { |
941 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1108 | dev_warn(&device->cdev->dev, |
942 | "memory allocation failed for private " | 1109 | "Allocating memory for private DASD data " |
943 | "data"); | 1110 | "failed\n"); |
944 | return -ENOMEM; | 1111 | return -ENOMEM; |
945 | } | 1112 | } |
946 | device->private = (void *) private; | 1113 | device->private = (void *) private; |
@@ -965,8 +1132,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
965 | if (private->uid.type == UA_BASE_DEVICE) { | 1132 | if (private->uid.type == UA_BASE_DEVICE) { |
966 | block = dasd_alloc_block(); | 1133 | block = dasd_alloc_block(); |
967 | if (IS_ERR(block)) { | 1134 | if (IS_ERR(block)) { |
968 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1135 | DBF_EVENT(DBF_WARNING, "could not allocate dasd " |
969 | "could not allocate dasd block structure"); | 1136 | "block structure for device: %s", |
1137 | dev_name(&device->cdev->dev)); | ||
970 | rc = PTR_ERR(block); | 1138 | rc = PTR_ERR(block); |
971 | goto out_err1; | 1139 | goto out_err1; |
972 | } | 1140 | } |
@@ -997,20 +1165,27 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
997 | memset(rdc_data, 0, sizeof(rdc_data)); | 1165 | memset(rdc_data, 0, sizeof(rdc_data)); |
998 | rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64); | 1166 | rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64); |
999 | if (rc) { | 1167 | if (rc) { |
1000 | DEV_MESSAGE(KERN_WARNING, device, | 1168 | DBF_EVENT(DBF_WARNING, |
1001 | "Read device characteristics returned " | 1169 | "Read device characteristics failed, rc=%d for " |
1002 | "rc=%d", rc); | 1170 | "device: %s", rc, dev_name(&device->cdev->dev)); |
1003 | goto out_err3; | 1171 | goto out_err3; |
1004 | } | 1172 | } |
1005 | DEV_MESSAGE(KERN_INFO, device, | 1173 | /* find the vaild cylinder size */ |
1006 | "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", | 1174 | if (private->rdc_data.no_cyl == LV_COMPAT_CYL && |
1007 | private->rdc_data.dev_type, | 1175 | private->rdc_data.long_no_cyl) |
1008 | private->rdc_data.dev_model, | 1176 | private->real_cyl = private->rdc_data.long_no_cyl; |
1009 | private->rdc_data.cu_type, | 1177 | else |
1010 | private->rdc_data.cu_model.model, | 1178 | private->real_cyl = private->rdc_data.no_cyl; |
1011 | private->rdc_data.no_cyl, | 1179 | |
1012 | private->rdc_data.trk_per_cyl, | 1180 | dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " |
1013 | private->rdc_data.sec_per_trk); | 1181 | "with %d cylinders, %d heads, %d sectors\n", |
1182 | private->rdc_data.dev_type, | ||
1183 | private->rdc_data.dev_model, | ||
1184 | private->rdc_data.cu_type, | ||
1185 | private->rdc_data.cu_model.model, | ||
1186 | private->real_cyl, | ||
1187 | private->rdc_data.trk_per_cyl, | ||
1188 | private->rdc_data.sec_per_trk); | ||
1014 | return 0; | 1189 | return 0; |
1015 | 1190 | ||
1016 | out_err3: | 1191 | out_err3: |
@@ -1151,14 +1326,12 @@ dasd_eckd_end_analysis(struct dasd_block *block) | |||
1151 | status = private->init_cqr_status; | 1326 | status = private->init_cqr_status; |
1152 | private->init_cqr_status = -1; | 1327 | private->init_cqr_status = -1; |
1153 | if (status != DASD_CQR_DONE) { | 1328 | if (status != DASD_CQR_DONE) { |
1154 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1329 | dev_warn(&device->cdev->dev, |
1155 | "volume analysis returned unformatted disk"); | 1330 | "The DASD is not formatted\n"); |
1156 | return -EMEDIUMTYPE; | 1331 | return -EMEDIUMTYPE; |
1157 | } | 1332 | } |
1158 | 1333 | ||
1159 | private->uses_cdl = 1; | 1334 | private->uses_cdl = 1; |
1160 | /* Calculate number of blocks/records per track. */ | ||
1161 | blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block); | ||
1162 | /* Check Track 0 for Compatible Disk Layout */ | 1335 | /* Check Track 0 for Compatible Disk Layout */ |
1163 | count_area = NULL; | 1336 | count_area = NULL; |
1164 | for (i = 0; i < 3; i++) { | 1337 | for (i = 0; i < 3; i++) { |
@@ -1182,8 +1355,8 @@ dasd_eckd_end_analysis(struct dasd_block *block) | |||
1182 | count_area = &private->count_area[0]; | 1355 | count_area = &private->count_area[0]; |
1183 | } else { | 1356 | } else { |
1184 | if (private->count_area[3].record == 1) | 1357 | if (private->count_area[3].record == 1) |
1185 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1358 | dev_warn(&device->cdev->dev, |
1186 | "Trk 0: no records after VTOC!"); | 1359 | "Track 0 has no records following the VTOC\n"); |
1187 | } | 1360 | } |
1188 | if (count_area != NULL && count_area->kl == 0) { | 1361 | if (count_area != NULL && count_area->kl == 0) { |
1189 | /* we found notthing violating our disk layout */ | 1362 | /* we found notthing violating our disk layout */ |
@@ -1191,8 +1364,8 @@ dasd_eckd_end_analysis(struct dasd_block *block) | |||
1191 | block->bp_block = count_area->dl; | 1364 | block->bp_block = count_area->dl; |
1192 | } | 1365 | } |
1193 | if (block->bp_block == 0) { | 1366 | if (block->bp_block == 0) { |
1194 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 1367 | dev_warn(&device->cdev->dev, |
1195 | "Volume has incompatible disk layout"); | 1368 | "The disk layout of the DASD is not supported\n"); |
1196 | return -EMEDIUMTYPE; | 1369 | return -EMEDIUMTYPE; |
1197 | } | 1370 | } |
1198 | block->s2b_shift = 0; /* bits to shift 512 to get a block */ | 1371 | block->s2b_shift = 0; /* bits to shift 512 to get a block */ |
@@ -1200,19 +1373,19 @@ dasd_eckd_end_analysis(struct dasd_block *block) | |||
1200 | block->s2b_shift++; | 1373 | block->s2b_shift++; |
1201 | 1374 | ||
1202 | blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block); | 1375 | blk_per_trk = recs_per_track(&private->rdc_data, 0, block->bp_block); |
1203 | block->blocks = (private->rdc_data.no_cyl * | 1376 | block->blocks = (private->real_cyl * |
1204 | private->rdc_data.trk_per_cyl * | 1377 | private->rdc_data.trk_per_cyl * |
1205 | blk_per_trk); | 1378 | blk_per_trk); |
1206 | 1379 | ||
1207 | DEV_MESSAGE(KERN_INFO, device, | 1380 | dev_info(&device->cdev->dev, |
1208 | "(%dkB blks): %dkB at %dkB/trk %s", | 1381 | "DASD with %d KB/block, %d KB total size, %d KB/track, " |
1209 | (block->bp_block >> 10), | 1382 | "%s\n", (block->bp_block >> 10), |
1210 | ((private->rdc_data.no_cyl * | 1383 | ((private->real_cyl * |
1211 | private->rdc_data.trk_per_cyl * | 1384 | private->rdc_data.trk_per_cyl * |
1212 | blk_per_trk * (block->bp_block >> 9)) >> 1), | 1385 | blk_per_trk * (block->bp_block >> 9)) >> 1), |
1213 | ((blk_per_trk * block->bp_block) >> 10), | 1386 | ((blk_per_trk * block->bp_block) >> 10), |
1214 | private->uses_cdl ? | 1387 | private->uses_cdl ? |
1215 | "compatible disk layout" : "linux disk layout"); | 1388 | "compatible disk layout" : "linux disk layout"); |
1216 | 1389 | ||
1217 | return 0; | 1390 | return 0; |
1218 | } | 1391 | } |
@@ -1262,31 +1435,35 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1262 | struct eckd_count *ect; | 1435 | struct eckd_count *ect; |
1263 | struct ccw1 *ccw; | 1436 | struct ccw1 *ccw; |
1264 | void *data; | 1437 | void *data; |
1265 | int rpt, cyl, head; | 1438 | int rpt; |
1439 | struct ch_t address; | ||
1266 | int cplength, datasize; | 1440 | int cplength, datasize; |
1267 | int i; | 1441 | int i; |
1442 | int intensity = 0; | ||
1443 | int r0_perm; | ||
1268 | 1444 | ||
1269 | private = (struct dasd_eckd_private *) device->private; | 1445 | private = (struct dasd_eckd_private *) device->private; |
1270 | rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize); | 1446 | rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize); |
1271 | cyl = fdata->start_unit / private->rdc_data.trk_per_cyl; | 1447 | set_ch_t(&address, |
1272 | head = fdata->start_unit % private->rdc_data.trk_per_cyl; | 1448 | fdata->start_unit / private->rdc_data.trk_per_cyl, |
1449 | fdata->start_unit % private->rdc_data.trk_per_cyl); | ||
1273 | 1450 | ||
1274 | /* Sanity checks. */ | 1451 | /* Sanity checks. */ |
1275 | if (fdata->start_unit >= | 1452 | if (fdata->start_unit >= |
1276 | (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) { | 1453 | (private->real_cyl * private->rdc_data.trk_per_cyl)) { |
1277 | DEV_MESSAGE(KERN_INFO, device, "Track no %d too big!", | 1454 | dev_warn(&device->cdev->dev, "Start track number %d used in " |
1278 | fdata->start_unit); | 1455 | "formatting is too big\n", fdata->start_unit); |
1279 | return ERR_PTR(-EINVAL); | 1456 | return ERR_PTR(-EINVAL); |
1280 | } | 1457 | } |
1281 | if (fdata->start_unit > fdata->stop_unit) { | 1458 | if (fdata->start_unit > fdata->stop_unit) { |
1282 | DEV_MESSAGE(KERN_INFO, device, "Track %d reached! ending.", | 1459 | dev_warn(&device->cdev->dev, "Start track %d used in " |
1283 | fdata->start_unit); | 1460 | "formatting exceeds end track\n", fdata->start_unit); |
1284 | return ERR_PTR(-EINVAL); | 1461 | return ERR_PTR(-EINVAL); |
1285 | } | 1462 | } |
1286 | if (dasd_check_blocksize(fdata->blksize) != 0) { | 1463 | if (dasd_check_blocksize(fdata->blksize) != 0) { |
1287 | DEV_MESSAGE(KERN_WARNING, device, | 1464 | dev_warn(&device->cdev->dev, |
1288 | "Invalid blocksize %d...terminating!", | 1465 | "The DASD cannot be formatted with block size %d\n", |
1289 | fdata->blksize); | 1466 | fdata->blksize); |
1290 | return ERR_PTR(-EINVAL); | 1467 | return ERR_PTR(-EINVAL); |
1291 | } | 1468 | } |
1292 | 1469 | ||
@@ -1296,9 +1473,17 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1296 | * Bit 1: write home address, currently not supported | 1473 | * Bit 1: write home address, currently not supported |
1297 | * Bit 2: invalidate tracks | 1474 | * Bit 2: invalidate tracks |
1298 | * Bit 3: use OS/390 compatible disk layout (cdl) | 1475 | * Bit 3: use OS/390 compatible disk layout (cdl) |
1476 | * Bit 4: do not allow storage subsystem to modify record zero | ||
1299 | * Only some bit combinations do make sense. | 1477 | * Only some bit combinations do make sense. |
1300 | */ | 1478 | */ |
1301 | switch (fdata->intensity) { | 1479 | if (fdata->intensity & 0x10) { |
1480 | r0_perm = 0; | ||
1481 | intensity = fdata->intensity & ~0x10; | ||
1482 | } else { | ||
1483 | r0_perm = 1; | ||
1484 | intensity = fdata->intensity; | ||
1485 | } | ||
1486 | switch (intensity) { | ||
1302 | case 0x00: /* Normal format */ | 1487 | case 0x00: /* Normal format */ |
1303 | case 0x08: /* Normal format, use cdl. */ | 1488 | case 0x08: /* Normal format, use cdl. */ |
1304 | cplength = 2 + rpt; | 1489 | cplength = 2 + rpt; |
@@ -1322,8 +1507,8 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1322 | sizeof(struct eckd_count); | 1507 | sizeof(struct eckd_count); |
1323 | break; | 1508 | break; |
1324 | default: | 1509 | default: |
1325 | DEV_MESSAGE(KERN_WARNING, device, "Invalid flags 0x%x.", | 1510 | dev_warn(&device->cdev->dev, "An I/O control call used " |
1326 | fdata->intensity); | 1511 | "incorrect flags 0x%x\n", fdata->intensity); |
1327 | return ERR_PTR(-EINVAL); | 1512 | return ERR_PTR(-EINVAL); |
1328 | } | 1513 | } |
1329 | /* Allocate the format ccw request. */ | 1514 | /* Allocate the format ccw request. */ |
@@ -1335,11 +1520,14 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1335 | data = fcp->data; | 1520 | data = fcp->data; |
1336 | ccw = fcp->cpaddr; | 1521 | ccw = fcp->cpaddr; |
1337 | 1522 | ||
1338 | switch (fdata->intensity & ~0x08) { | 1523 | switch (intensity & ~0x08) { |
1339 | case 0x00: /* Normal format. */ | 1524 | case 0x00: /* Normal format. */ |
1340 | define_extent(ccw++, (struct DE_eckd_data *) data, | 1525 | define_extent(ccw++, (struct DE_eckd_data *) data, |
1341 | fdata->start_unit, fdata->start_unit, | 1526 | fdata->start_unit, fdata->start_unit, |
1342 | DASD_ECKD_CCW_WRITE_CKD, device); | 1527 | DASD_ECKD_CCW_WRITE_CKD, device); |
1528 | /* grant subsystem permission to format R0 */ | ||
1529 | if (r0_perm) | ||
1530 | ((struct DE_eckd_data *)data)->ga_extended |= 0x04; | ||
1343 | data += sizeof(struct DE_eckd_data); | 1531 | data += sizeof(struct DE_eckd_data); |
1344 | ccw[-1].flags |= CCW_FLAG_CC; | 1532 | ccw[-1].flags |= CCW_FLAG_CC; |
1345 | locate_record(ccw++, (struct LO_eckd_data *) data, | 1533 | locate_record(ccw++, (struct LO_eckd_data *) data, |
@@ -1373,11 +1561,11 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1373 | data += sizeof(struct LO_eckd_data); | 1561 | data += sizeof(struct LO_eckd_data); |
1374 | break; | 1562 | break; |
1375 | } | 1563 | } |
1376 | if (fdata->intensity & 0x01) { /* write record zero */ | 1564 | if (intensity & 0x01) { /* write record zero */ |
1377 | ect = (struct eckd_count *) data; | 1565 | ect = (struct eckd_count *) data; |
1378 | data += sizeof(struct eckd_count); | 1566 | data += sizeof(struct eckd_count); |
1379 | ect->cyl = cyl; | 1567 | ect->cyl = address.cyl; |
1380 | ect->head = head; | 1568 | ect->head = address.head; |
1381 | ect->record = 0; | 1569 | ect->record = 0; |
1382 | ect->kl = 0; | 1570 | ect->kl = 0; |
1383 | ect->dl = 8; | 1571 | ect->dl = 8; |
@@ -1388,11 +1576,11 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1388 | ccw->cda = (__u32)(addr_t) ect; | 1576 | ccw->cda = (__u32)(addr_t) ect; |
1389 | ccw++; | 1577 | ccw++; |
1390 | } | 1578 | } |
1391 | if ((fdata->intensity & ~0x08) & 0x04) { /* erase track */ | 1579 | if ((intensity & ~0x08) & 0x04) { /* erase track */ |
1392 | ect = (struct eckd_count *) data; | 1580 | ect = (struct eckd_count *) data; |
1393 | data += sizeof(struct eckd_count); | 1581 | data += sizeof(struct eckd_count); |
1394 | ect->cyl = cyl; | 1582 | ect->cyl = address.cyl; |
1395 | ect->head = head; | 1583 | ect->head = address.head; |
1396 | ect->record = 1; | 1584 | ect->record = 1; |
1397 | ect->kl = 0; | 1585 | ect->kl = 0; |
1398 | ect->dl = 0; | 1586 | ect->dl = 0; |
@@ -1405,20 +1593,20 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1405 | for (i = 0; i < rpt; i++) { | 1593 | for (i = 0; i < rpt; i++) { |
1406 | ect = (struct eckd_count *) data; | 1594 | ect = (struct eckd_count *) data; |
1407 | data += sizeof(struct eckd_count); | 1595 | data += sizeof(struct eckd_count); |
1408 | ect->cyl = cyl; | 1596 | ect->cyl = address.cyl; |
1409 | ect->head = head; | 1597 | ect->head = address.head; |
1410 | ect->record = i + 1; | 1598 | ect->record = i + 1; |
1411 | ect->kl = 0; | 1599 | ect->kl = 0; |
1412 | ect->dl = fdata->blksize; | 1600 | ect->dl = fdata->blksize; |
1413 | /* Check for special tracks 0-1 when formatting CDL */ | 1601 | /* Check for special tracks 0-1 when formatting CDL */ |
1414 | if ((fdata->intensity & 0x08) && | 1602 | if ((intensity & 0x08) && |
1415 | fdata->start_unit == 0) { | 1603 | fdata->start_unit == 0) { |
1416 | if (i < 3) { | 1604 | if (i < 3) { |
1417 | ect->kl = 4; | 1605 | ect->kl = 4; |
1418 | ect->dl = sizes_trk0[i] - 4; | 1606 | ect->dl = sizes_trk0[i] - 4; |
1419 | } | 1607 | } |
1420 | } | 1608 | } |
1421 | if ((fdata->intensity & 0x08) && | 1609 | if ((intensity & 0x08) && |
1422 | fdata->start_unit == 1) { | 1610 | fdata->start_unit == 1) { |
1423 | ect->kl = 44; | 1611 | ect->kl = 44; |
1424 | ect->dl = LABEL_SIZE - 44; | 1612 | ect->dl = LABEL_SIZE - 44; |
@@ -1479,57 +1667,69 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
1479 | struct irb *irb) | 1667 | struct irb *irb) |
1480 | { | 1668 | { |
1481 | char mask; | 1669 | char mask; |
1670 | char *sense = NULL; | ||
1482 | 1671 | ||
1483 | /* first of all check for state change pending interrupt */ | 1672 | /* first of all check for state change pending interrupt */ |
1484 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; | 1673 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; |
1485 | if ((irb->scsw.cmd.dstat & mask) == mask) { | 1674 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { |
1486 | dasd_generic_handle_state_change(device); | 1675 | dasd_generic_handle_state_change(device); |
1487 | return; | 1676 | return; |
1488 | } | 1677 | } |
1489 | 1678 | ||
1490 | /* summary unit check */ | 1679 | /* summary unit check */ |
1491 | if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) && | 1680 | if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) && |
1492 | (irb->ecw[7] == 0x0D)) { | 1681 | (irb->ecw[7] == 0x0D)) { |
1493 | dasd_alias_handle_summary_unit_check(device, irb); | 1682 | dasd_alias_handle_summary_unit_check(device, irb); |
1494 | return; | 1683 | return; |
1495 | } | 1684 | } |
1496 | 1685 | ||
1497 | 1686 | sense = dasd_get_sense(irb); | |
1498 | /* service information message SIM */ | 1687 | /* service information message SIM */ |
1499 | if (irb->esw.esw0.erw.cons && !(irb->ecw[27] & DASD_SENSE_BIT_0) && | 1688 | if (sense && !(sense[27] & DASD_SENSE_BIT_0) && |
1500 | ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { | 1689 | ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) { |
1501 | dasd_3990_erp_handle_sim(device, irb->ecw); | 1690 | dasd_3990_erp_handle_sim(device, sense); |
1502 | dasd_schedule_device_bh(device); | 1691 | dasd_schedule_device_bh(device); |
1503 | return; | 1692 | return; |
1504 | } | 1693 | } |
1505 | 1694 | ||
1506 | if ((irb->scsw.cmd.cc == 1) && | 1695 | if ((scsw_cc(&irb->scsw) == 1) && |
1507 | (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && | 1696 | (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) && |
1508 | (irb->scsw.cmd.actl & SCSW_ACTL_START_PEND) && | 1697 | (scsw_actl(&irb->scsw) & SCSW_ACTL_START_PEND) && |
1509 | (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND)) { | 1698 | (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND)) { |
1510 | /* fake irb do nothing, they are handled elsewhere */ | 1699 | /* fake irb do nothing, they are handled elsewhere */ |
1511 | dasd_schedule_device_bh(device); | 1700 | dasd_schedule_device_bh(device); |
1512 | return; | 1701 | return; |
1513 | } | 1702 | } |
1514 | 1703 | ||
1515 | if (!(irb->esw.esw0.erw.cons)) { | 1704 | if (!sense) { |
1516 | /* just report other unsolicited interrupts */ | 1705 | /* just report other unsolicited interrupts */ |
1517 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1706 | DBF_DEV_EVENT(DBF_ERR, device, "%s", |
1518 | "unsolicited interrupt received"); | 1707 | "unsolicited interrupt received"); |
1519 | } else { | 1708 | } else { |
1520 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1709 | DBF_DEV_EVENT(DBF_ERR, device, "%s", |
1521 | "unsolicited interrupt received " | 1710 | "unsolicited interrupt received " |
1522 | "(sense available)"); | 1711 | "(sense available)"); |
1523 | device->discipline->dump_sense(device, NULL, irb); | 1712 | device->discipline->dump_sense_dbf(device, NULL, irb, |
1713 | "unsolicited"); | ||
1524 | } | 1714 | } |
1525 | 1715 | ||
1526 | dasd_schedule_device_bh(device); | 1716 | dasd_schedule_device_bh(device); |
1527 | return; | 1717 | return; |
1528 | }; | 1718 | }; |
1529 | 1719 | ||
1530 | static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | 1720 | |
1721 | static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( | ||
1722 | struct dasd_device *startdev, | ||
1531 | struct dasd_block *block, | 1723 | struct dasd_block *block, |
1532 | struct request *req) | 1724 | struct request *req, |
1725 | sector_t first_rec, | ||
1726 | sector_t last_rec, | ||
1727 | sector_t first_trk, | ||
1728 | sector_t last_trk, | ||
1729 | unsigned int first_offs, | ||
1730 | unsigned int last_offs, | ||
1731 | unsigned int blk_per_trk, | ||
1732 | unsigned int blksize) | ||
1533 | { | 1733 | { |
1534 | struct dasd_eckd_private *private; | 1734 | struct dasd_eckd_private *private; |
1535 | unsigned long *idaws; | 1735 | unsigned long *idaws; |
@@ -1539,11 +1739,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | |||
1539 | struct req_iterator iter; | 1739 | struct req_iterator iter; |
1540 | struct bio_vec *bv; | 1740 | struct bio_vec *bv; |
1541 | char *dst; | 1741 | char *dst; |
1542 | unsigned int blksize, blk_per_trk, off; | 1742 | unsigned int off; |
1543 | int count, cidaw, cplength, datasize; | 1743 | int count, cidaw, cplength, datasize; |
1544 | sector_t recid, first_rec, last_rec; | 1744 | sector_t recid; |
1545 | sector_t first_trk, last_trk; | ||
1546 | unsigned int first_offs, last_offs; | ||
1547 | unsigned char cmd, rcmd; | 1745 | unsigned char cmd, rcmd; |
1548 | int use_prefix; | 1746 | int use_prefix; |
1549 | struct dasd_device *basedev; | 1747 | struct dasd_device *basedev; |
@@ -1556,15 +1754,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | |||
1556 | cmd = DASD_ECKD_CCW_WRITE_MT; | 1754 | cmd = DASD_ECKD_CCW_WRITE_MT; |
1557 | else | 1755 | else |
1558 | return ERR_PTR(-EINVAL); | 1756 | return ERR_PTR(-EINVAL); |
1559 | /* Calculate number of blocks/records per track. */ | 1757 | |
1560 | blksize = block->bp_block; | ||
1561 | blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); | ||
1562 | /* Calculate record id of first and last block. */ | ||
1563 | first_rec = first_trk = req->sector >> block->s2b_shift; | ||
1564 | first_offs = sector_div(first_trk, blk_per_trk); | ||
1565 | last_rec = last_trk = | ||
1566 | (req->sector + req->nr_sectors - 1) >> block->s2b_shift; | ||
1567 | last_offs = sector_div(last_trk, blk_per_trk); | ||
1568 | /* Check struct bio and count the number of blocks for the request. */ | 1758 | /* Check struct bio and count the number of blocks for the request. */ |
1569 | count = 0; | 1759 | count = 0; |
1570 | cidaw = 0; | 1760 | cidaw = 0; |
@@ -1714,6 +1904,497 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | |||
1714 | return cqr; | 1904 | return cqr; |
1715 | } | 1905 | } |
1716 | 1906 | ||
1907 | static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | ||
1908 | struct dasd_device *startdev, | ||
1909 | struct dasd_block *block, | ||
1910 | struct request *req, | ||
1911 | sector_t first_rec, | ||
1912 | sector_t last_rec, | ||
1913 | sector_t first_trk, | ||
1914 | sector_t last_trk, | ||
1915 | unsigned int first_offs, | ||
1916 | unsigned int last_offs, | ||
1917 | unsigned int blk_per_trk, | ||
1918 | unsigned int blksize) | ||
1919 | { | ||
1920 | struct dasd_eckd_private *private; | ||
1921 | unsigned long *idaws; | ||
1922 | struct dasd_ccw_req *cqr; | ||
1923 | struct ccw1 *ccw; | ||
1924 | struct req_iterator iter; | ||
1925 | struct bio_vec *bv; | ||
1926 | char *dst, *idaw_dst; | ||
1927 | unsigned int cidaw, cplength, datasize; | ||
1928 | unsigned int tlf; | ||
1929 | sector_t recid; | ||
1930 | unsigned char cmd; | ||
1931 | struct dasd_device *basedev; | ||
1932 | unsigned int trkcount, count, count_to_trk_end; | ||
1933 | unsigned int idaw_len, seg_len, part_len, len_to_track_end; | ||
1934 | unsigned char new_track, end_idaw; | ||
1935 | sector_t trkid; | ||
1936 | unsigned int recoffs; | ||
1937 | |||
1938 | basedev = block->base; | ||
1939 | private = (struct dasd_eckd_private *) basedev->private; | ||
1940 | if (rq_data_dir(req) == READ) | ||
1941 | cmd = DASD_ECKD_CCW_READ_TRACK_DATA; | ||
1942 | else if (rq_data_dir(req) == WRITE) | ||
1943 | cmd = DASD_ECKD_CCW_WRITE_TRACK_DATA; | ||
1944 | else | ||
1945 | return ERR_PTR(-EINVAL); | ||
1946 | |||
1947 | /* Track based I/O needs IDAWs for each page, and not just for | ||
1948 | * 64 bit addresses. We need additional idals for pages | ||
1949 | * that get filled from two tracks, so we use the number | ||
1950 | * of records as upper limit. | ||
1951 | */ | ||
1952 | cidaw = last_rec - first_rec + 1; | ||
1953 | trkcount = last_trk - first_trk + 1; | ||
1954 | |||
1955 | /* 1x prefix + one read/write ccw per track */ | ||
1956 | cplength = 1 + trkcount; | ||
1957 | |||
1958 | /* on 31-bit we need space for two 32 bit addresses per page | ||
1959 | * on 64-bit one 64 bit address | ||
1960 | */ | ||
1961 | datasize = sizeof(struct PFX_eckd_data) + | ||
1962 | cidaw * sizeof(unsigned long long); | ||
1963 | |||
1964 | /* Allocate the ccw request. */ | ||
1965 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | ||
1966 | cplength, datasize, startdev); | ||
1967 | if (IS_ERR(cqr)) | ||
1968 | return cqr; | ||
1969 | ccw = cqr->cpaddr; | ||
1970 | /* transfer length factor: how many bytes to read from the last track */ | ||
1971 | if (first_trk == last_trk) | ||
1972 | tlf = last_offs - first_offs + 1; | ||
1973 | else | ||
1974 | tlf = last_offs + 1; | ||
1975 | tlf *= blksize; | ||
1976 | |||
1977 | if (prefix_LRE(ccw++, cqr->data, first_trk, | ||
1978 | last_trk, cmd, basedev, startdev, | ||
1979 | 1 /* format */, first_offs + 1, | ||
1980 | trkcount, blksize, | ||
1981 | tlf) == -EAGAIN) { | ||
1982 | /* Clock not in sync and XRC is enabled. | ||
1983 | * Try again later. | ||
1984 | */ | ||
1985 | dasd_sfree_request(cqr, startdev); | ||
1986 | return ERR_PTR(-EAGAIN); | ||
1987 | } | ||
1988 | |||
1989 | /* | ||
1990 | * The translation of request into ccw programs must meet the | ||
1991 | * following conditions: | ||
1992 | * - all idaws but the first and the last must address full pages | ||
1993 | * (or 2K blocks on 31-bit) | ||
1994 | * - the scope of a ccw and it's idal ends with the track boundaries | ||
1995 | */ | ||
1996 | idaws = (unsigned long *) (cqr->data + sizeof(struct PFX_eckd_data)); | ||
1997 | recid = first_rec; | ||
1998 | new_track = 1; | ||
1999 | end_idaw = 0; | ||
2000 | len_to_track_end = 0; | ||
2001 | idaw_dst = 0; | ||
2002 | idaw_len = 0; | ||
2003 | rq_for_each_segment(bv, req, iter) { | ||
2004 | dst = page_address(bv->bv_page) + bv->bv_offset; | ||
2005 | seg_len = bv->bv_len; | ||
2006 | while (seg_len) { | ||
2007 | if (new_track) { | ||
2008 | trkid = recid; | ||
2009 | recoffs = sector_div(trkid, blk_per_trk); | ||
2010 | count_to_trk_end = blk_per_trk - recoffs; | ||
2011 | count = min((last_rec - recid + 1), | ||
2012 | (sector_t)count_to_trk_end); | ||
2013 | len_to_track_end = count * blksize; | ||
2014 | ccw[-1].flags |= CCW_FLAG_CC; | ||
2015 | ccw->cmd_code = cmd; | ||
2016 | ccw->count = len_to_track_end; | ||
2017 | ccw->cda = (__u32)(addr_t)idaws; | ||
2018 | ccw->flags = CCW_FLAG_IDA; | ||
2019 | ccw++; | ||
2020 | recid += count; | ||
2021 | new_track = 0; | ||
2022 | } | ||
2023 | /* If we start a new idaw, everything is fine and the | ||
2024 | * start of the new idaw is the start of this segment. | ||
2025 | * If we continue an idaw, we must make sure that the | ||
2026 | * current segment begins where the so far accumulated | ||
2027 | * idaw ends | ||
2028 | */ | ||
2029 | if (!idaw_dst) | ||
2030 | idaw_dst = dst; | ||
2031 | if ((idaw_dst + idaw_len) != dst) { | ||
2032 | dasd_sfree_request(cqr, startdev); | ||
2033 | return ERR_PTR(-ERANGE); | ||
2034 | } | ||
2035 | part_len = min(seg_len, len_to_track_end); | ||
2036 | seg_len -= part_len; | ||
2037 | dst += part_len; | ||
2038 | idaw_len += part_len; | ||
2039 | len_to_track_end -= part_len; | ||
2040 | /* collected memory area ends on an IDA_BLOCK border, | ||
2041 | * -> create an idaw | ||
2042 | * idal_create_words will handle cases where idaw_len | ||
2043 | * is larger then IDA_BLOCK_SIZE | ||
2044 | */ | ||
2045 | if (!(__pa(idaw_dst + idaw_len) & (IDA_BLOCK_SIZE-1))) | ||
2046 | end_idaw = 1; | ||
2047 | /* We also need to end the idaw at track end */ | ||
2048 | if (!len_to_track_end) { | ||
2049 | new_track = 1; | ||
2050 | end_idaw = 1; | ||
2051 | } | ||
2052 | if (end_idaw) { | ||
2053 | idaws = idal_create_words(idaws, idaw_dst, | ||
2054 | idaw_len); | ||
2055 | idaw_dst = 0; | ||
2056 | idaw_len = 0; | ||
2057 | end_idaw = 0; | ||
2058 | } | ||
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | if (blk_noretry_request(req) || | ||
2063 | block->base->features & DASD_FEATURE_FAILFAST) | ||
2064 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | ||
2065 | cqr->startdev = startdev; | ||
2066 | cqr->memdev = startdev; | ||
2067 | cqr->block = block; | ||
2068 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | ||
2069 | cqr->lpm = private->path_data.ppm; | ||
2070 | cqr->retries = 256; | ||
2071 | cqr->buildclk = get_clock(); | ||
2072 | cqr->status = DASD_CQR_FILLED; | ||
2073 | return cqr; | ||
2074 | } | ||
2075 | |||
2076 | static int prepare_itcw(struct itcw *itcw, | ||
2077 | unsigned int trk, unsigned int totrk, int cmd, | ||
2078 | struct dasd_device *basedev, | ||
2079 | struct dasd_device *startdev, | ||
2080 | unsigned int rec_on_trk, int count, | ||
2081 | unsigned int blksize, | ||
2082 | unsigned int total_data_size, | ||
2083 | unsigned int tlf, | ||
2084 | unsigned int blk_per_trk) | ||
2085 | { | ||
2086 | struct PFX_eckd_data pfxdata; | ||
2087 | struct dasd_eckd_private *basepriv, *startpriv; | ||
2088 | struct DE_eckd_data *dedata; | ||
2089 | struct LRE_eckd_data *lredata; | ||
2090 | struct dcw *dcw; | ||
2091 | |||
2092 | u32 begcyl, endcyl; | ||
2093 | u16 heads, beghead, endhead; | ||
2094 | u8 pfx_cmd; | ||
2095 | |||
2096 | int rc = 0; | ||
2097 | int sector = 0; | ||
2098 | int dn, d; | ||
2099 | |||
2100 | |||
2101 | /* setup prefix data */ | ||
2102 | basepriv = (struct dasd_eckd_private *) basedev->private; | ||
2103 | startpriv = (struct dasd_eckd_private *) startdev->private; | ||
2104 | dedata = &pfxdata.define_extent; | ||
2105 | lredata = &pfxdata.locate_record; | ||
2106 | |||
2107 | memset(&pfxdata, 0, sizeof(pfxdata)); | ||
2108 | pfxdata.format = 1; /* PFX with LRE */ | ||
2109 | pfxdata.base_address = basepriv->ned->unit_addr; | ||
2110 | pfxdata.base_lss = basepriv->ned->ID; | ||
2111 | pfxdata.validity.define_extent = 1; | ||
2112 | |||
2113 | /* private uid is kept up to date, conf_data may be outdated */ | ||
2114 | if (startpriv->uid.type != UA_BASE_DEVICE) { | ||
2115 | pfxdata.validity.verify_base = 1; | ||
2116 | if (startpriv->uid.type == UA_HYPER_PAV_ALIAS) | ||
2117 | pfxdata.validity.hyper_pav = 1; | ||
2118 | } | ||
2119 | |||
2120 | switch (cmd) { | ||
2121 | case DASD_ECKD_CCW_READ_TRACK_DATA: | ||
2122 | dedata->mask.perm = 0x1; | ||
2123 | dedata->attributes.operation = basepriv->attrib.operation; | ||
2124 | dedata->blk_size = blksize; | ||
2125 | dedata->ga_extended |= 0x42; | ||
2126 | lredata->operation.orientation = 0x0; | ||
2127 | lredata->operation.operation = 0x0C; | ||
2128 | lredata->auxiliary.check_bytes = 0x01; | ||
2129 | pfx_cmd = DASD_ECKD_CCW_PFX_READ; | ||
2130 | break; | ||
2131 | case DASD_ECKD_CCW_WRITE_TRACK_DATA: | ||
2132 | dedata->mask.perm = 0x02; | ||
2133 | dedata->attributes.operation = basepriv->attrib.operation; | ||
2134 | dedata->blk_size = blksize; | ||
2135 | rc = check_XRC_on_prefix(&pfxdata, basedev); | ||
2136 | dedata->ga_extended |= 0x42; | ||
2137 | lredata->operation.orientation = 0x0; | ||
2138 | lredata->operation.operation = 0x3F; | ||
2139 | lredata->extended_operation = 0x23; | ||
2140 | lredata->auxiliary.check_bytes = 0x2; | ||
2141 | pfx_cmd = DASD_ECKD_CCW_PFX; | ||
2142 | break; | ||
2143 | default: | ||
2144 | DBF_DEV_EVENT(DBF_ERR, basedev, | ||
2145 | "prepare itcw, unknown opcode 0x%x", cmd); | ||
2146 | BUG(); | ||
2147 | break; | ||
2148 | } | ||
2149 | if (rc) | ||
2150 | return rc; | ||
2151 | |||
2152 | dedata->attributes.mode = 0x3; /* ECKD */ | ||
2153 | |||
2154 | heads = basepriv->rdc_data.trk_per_cyl; | ||
2155 | begcyl = trk / heads; | ||
2156 | beghead = trk % heads; | ||
2157 | endcyl = totrk / heads; | ||
2158 | endhead = totrk % heads; | ||
2159 | |||
2160 | /* check for sequential prestage - enhance cylinder range */ | ||
2161 | if (dedata->attributes.operation == DASD_SEQ_PRESTAGE || | ||
2162 | dedata->attributes.operation == DASD_SEQ_ACCESS) { | ||
2163 | |||
2164 | if (endcyl + basepriv->attrib.nr_cyl < basepriv->real_cyl) | ||
2165 | endcyl += basepriv->attrib.nr_cyl; | ||
2166 | else | ||
2167 | endcyl = (basepriv->real_cyl - 1); | ||
2168 | } | ||
2169 | |||
2170 | set_ch_t(&dedata->beg_ext, begcyl, beghead); | ||
2171 | set_ch_t(&dedata->end_ext, endcyl, endhead); | ||
2172 | |||
2173 | dedata->ep_format = 0x20; /* records per track is valid */ | ||
2174 | dedata->ep_rec_per_track = blk_per_trk; | ||
2175 | |||
2176 | if (rec_on_trk) { | ||
2177 | switch (basepriv->rdc_data.dev_type) { | ||
2178 | case 0x3390: | ||
2179 | dn = ceil_quot(blksize + 6, 232); | ||
2180 | d = 9 + ceil_quot(blksize + 6 * (dn + 1), 34); | ||
2181 | sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8; | ||
2182 | break; | ||
2183 | case 0x3380: | ||
2184 | d = 7 + ceil_quot(blksize + 12, 32); | ||
2185 | sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7; | ||
2186 | break; | ||
2187 | } | ||
2188 | } | ||
2189 | |||
2190 | lredata->auxiliary.length_valid = 1; | ||
2191 | lredata->auxiliary.length_scope = 1; | ||
2192 | lredata->auxiliary.imbedded_ccw_valid = 1; | ||
2193 | lredata->length = tlf; | ||
2194 | lredata->imbedded_ccw = cmd; | ||
2195 | lredata->count = count; | ||
2196 | lredata->sector = sector; | ||
2197 | set_ch_t(&lredata->seek_addr, begcyl, beghead); | ||
2198 | lredata->search_arg.cyl = lredata->seek_addr.cyl; | ||
2199 | lredata->search_arg.head = lredata->seek_addr.head; | ||
2200 | lredata->search_arg.record = rec_on_trk; | ||
2201 | |||
2202 | dcw = itcw_add_dcw(itcw, pfx_cmd, 0, | ||
2203 | &pfxdata, sizeof(pfxdata), total_data_size); | ||
2204 | |||
2205 | return rc; | ||
2206 | } | ||
2207 | |||
2208 | static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | ||
2209 | struct dasd_device *startdev, | ||
2210 | struct dasd_block *block, | ||
2211 | struct request *req, | ||
2212 | sector_t first_rec, | ||
2213 | sector_t last_rec, | ||
2214 | sector_t first_trk, | ||
2215 | sector_t last_trk, | ||
2216 | unsigned int first_offs, | ||
2217 | unsigned int last_offs, | ||
2218 | unsigned int blk_per_trk, | ||
2219 | unsigned int blksize) | ||
2220 | { | ||
2221 | struct dasd_eckd_private *private; | ||
2222 | struct dasd_ccw_req *cqr; | ||
2223 | struct req_iterator iter; | ||
2224 | struct bio_vec *bv; | ||
2225 | char *dst; | ||
2226 | unsigned int trkcount, ctidaw; | ||
2227 | unsigned char cmd; | ||
2228 | struct dasd_device *basedev; | ||
2229 | unsigned int tlf; | ||
2230 | struct itcw *itcw; | ||
2231 | struct tidaw *last_tidaw = NULL; | ||
2232 | int itcw_op; | ||
2233 | size_t itcw_size; | ||
2234 | |||
2235 | basedev = block->base; | ||
2236 | private = (struct dasd_eckd_private *) basedev->private; | ||
2237 | if (rq_data_dir(req) == READ) { | ||
2238 | cmd = DASD_ECKD_CCW_READ_TRACK_DATA; | ||
2239 | itcw_op = ITCW_OP_READ; | ||
2240 | } else if (rq_data_dir(req) == WRITE) { | ||
2241 | cmd = DASD_ECKD_CCW_WRITE_TRACK_DATA; | ||
2242 | itcw_op = ITCW_OP_WRITE; | ||
2243 | } else | ||
2244 | return ERR_PTR(-EINVAL); | ||
2245 | |||
2246 | /* trackbased I/O needs address all memory via TIDAWs, | ||
2247 | * not just for 64 bit addresses. This allows us to map | ||
2248 | * each segment directly to one tidaw. | ||
2249 | */ | ||
2250 | trkcount = last_trk - first_trk + 1; | ||
2251 | ctidaw = 0; | ||
2252 | rq_for_each_segment(bv, req, iter) { | ||
2253 | ++ctidaw; | ||
2254 | } | ||
2255 | |||
2256 | /* Allocate the ccw request. */ | ||
2257 | itcw_size = itcw_calc_size(0, ctidaw, 0); | ||
2258 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | ||
2259 | 0, itcw_size, startdev); | ||
2260 | if (IS_ERR(cqr)) | ||
2261 | return cqr; | ||
2262 | |||
2263 | cqr->cpmode = 1; | ||
2264 | cqr->startdev = startdev; | ||
2265 | cqr->memdev = startdev; | ||
2266 | cqr->block = block; | ||
2267 | cqr->expires = 100*HZ; | ||
2268 | cqr->buildclk = get_clock(); | ||
2269 | cqr->status = DASD_CQR_FILLED; | ||
2270 | cqr->retries = 10; | ||
2271 | |||
2272 | /* transfer length factor: how many bytes to read from the last track */ | ||
2273 | if (first_trk == last_trk) | ||
2274 | tlf = last_offs - first_offs + 1; | ||
2275 | else | ||
2276 | tlf = last_offs + 1; | ||
2277 | tlf *= blksize; | ||
2278 | |||
2279 | itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0); | ||
2280 | cqr->cpaddr = itcw_get_tcw(itcw); | ||
2281 | |||
2282 | if (prepare_itcw(itcw, first_trk, last_trk, | ||
2283 | cmd, basedev, startdev, | ||
2284 | first_offs + 1, | ||
2285 | trkcount, blksize, | ||
2286 | (last_rec - first_rec + 1) * blksize, | ||
2287 | tlf, blk_per_trk) == -EAGAIN) { | ||
2288 | /* Clock not in sync and XRC is enabled. | ||
2289 | * Try again later. | ||
2290 | */ | ||
2291 | dasd_sfree_request(cqr, startdev); | ||
2292 | return ERR_PTR(-EAGAIN); | ||
2293 | } | ||
2294 | |||
2295 | /* | ||
2296 | * A tidaw can address 4k of memory, but must not cross page boundaries | ||
2297 | * We can let the block layer handle this by setting | ||
2298 | * blk_queue_segment_boundary to page boundaries and | ||
2299 | * blk_max_segment_size to page size when setting up the request queue. | ||
2300 | */ | ||
2301 | rq_for_each_segment(bv, req, iter) { | ||
2302 | dst = page_address(bv->bv_page) + bv->bv_offset; | ||
2303 | last_tidaw = itcw_add_tidaw(itcw, 0x00, dst, bv->bv_len); | ||
2304 | if (IS_ERR(last_tidaw)) | ||
2305 | return (struct dasd_ccw_req *)last_tidaw; | ||
2306 | } | ||
2307 | |||
2308 | last_tidaw->flags |= 0x80; | ||
2309 | itcw_finalize(itcw); | ||
2310 | |||
2311 | if (blk_noretry_request(req) || | ||
2312 | block->base->features & DASD_FEATURE_FAILFAST) | ||
2313 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | ||
2314 | cqr->startdev = startdev; | ||
2315 | cqr->memdev = startdev; | ||
2316 | cqr->block = block; | ||
2317 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | ||
2318 | cqr->lpm = private->path_data.ppm; | ||
2319 | cqr->retries = 256; | ||
2320 | cqr->buildclk = get_clock(); | ||
2321 | cqr->status = DASD_CQR_FILLED; | ||
2322 | return cqr; | ||
2323 | } | ||
2324 | |||
2325 | static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | ||
2326 | struct dasd_block *block, | ||
2327 | struct request *req) | ||
2328 | { | ||
2329 | int tpm, cmdrtd, cmdwtd; | ||
2330 | int use_prefix; | ||
2331 | |||
2332 | struct dasd_eckd_private *private; | ||
2333 | int fcx_in_css, fcx_in_gneq, fcx_in_features; | ||
2334 | struct dasd_device *basedev; | ||
2335 | sector_t first_rec, last_rec; | ||
2336 | sector_t first_trk, last_trk; | ||
2337 | unsigned int first_offs, last_offs; | ||
2338 | unsigned int blk_per_trk, blksize; | ||
2339 | int cdlspecial; | ||
2340 | struct dasd_ccw_req *cqr; | ||
2341 | |||
2342 | basedev = block->base; | ||
2343 | private = (struct dasd_eckd_private *) basedev->private; | ||
2344 | |||
2345 | /* Calculate number of blocks/records per track. */ | ||
2346 | blksize = block->bp_block; | ||
2347 | blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); | ||
2348 | /* Calculate record id of first and last block. */ | ||
2349 | first_rec = first_trk = req->sector >> block->s2b_shift; | ||
2350 | first_offs = sector_div(first_trk, blk_per_trk); | ||
2351 | last_rec = last_trk = | ||
2352 | (req->sector + req->nr_sectors - 1) >> block->s2b_shift; | ||
2353 | last_offs = sector_div(last_trk, blk_per_trk); | ||
2354 | cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk); | ||
2355 | |||
2356 | /* is transport mode supported ? */ | ||
2357 | fcx_in_css = css_general_characteristics.fcx; | ||
2358 | fcx_in_gneq = private->gneq->reserved2[7] & 0x04; | ||
2359 | fcx_in_features = private->features.feature[40] & 0x80; | ||
2360 | tpm = fcx_in_css && fcx_in_gneq && fcx_in_features; | ||
2361 | |||
2362 | /* is read track data and write track data in command mode supported? */ | ||
2363 | cmdrtd = private->features.feature[9] & 0x20; | ||
2364 | cmdwtd = private->features.feature[12] & 0x40; | ||
2365 | use_prefix = private->features.feature[8] & 0x01; | ||
2366 | |||
2367 | cqr = NULL; | ||
2368 | if (cdlspecial || dasd_page_cache) { | ||
2369 | /* do nothing, just fall through to the cmd mode single case */ | ||
2370 | } else if (!dasd_nofcx && tpm && (first_trk == last_trk)) { | ||
2371 | cqr = dasd_eckd_build_cp_tpm_track(startdev, block, req, | ||
2372 | first_rec, last_rec, | ||
2373 | first_trk, last_trk, | ||
2374 | first_offs, last_offs, | ||
2375 | blk_per_trk, blksize); | ||
2376 | if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN) | ||
2377 | cqr = NULL; | ||
2378 | } else if (use_prefix && | ||
2379 | (((rq_data_dir(req) == READ) && cmdrtd) || | ||
2380 | ((rq_data_dir(req) == WRITE) && cmdwtd))) { | ||
2381 | cqr = dasd_eckd_build_cp_cmd_track(startdev, block, req, | ||
2382 | first_rec, last_rec, | ||
2383 | first_trk, last_trk, | ||
2384 | first_offs, last_offs, | ||
2385 | blk_per_trk, blksize); | ||
2386 | if (IS_ERR(cqr) && PTR_ERR(cqr) != -EAGAIN) | ||
2387 | cqr = NULL; | ||
2388 | } | ||
2389 | if (!cqr) | ||
2390 | cqr = dasd_eckd_build_cp_cmd_single(startdev, block, req, | ||
2391 | first_rec, last_rec, | ||
2392 | first_trk, last_trk, | ||
2393 | first_offs, last_offs, | ||
2394 | blk_per_trk, blksize); | ||
2395 | return cqr; | ||
2396 | } | ||
2397 | |||
1717 | static int | 2398 | static int |
1718 | dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) | 2399 | dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) |
1719 | { | 2400 | { |
@@ -1767,7 +2448,7 @@ out: | |||
1767 | } | 2448 | } |
1768 | 2449 | ||
1769 | /* | 2450 | /* |
1770 | * Modify ccw chain in cqr so it can be started on a base device. | 2451 | * Modify ccw/tcw in cqr so it can be started on a base device. |
1771 | * | 2452 | * |
1772 | * Note that this is not enough to restart the cqr! | 2453 | * Note that this is not enough to restart the cqr! |
1773 | * Either reset cqr->startdev as well (summary unit check handling) | 2454 | * 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) | |||
1777 | { | 2458 | { |
1778 | struct ccw1 *ccw; | 2459 | struct ccw1 *ccw; |
1779 | struct PFX_eckd_data *pfxdata; | 2460 | struct PFX_eckd_data *pfxdata; |
1780 | 2461 | struct tcw *tcw; | |
1781 | ccw = cqr->cpaddr; | 2462 | struct tccb *tccb; |
1782 | pfxdata = cqr->data; | 2463 | struct dcw *dcw; |
1783 | 2464 | ||
1784 | if (ccw->cmd_code == DASD_ECKD_CCW_PFX) { | 2465 | if (cqr->cpmode == 1) { |
2466 | tcw = cqr->cpaddr; | ||
2467 | tccb = tcw_get_tccb(tcw); | ||
2468 | dcw = (struct dcw *)&tccb->tca[0]; | ||
2469 | pfxdata = (struct PFX_eckd_data *)&dcw->cd[0]; | ||
1785 | pfxdata->validity.verify_base = 0; | 2470 | pfxdata->validity.verify_base = 0; |
1786 | pfxdata->validity.hyper_pav = 0; | 2471 | pfxdata->validity.hyper_pav = 0; |
2472 | } else { | ||
2473 | ccw = cqr->cpaddr; | ||
2474 | pfxdata = cqr->data; | ||
2475 | if (ccw->cmd_code == DASD_ECKD_CCW_PFX) { | ||
2476 | pfxdata->validity.verify_base = 0; | ||
2477 | pfxdata->validity.hyper_pav = 0; | ||
2478 | } | ||
1787 | } | 2479 | } |
1788 | } | 2480 | } |
1789 | 2481 | ||
@@ -1861,6 +2553,7 @@ dasd_eckd_release(struct dasd_device *device) | |||
1861 | { | 2553 | { |
1862 | struct dasd_ccw_req *cqr; | 2554 | struct dasd_ccw_req *cqr; |
1863 | int rc; | 2555 | int rc; |
2556 | struct ccw1 *ccw; | ||
1864 | 2557 | ||
1865 | if (!capable(CAP_SYS_ADMIN)) | 2558 | if (!capable(CAP_SYS_ADMIN)) |
1866 | return -EACCES; | 2559 | return -EACCES; |
@@ -1868,14 +2561,15 @@ dasd_eckd_release(struct dasd_device *device) | |||
1868 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2561 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1869 | 1, 32, device); | 2562 | 1, 32, device); |
1870 | if (IS_ERR(cqr)) { | 2563 | if (IS_ERR(cqr)) { |
1871 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 2564 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1872 | "Could not allocate initialization request"); | 2565 | "Could not allocate initialization request"); |
1873 | return PTR_ERR(cqr); | 2566 | return PTR_ERR(cqr); |
1874 | } | 2567 | } |
1875 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE; | 2568 | ccw = cqr->cpaddr; |
1876 | cqr->cpaddr->flags |= CCW_FLAG_SLI; | 2569 | ccw->cmd_code = DASD_ECKD_CCW_RELEASE; |
1877 | cqr->cpaddr->count = 32; | 2570 | ccw->flags |= CCW_FLAG_SLI; |
1878 | cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; | 2571 | ccw->count = 32; |
2572 | ccw->cda = (__u32)(addr_t) cqr->data; | ||
1879 | cqr->startdev = device; | 2573 | cqr->startdev = device; |
1880 | cqr->memdev = device; | 2574 | cqr->memdev = device; |
1881 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 2575 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
@@ -1902,6 +2596,7 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
1902 | { | 2596 | { |
1903 | struct dasd_ccw_req *cqr; | 2597 | struct dasd_ccw_req *cqr; |
1904 | int rc; | 2598 | int rc; |
2599 | struct ccw1 *ccw; | ||
1905 | 2600 | ||
1906 | if (!capable(CAP_SYS_ADMIN)) | 2601 | if (!capable(CAP_SYS_ADMIN)) |
1907 | return -EACCES; | 2602 | return -EACCES; |
@@ -1909,14 +2604,15 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
1909 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2604 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1910 | 1, 32, device); | 2605 | 1, 32, device); |
1911 | if (IS_ERR(cqr)) { | 2606 | if (IS_ERR(cqr)) { |
1912 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 2607 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1913 | "Could not allocate initialization request"); | 2608 | "Could not allocate initialization request"); |
1914 | return PTR_ERR(cqr); | 2609 | return PTR_ERR(cqr); |
1915 | } | 2610 | } |
1916 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE; | 2611 | ccw = cqr->cpaddr; |
1917 | cqr->cpaddr->flags |= CCW_FLAG_SLI; | 2612 | ccw->cmd_code = DASD_ECKD_CCW_RESERVE; |
1918 | cqr->cpaddr->count = 32; | 2613 | ccw->flags |= CCW_FLAG_SLI; |
1919 | cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; | 2614 | ccw->count = 32; |
2615 | ccw->cda = (__u32)(addr_t) cqr->data; | ||
1920 | cqr->startdev = device; | 2616 | cqr->startdev = device; |
1921 | cqr->memdev = device; | 2617 | cqr->memdev = device; |
1922 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 2618 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
@@ -1942,6 +2638,7 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
1942 | { | 2638 | { |
1943 | struct dasd_ccw_req *cqr; | 2639 | struct dasd_ccw_req *cqr; |
1944 | int rc; | 2640 | int rc; |
2641 | struct ccw1 *ccw; | ||
1945 | 2642 | ||
1946 | if (!capable(CAP_SYS_ADMIN)) | 2643 | if (!capable(CAP_SYS_ADMIN)) |
1947 | return -EACCES; | 2644 | return -EACCES; |
@@ -1949,14 +2646,15 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
1949 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2646 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, |
1950 | 1, 32, device); | 2647 | 1, 32, device); |
1951 | if (IS_ERR(cqr)) { | 2648 | if (IS_ERR(cqr)) { |
1952 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 2649 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1953 | "Could not allocate initialization request"); | 2650 | "Could not allocate initialization request"); |
1954 | return PTR_ERR(cqr); | 2651 | return PTR_ERR(cqr); |
1955 | } | 2652 | } |
1956 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK; | 2653 | ccw = cqr->cpaddr; |
1957 | cqr->cpaddr->flags |= CCW_FLAG_SLI; | 2654 | ccw->cmd_code = DASD_ECKD_CCW_SLCK; |
1958 | cqr->cpaddr->count = 32; | 2655 | ccw->flags |= CCW_FLAG_SLI; |
1959 | cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; | 2656 | ccw->count = 32; |
2657 | ccw->cda = (__u32)(addr_t) cqr->data; | ||
1960 | cqr->startdev = device; | 2658 | cqr->startdev = device; |
1961 | cqr->memdev = device; | 2659 | cqr->memdev = device; |
1962 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 2660 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
@@ -1990,7 +2688,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp) | |||
1990 | sizeof(struct dasd_rssd_perf_stats_t)), | 2688 | sizeof(struct dasd_rssd_perf_stats_t)), |
1991 | device); | 2689 | device); |
1992 | if (IS_ERR(cqr)) { | 2690 | if (IS_ERR(cqr)) { |
1993 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 2691 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
1994 | "Could not allocate initialization request"); | 2692 | "Could not allocate initialization request"); |
1995 | return PTR_ERR(cqr); | 2693 | return PTR_ERR(cqr); |
1996 | } | 2694 | } |
@@ -2080,9 +2778,9 @@ dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp) | |||
2080 | return -EFAULT; | 2778 | return -EFAULT; |
2081 | private->attrib = attrib; | 2779 | private->attrib = attrib; |
2082 | 2780 | ||
2083 | DEV_MESSAGE(KERN_INFO, device, | 2781 | dev_info(&device->cdev->dev, |
2084 | "cache operation mode set to %x (%i cylinder prestage)", | 2782 | "The DASD cache mode was set to %x (%i cylinder prestage)\n", |
2085 | private->attrib.operation, private->attrib.nr_cyl); | 2783 | private->attrib.operation, private->attrib.nr_cyl); |
2086 | return 0; | 2784 | return 0; |
2087 | } | 2785 | } |
2088 | 2786 | ||
@@ -2133,7 +2831,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) | |||
2133 | /* setup CCWs for PSF + RSSD */ | 2831 | /* setup CCWs for PSF + RSSD */ |
2134 | cqr = dasd_smalloc_request("ECKD", 2 , 0, device); | 2832 | cqr = dasd_smalloc_request("ECKD", 2 , 0, device); |
2135 | if (IS_ERR(cqr)) { | 2833 | if (IS_ERR(cqr)) { |
2136 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 2834 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2137 | "Could not allocate initialization request"); | 2835 | "Could not allocate initialization request"); |
2138 | rc = PTR_ERR(cqr); | 2836 | rc = PTR_ERR(cqr); |
2139 | goto out_free; | 2837 | goto out_free; |
@@ -2242,11 +2940,54 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) | |||
2242 | return len; | 2940 | return len; |
2243 | } | 2941 | } |
2244 | 2942 | ||
2943 | static void | ||
2944 | dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, | ||
2945 | struct irb *irb, char *reason) | ||
2946 | { | ||
2947 | u64 *sense; | ||
2948 | int sl; | ||
2949 | struct tsb *tsb; | ||
2950 | |||
2951 | sense = NULL; | ||
2952 | tsb = NULL; | ||
2953 | if (req && scsw_is_tm(&req->irb.scsw)) { | ||
2954 | if (irb->scsw.tm.tcw) | ||
2955 | tsb = tcw_get_tsb( | ||
2956 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); | ||
2957 | if (tsb && (irb->scsw.tm.fcxs == 0x01)) { | ||
2958 | switch (tsb->flags & 0x07) { | ||
2959 | case 1: /* tsa_iostat */ | ||
2960 | sense = (u64 *)tsb->tsa.iostat.sense; | ||
2961 | break; | ||
2962 | case 2: /* ts_ddpc */ | ||
2963 | sense = (u64 *)tsb->tsa.ddpc.sense; | ||
2964 | break; | ||
2965 | case 3: /* tsa_intrg */ | ||
2966 | break; | ||
2967 | } | ||
2968 | } | ||
2969 | } else { | ||
2970 | if (irb->esw.esw0.erw.cons) | ||
2971 | sense = (u64 *)irb->ecw; | ||
2972 | } | ||
2973 | if (sense) { | ||
2974 | for (sl = 0; sl < 4; sl++) { | ||
2975 | DBF_DEV_EVENT(DBF_EMERG, device, | ||
2976 | "%s: %016llx %016llx %016llx %016llx", | ||
2977 | reason, sense[0], sense[1], sense[2], | ||
2978 | sense[3]); | ||
2979 | } | ||
2980 | } else { | ||
2981 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", | ||
2982 | "SORRY - NO VALID SENSE AVAILABLE\n"); | ||
2983 | } | ||
2984 | } | ||
2985 | |||
2245 | /* | 2986 | /* |
2246 | * Print sense data and related channel program. | 2987 | * Print sense data and related channel program. |
2247 | * Parts are printed because printk buffer is only 1024 bytes. | 2988 | * Parts are printed because printk buffer is only 1024 bytes. |
2248 | */ | 2989 | */ |
2249 | static void dasd_eckd_dump_sense(struct dasd_device *device, | 2990 | static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, |
2250 | struct dasd_ccw_req *req, struct irb *irb) | 2991 | struct dasd_ccw_req *req, struct irb *irb) |
2251 | { | 2992 | { |
2252 | char *page; | 2993 | char *page; |
@@ -2255,8 +2996,8 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, | |||
2255 | 2996 | ||
2256 | page = (char *) get_zeroed_page(GFP_ATOMIC); | 2997 | page = (char *) get_zeroed_page(GFP_ATOMIC); |
2257 | if (page == NULL) { | 2998 | if (page == NULL) { |
2258 | DEV_MESSAGE(KERN_ERR, device, " %s", | 2999 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2259 | "No memory to dump sense data"); | 3000 | "No memory to dump sense data\n"); |
2260 | return; | 3001 | return; |
2261 | } | 3002 | } |
2262 | /* dump the sense data */ | 3003 | /* dump the sense data */ |
@@ -2265,7 +3006,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, | |||
2265 | dev_name(&device->cdev->dev)); | 3006 | dev_name(&device->cdev->dev)); |
2266 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3007 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
2267 | " in req: %p CS: 0x%02X DS: 0x%02X\n", req, | 3008 | " in req: %p CS: 0x%02X DS: 0x%02X\n", req, |
2268 | irb->scsw.cmd.cstat, irb->scsw.cmd.dstat); | 3009 | scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw)); |
2269 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3010 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
2270 | " device %s: Failing CCW: %p\n", | 3011 | " device %s: Failing CCW: %p\n", |
2271 | dev_name(&device->cdev->dev), | 3012 | dev_name(&device->cdev->dev), |
@@ -2341,6 +3082,147 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, | |||
2341 | free_page((unsigned long) page); | 3082 | free_page((unsigned long) page); |
2342 | } | 3083 | } |
2343 | 3084 | ||
3085 | |||
3086 | /* | ||
3087 | * Print sense data from a tcw. | ||
3088 | */ | ||
3089 | static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | ||
3090 | struct dasd_ccw_req *req, struct irb *irb) | ||
3091 | { | ||
3092 | char *page; | ||
3093 | int len, sl, sct, residual; | ||
3094 | |||
3095 | struct tsb *tsb; | ||
3096 | u8 *sense; | ||
3097 | |||
3098 | |||
3099 | page = (char *) get_zeroed_page(GFP_ATOMIC); | ||
3100 | if (page == NULL) { | ||
3101 | DBF_DEV_EVENT(DBF_WARNING, device, " %s", | ||
3102 | "No memory to dump sense data"); | ||
3103 | return; | ||
3104 | } | ||
3105 | /* dump the sense data */ | ||
3106 | len = sprintf(page, KERN_ERR PRINTK_HEADER | ||
3107 | " I/O status report for device %s:\n", | ||
3108 | dev_name(&device->cdev->dev)); | ||
3109 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3110 | " in req: %p CS: 0x%02X DS: 0x%02X " | ||
3111 | "fcxs: 0x%02X schxs: 0x%02X\n", req, | ||
3112 | scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), | ||
3113 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs); | ||
3114 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3115 | " device %s: Failing TCW: %p\n", | ||
3116 | dev_name(&device->cdev->dev), | ||
3117 | (void *) (addr_t) irb->scsw.tm.tcw); | ||
3118 | |||
3119 | tsb = NULL; | ||
3120 | sense = NULL; | ||
3121 | if (irb->scsw.tm.tcw) | ||
3122 | tsb = tcw_get_tsb( | ||
3123 | (struct tcw *)(unsigned long)irb->scsw.tm.tcw); | ||
3124 | |||
3125 | if (tsb && (irb->scsw.tm.fcxs == 0x01)) { | ||
3126 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3127 | " tsb->length %d\n", tsb->length); | ||
3128 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3129 | " tsb->flags %x\n", tsb->flags); | ||
3130 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3131 | " tsb->dcw_offset %d\n", tsb->dcw_offset); | ||
3132 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3133 | " tsb->count %d\n", tsb->count); | ||
3134 | residual = tsb->count - 28; | ||
3135 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3136 | " residual %d\n", residual); | ||
3137 | |||
3138 | switch (tsb->flags & 0x07) { | ||
3139 | case 1: /* tsa_iostat */ | ||
3140 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3141 | " tsb->tsa.iostat.dev_time %d\n", | ||
3142 | tsb->tsa.iostat.dev_time); | ||
3143 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3144 | " tsb->tsa.iostat.def_time %d\n", | ||
3145 | tsb->tsa.iostat.def_time); | ||
3146 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3147 | " tsb->tsa.iostat.queue_time %d\n", | ||
3148 | tsb->tsa.iostat.queue_time); | ||
3149 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3150 | " tsb->tsa.iostat.dev_busy_time %d\n", | ||
3151 | tsb->tsa.iostat.dev_busy_time); | ||
3152 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3153 | " tsb->tsa.iostat.dev_act_time %d\n", | ||
3154 | tsb->tsa.iostat.dev_act_time); | ||
3155 | sense = tsb->tsa.iostat.sense; | ||
3156 | break; | ||
3157 | case 2: /* ts_ddpc */ | ||
3158 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3159 | " tsb->tsa.ddpc.rc %d\n", tsb->tsa.ddpc.rc); | ||
3160 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3161 | " tsb->tsa.ddpc.rcq: "); | ||
3162 | for (sl = 0; sl < 16; sl++) { | ||
3163 | for (sct = 0; sct < 8; sct++) { | ||
3164 | len += sprintf(page + len, " %02x", | ||
3165 | tsb->tsa.ddpc.rcq[sl]); | ||
3166 | } | ||
3167 | len += sprintf(page + len, "\n"); | ||
3168 | } | ||
3169 | sense = tsb->tsa.ddpc.sense; | ||
3170 | break; | ||
3171 | case 3: /* tsa_intrg */ | ||
3172 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3173 | " tsb->tsa.intrg.: not supportet yet \n"); | ||
3174 | break; | ||
3175 | } | ||
3176 | |||
3177 | if (sense) { | ||
3178 | for (sl = 0; sl < 4; sl++) { | ||
3179 | len += sprintf(page + len, | ||
3180 | KERN_ERR PRINTK_HEADER | ||
3181 | " Sense(hex) %2d-%2d:", | ||
3182 | (8 * sl), ((8 * sl) + 7)); | ||
3183 | for (sct = 0; sct < 8; sct++) { | ||
3184 | len += sprintf(page + len, " %02x", | ||
3185 | sense[8 * sl + sct]); | ||
3186 | } | ||
3187 | len += sprintf(page + len, "\n"); | ||
3188 | } | ||
3189 | |||
3190 | if (sense[27] & DASD_SENSE_BIT_0) { | ||
3191 | /* 24 Byte Sense Data */ | ||
3192 | sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3193 | " 24 Byte: %x MSG %x, " | ||
3194 | "%s MSGb to SYSOP\n", | ||
3195 | sense[7] >> 4, sense[7] & 0x0f, | ||
3196 | sense[1] & 0x10 ? "" : "no"); | ||
3197 | } else { | ||
3198 | /* 32 Byte Sense Data */ | ||
3199 | sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3200 | " 32 Byte: Format: %x " | ||
3201 | "Exception class %x\n", | ||
3202 | sense[6] & 0x0f, sense[22] >> 4); | ||
3203 | } | ||
3204 | } else { | ||
3205 | sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3206 | " SORRY - NO VALID SENSE AVAILABLE\n"); | ||
3207 | } | ||
3208 | } else { | ||
3209 | sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
3210 | " SORRY - NO TSB DATA AVAILABLE\n"); | ||
3211 | } | ||
3212 | printk("%s", page); | ||
3213 | free_page((unsigned long) page); | ||
3214 | } | ||
3215 | |||
3216 | static void dasd_eckd_dump_sense(struct dasd_device *device, | ||
3217 | struct dasd_ccw_req *req, struct irb *irb) | ||
3218 | { | ||
3219 | if (req && scsw_is_tm(&req->irb.scsw)) | ||
3220 | dasd_eckd_dump_sense_tcw(device, req, irb); | ||
3221 | else | ||
3222 | dasd_eckd_dump_sense_ccw(device, req, irb); | ||
3223 | } | ||
3224 | |||
3225 | |||
2344 | /* | 3226 | /* |
2345 | * max_blocks is dependent on the amount of storage that is available | 3227 | * max_blocks is dependent on the amount of storage that is available |
2346 | * in the static io buffer for each device. Currently each device has | 3228 | * in the static io buffer for each device. Currently each device has |
@@ -2375,6 +3257,7 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
2375 | .build_cp = dasd_eckd_build_alias_cp, | 3257 | .build_cp = dasd_eckd_build_alias_cp, |
2376 | .free_cp = dasd_eckd_free_alias_cp, | 3258 | .free_cp = dasd_eckd_free_alias_cp, |
2377 | .dump_sense = dasd_eckd_dump_sense, | 3259 | .dump_sense = dasd_eckd_dump_sense, |
3260 | .dump_sense_dbf = dasd_eckd_dump_sense_dbf, | ||
2378 | .fill_info = dasd_eckd_fill_info, | 3261 | .fill_info = dasd_eckd_fill_info, |
2379 | .ioctl = dasd_eckd_ioctl, | 3262 | .ioctl = dasd_eckd_ioctl, |
2380 | }; | 3263 | }; |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 2476f87d21d0..ad45bcac3ce4 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
@@ -38,8 +38,11 @@ | |||
38 | #define DASD_ECKD_CCW_RELEASE 0x94 | 38 | #define DASD_ECKD_CCW_RELEASE 0x94 |
39 | #define DASD_ECKD_CCW_READ_CKD_MT 0x9e | 39 | #define DASD_ECKD_CCW_READ_CKD_MT 0x9e |
40 | #define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d | 40 | #define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d |
41 | #define DASD_ECKD_CCW_WRITE_TRACK_DATA 0xA5 | ||
42 | #define DASD_ECKD_CCW_READ_TRACK_DATA 0xA6 | ||
41 | #define DASD_ECKD_CCW_RESERVE 0xB4 | 43 | #define DASD_ECKD_CCW_RESERVE 0xB4 |
42 | #define DASD_ECKD_CCW_PFX 0xE7 | 44 | #define DASD_ECKD_CCW_PFX 0xE7 |
45 | #define DASD_ECKD_CCW_PFX_READ 0xEA | ||
43 | #define DASD_ECKD_CCW_RSCK 0xF9 | 46 | #define DASD_ECKD_CCW_RSCK 0xF9 |
44 | 47 | ||
45 | /* | 48 | /* |
@@ -48,6 +51,11 @@ | |||
48 | #define PSF_ORDER_PRSSD 0x18 | 51 | #define PSF_ORDER_PRSSD 0x18 |
49 | #define PSF_ORDER_SSC 0x1D | 52 | #define PSF_ORDER_SSC 0x1D |
50 | 53 | ||
54 | /* | ||
55 | * Size that is reportet for large volumes in the old 16-bit no_cyl field | ||
56 | */ | ||
57 | #define LV_COMPAT_CYL 0xFFFE | ||
58 | |||
51 | /***************************************************************************** | 59 | /***************************************************************************** |
52 | * SECTION: Type Definitions | 60 | * SECTION: Type Definitions |
53 | ****************************************************************************/ | 61 | ****************************************************************************/ |
@@ -118,7 +126,9 @@ struct DE_eckd_data { | |||
118 | unsigned long long ep_sys_time; /* Ext Parameter - System Time Stamp */ | 126 | unsigned long long ep_sys_time; /* Ext Parameter - System Time Stamp */ |
119 | __u8 ep_format; /* Extended Parameter format byte */ | 127 | __u8 ep_format; /* Extended Parameter format byte */ |
120 | __u8 ep_prio; /* Extended Parameter priority I/O byte */ | 128 | __u8 ep_prio; /* Extended Parameter priority I/O byte */ |
121 | __u8 ep_reserved[6]; /* Extended Parameter Reserved */ | 129 | __u8 ep_reserved1; /* Extended Parameter Reserved */ |
130 | __u8 ep_rec_per_track; /* Number of records on a track */ | ||
131 | __u8 ep_reserved[4]; /* Extended Parameter Reserved */ | ||
122 | } __attribute__ ((packed)); | 132 | } __attribute__ ((packed)); |
123 | 133 | ||
124 | struct LO_eckd_data { | 134 | struct LO_eckd_data { |
@@ -139,11 +149,37 @@ struct LO_eckd_data { | |||
139 | __u16 length; | 149 | __u16 length; |
140 | } __attribute__ ((packed)); | 150 | } __attribute__ ((packed)); |
141 | 151 | ||
152 | struct LRE_eckd_data { | ||
153 | struct { | ||
154 | unsigned char orientation:2; | ||
155 | unsigned char operation:6; | ||
156 | } __attribute__ ((packed)) operation; | ||
157 | struct { | ||
158 | unsigned char length_valid:1; | ||
159 | unsigned char length_scope:1; | ||
160 | unsigned char imbedded_ccw_valid:1; | ||
161 | unsigned char check_bytes:2; | ||
162 | unsigned char imbedded_count_valid:1; | ||
163 | unsigned char reserved:1; | ||
164 | unsigned char read_count_suffix:1; | ||
165 | } __attribute__ ((packed)) auxiliary; | ||
166 | __u8 imbedded_ccw; | ||
167 | __u8 count; | ||
168 | struct ch_t seek_addr; | ||
169 | struct chr_t search_arg; | ||
170 | __u8 sector; | ||
171 | __u16 length; | ||
172 | __u8 imbedded_count; | ||
173 | __u8 extended_operation; | ||
174 | __u16 extended_parameter_length; | ||
175 | __u8 extended_parameter[0]; | ||
176 | } __attribute__ ((packed)); | ||
177 | |||
142 | /* Prefix data for format 0x00 and 0x01 */ | 178 | /* Prefix data for format 0x00 and 0x01 */ |
143 | struct PFX_eckd_data { | 179 | struct PFX_eckd_data { |
144 | unsigned char format; | 180 | unsigned char format; |
145 | struct { | 181 | struct { |
146 | unsigned char define_extend:1; | 182 | unsigned char define_extent:1; |
147 | unsigned char time_stamp:1; | 183 | unsigned char time_stamp:1; |
148 | unsigned char verify_base:1; | 184 | unsigned char verify_base:1; |
149 | unsigned char hyper_pav:1; | 185 | unsigned char hyper_pav:1; |
@@ -153,9 +189,8 @@ struct PFX_eckd_data { | |||
153 | __u8 aux; | 189 | __u8 aux; |
154 | __u8 base_lss; | 190 | __u8 base_lss; |
155 | __u8 reserved[7]; | 191 | __u8 reserved[7]; |
156 | struct DE_eckd_data define_extend; | 192 | struct DE_eckd_data define_extent; |
157 | struct LO_eckd_data locate_record; | 193 | struct LRE_eckd_data locate_record; |
158 | __u8 LO_extended_data[4]; | ||
159 | } __attribute__ ((packed)); | 194 | } __attribute__ ((packed)); |
160 | 195 | ||
161 | struct dasd_eckd_characteristics { | 196 | struct dasd_eckd_characteristics { |
@@ -228,7 +263,8 @@ struct dasd_eckd_characteristics { | |||
228 | __u8 factor7; | 263 | __u8 factor7; |
229 | __u8 factor8; | 264 | __u8 factor8; |
230 | __u8 reserved2[3]; | 265 | __u8 reserved2[3]; |
231 | __u8 reserved3[10]; | 266 | __u8 reserved3[6]; |
267 | __u32 long_no_cyl; | ||
232 | } __attribute__ ((packed)); | 268 | } __attribute__ ((packed)); |
233 | 269 | ||
234 | /* elements of the configuration data */ | 270 | /* elements of the configuration data */ |
@@ -406,6 +442,7 @@ struct dasd_eckd_private { | |||
406 | int uses_cdl; | 442 | int uses_cdl; |
407 | struct attrib_data_t attrib; /* e.g. cache operations */ | 443 | struct attrib_data_t attrib; /* e.g. cache operations */ |
408 | struct dasd_rssd_features features; | 444 | struct dasd_rssd_features features; |
445 | u32 real_cyl; | ||
409 | 446 | ||
410 | /* alias managemnet */ | 447 | /* alias managemnet */ |
411 | struct dasd_uid uid; | 448 | struct dasd_uid uid; |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index f8e05ce98621..c24c8c30380d 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> | 6 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "dasd" | ||
10 | |||
9 | #include <linux/init.h> | 11 | #include <linux/init.h> |
10 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
11 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
@@ -297,11 +299,12 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, | |||
297 | struct dasd_eer_header header; | 299 | struct dasd_eer_header header; |
298 | unsigned long flags; | 300 | unsigned long flags; |
299 | struct eerbuffer *eerb; | 301 | struct eerbuffer *eerb; |
302 | char *sense; | ||
300 | 303 | ||
301 | /* go through cqr chain and count the valid sense data sets */ | 304 | /* go through cqr chain and count the valid sense data sets */ |
302 | data_size = 0; | 305 | data_size = 0; |
303 | for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) | 306 | for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) |
304 | if (temp_cqr->irb.esw.esw0.erw.cons) | 307 | if (dasd_get_sense(&temp_cqr->irb)) |
305 | data_size += 32; | 308 | data_size += 32; |
306 | 309 | ||
307 | header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ | 310 | header.total_size = sizeof(header) + data_size + 4; /* "EOR" */ |
@@ -316,9 +319,11 @@ static void dasd_eer_write_standard_trigger(struct dasd_device *device, | |||
316 | list_for_each_entry(eerb, &bufferlist, list) { | 319 | list_for_each_entry(eerb, &bufferlist, list) { |
317 | dasd_eer_start_record(eerb, header.total_size); | 320 | dasd_eer_start_record(eerb, header.total_size); |
318 | dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header)); | 321 | dasd_eer_write_buffer(eerb, (char *) &header, sizeof(header)); |
319 | for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) | 322 | for (temp_cqr = cqr; temp_cqr; temp_cqr = temp_cqr->refers) { |
320 | if (temp_cqr->irb.esw.esw0.erw.cons) | 323 | sense = dasd_get_sense(&temp_cqr->irb); |
321 | dasd_eer_write_buffer(eerb, cqr->irb.ecw, 32); | 324 | if (sense) |
325 | dasd_eer_write_buffer(eerb, sense, 32); | ||
326 | } | ||
322 | dasd_eer_write_buffer(eerb, "EOR", 4); | 327 | dasd_eer_write_buffer(eerb, "EOR", 4); |
323 | } | 328 | } |
324 | spin_unlock_irqrestore(&bufferlock, flags); | 329 | spin_unlock_irqrestore(&bufferlock, flags); |
@@ -451,6 +456,7 @@ int dasd_eer_enable(struct dasd_device *device) | |||
451 | { | 456 | { |
452 | struct dasd_ccw_req *cqr; | 457 | struct dasd_ccw_req *cqr; |
453 | unsigned long flags; | 458 | unsigned long flags; |
459 | struct ccw1 *ccw; | ||
454 | 460 | ||
455 | if (device->eer_cqr) | 461 | if (device->eer_cqr) |
456 | return 0; | 462 | return 0; |
@@ -468,10 +474,11 @@ int dasd_eer_enable(struct dasd_device *device) | |||
468 | cqr->expires = 10 * HZ; | 474 | cqr->expires = 10 * HZ; |
469 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 475 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
470 | 476 | ||
471 | cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; | 477 | ccw = cqr->cpaddr; |
472 | cqr->cpaddr->count = SNSS_DATA_SIZE; | 478 | ccw->cmd_code = DASD_ECKD_CCW_SNSS; |
473 | cqr->cpaddr->flags = 0; | 479 | ccw->count = SNSS_DATA_SIZE; |
474 | cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; | 480 | ccw->flags = 0; |
481 | ccw->cda = (__u32)(addr_t) cqr->data; | ||
475 | 482 | ||
476 | cqr->buildclk = get_clock(); | 483 | cqr->buildclk = get_clock(); |
477 | cqr->status = DASD_CQR_FILLED; | 484 | cqr->status = DASD_CQR_FILLED; |
@@ -534,7 +541,7 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) | |||
534 | if (eerb->buffer_page_count < 1 || | 541 | if (eerb->buffer_page_count < 1 || |
535 | eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { | 542 | eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { |
536 | kfree(eerb); | 543 | kfree(eerb); |
537 | MESSAGE(KERN_WARNING, "can't open device since module " | 544 | DBF_EVENT(DBF_WARNING, "can't open device since module " |
538 | "parameter eer_pages is smaller than 1 or" | 545 | "parameter eer_pages is smaller than 1 or" |
539 | " bigger than %d", (int)(INT_MAX / PAGE_SIZE)); | 546 | " bigger than %d", (int)(INT_MAX / PAGE_SIZE)); |
540 | unlock_kernel(); | 547 | unlock_kernel(); |
@@ -687,7 +694,7 @@ int __init dasd_eer_init(void) | |||
687 | if (rc) { | 694 | if (rc) { |
688 | kfree(dasd_eer_dev); | 695 | kfree(dasd_eer_dev); |
689 | dasd_eer_dev = NULL; | 696 | dasd_eer_dev = NULL; |
690 | MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " | 697 | DBF_EVENT(DBF_ERR, "%s", "dasd_eer_init could not " |
691 | "register misc device"); | 698 | "register misc device"); |
692 | return rc; | 699 | return rc; |
693 | } | 700 | } |
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 8f10000851a3..d970ce2814be 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c | |||
@@ -9,6 +9,8 @@ | |||
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define KMSG_COMPONENT "dasd" | ||
13 | |||
12 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
14 | 16 | ||
@@ -91,14 +93,14 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr) | |||
91 | 93 | ||
92 | /* just retry - there is nothing to save ... I got no sense data.... */ | 94 | /* just retry - there is nothing to save ... I got no sense data.... */ |
93 | if (cqr->retries > 0) { | 95 | if (cqr->retries > 0) { |
94 | DEV_MESSAGE (KERN_DEBUG, device, | 96 | DBF_DEV_EVENT(DBF_DEBUG, device, |
95 | "default ERP called (%i retries left)", | 97 | "default ERP called (%i retries left)", |
96 | cqr->retries); | 98 | cqr->retries); |
97 | cqr->lpm = LPM_ANYPATH; | 99 | cqr->lpm = LPM_ANYPATH; |
98 | cqr->status = DASD_CQR_FILLED; | 100 | cqr->status = DASD_CQR_FILLED; |
99 | } else { | 101 | } else { |
100 | DEV_MESSAGE (KERN_WARNING, device, "%s", | 102 | dev_err(&device->cdev->dev, |
101 | "default ERP called (NO retry left)"); | 103 | "default ERP has run out of retries and failed\n"); |
102 | cqr->status = DASD_CQR_FAILED; | 104 | cqr->status = DASD_CQR_FAILED; |
103 | cqr->stopclk = get_clock(); | 105 | cqr->stopclk = get_clock(); |
104 | } | 106 | } |
@@ -162,8 +164,21 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) | |||
162 | device->discipline->dump_sense(device, cqr, irb); | 164 | device->discipline->dump_sense(device, cqr, irb); |
163 | } | 165 | } |
164 | 166 | ||
167 | void | ||
168 | dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb) | ||
169 | { | ||
170 | struct dasd_device *device; | ||
171 | |||
172 | device = cqr->startdev; | ||
173 | /* dump sense data to s390 debugfeature*/ | ||
174 | if (device->discipline && device->discipline->dump_sense_dbf) | ||
175 | device->discipline->dump_sense_dbf(device, cqr, irb, "log"); | ||
176 | } | ||
177 | EXPORT_SYMBOL(dasd_log_sense_dbf); | ||
178 | |||
165 | EXPORT_SYMBOL(dasd_default_erp_action); | 179 | EXPORT_SYMBOL(dasd_default_erp_action); |
166 | EXPORT_SYMBOL(dasd_default_erp_postaction); | 180 | EXPORT_SYMBOL(dasd_default_erp_postaction); |
167 | EXPORT_SYMBOL(dasd_alloc_erp_request); | 181 | EXPORT_SYMBOL(dasd_alloc_erp_request); |
168 | EXPORT_SYMBOL(dasd_free_erp_request); | 182 | EXPORT_SYMBOL(dasd_free_erp_request); |
169 | EXPORT_SYMBOL(dasd_log_sense); | 183 | EXPORT_SYMBOL(dasd_log_sense); |
184 | |||
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index f1d176021694..a3eb6fd14673 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "dasd" | ||
10 | |||
9 | #include <linux/stddef.h> | 11 | #include <linux/stddef.h> |
10 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
11 | #include <asm/debug.h> | 13 | #include <asm/debug.h> |
@@ -128,17 +130,18 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
128 | private = kzalloc(sizeof(struct dasd_fba_private), | 130 | private = kzalloc(sizeof(struct dasd_fba_private), |
129 | GFP_KERNEL | GFP_DMA); | 131 | GFP_KERNEL | GFP_DMA); |
130 | if (private == NULL) { | 132 | if (private == NULL) { |
131 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 133 | dev_warn(&device->cdev->dev, |
132 | "memory allocation failed for private " | 134 | "Allocating memory for private DASD " |
133 | "data"); | 135 | "data failed\n"); |
134 | return -ENOMEM; | 136 | return -ENOMEM; |
135 | } | 137 | } |
136 | device->private = (void *) private; | 138 | device->private = (void *) private; |
137 | } | 139 | } |
138 | block = dasd_alloc_block(); | 140 | block = dasd_alloc_block(); |
139 | if (IS_ERR(block)) { | 141 | if (IS_ERR(block)) { |
140 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 142 | DBF_EVENT(DBF_WARNING, "could not allocate dasd block " |
141 | "could not allocate dasd block structure"); | 143 | "structure for device: %s", |
144 | dev_name(&device->cdev->dev)); | ||
142 | device->private = NULL; | 145 | device->private = NULL; |
143 | kfree(private); | 146 | kfree(private); |
144 | return PTR_ERR(block); | 147 | return PTR_ERR(block); |
@@ -150,9 +153,9 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
150 | rdc_data = (void *) &(private->rdc_data); | 153 | rdc_data = (void *) &(private->rdc_data); |
151 | rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32); | 154 | rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32); |
152 | if (rc) { | 155 | if (rc) { |
153 | DEV_MESSAGE(KERN_WARNING, device, | 156 | DBF_EVENT(DBF_WARNING, "Read device characteristics returned " |
154 | "Read device characteristics returned error %d", | 157 | "error %d for device: %s", |
155 | rc); | 158 | rc, dev_name(&device->cdev->dev)); |
156 | device->block = NULL; | 159 | device->block = NULL; |
157 | dasd_free_block(block); | 160 | dasd_free_block(block); |
158 | device->private = NULL; | 161 | device->private = NULL; |
@@ -160,15 +163,16 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
160 | return rc; | 163 | return rc; |
161 | } | 164 | } |
162 | 165 | ||
163 | DEV_MESSAGE(KERN_INFO, device, | 166 | dev_info(&device->cdev->dev, |
164 | "%04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)", | 167 | "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB " |
165 | cdev->id.dev_type, | 168 | "and %d B/blk\n", |
166 | cdev->id.dev_model, | 169 | cdev->id.dev_type, |
167 | cdev->id.cu_type, | 170 | cdev->id.dev_model, |
168 | cdev->id.cu_model, | 171 | cdev->id.cu_type, |
169 | ((private->rdc_data.blk_bdsa * | 172 | cdev->id.cu_model, |
170 | (private->rdc_data.blk_size >> 9)) >> 11), | 173 | ((private->rdc_data.blk_bdsa * |
171 | private->rdc_data.blk_size); | 174 | (private->rdc_data.blk_size >> 9)) >> 11), |
175 | private->rdc_data.blk_size); | ||
172 | return 0; | 176 | return 0; |
173 | } | 177 | } |
174 | 178 | ||
@@ -180,7 +184,7 @@ static int dasd_fba_do_analysis(struct dasd_block *block) | |||
180 | private = (struct dasd_fba_private *) block->base->private; | 184 | private = (struct dasd_fba_private *) block->base->private; |
181 | rc = dasd_check_blocksize(private->rdc_data.blk_size); | 185 | rc = dasd_check_blocksize(private->rdc_data.blk_size); |
182 | if (rc) { | 186 | if (rc) { |
183 | DEV_MESSAGE(KERN_INFO, block->base, "unknown blocksize %d", | 187 | DBF_DEV_EVENT(DBF_WARNING, block->base, "unknown blocksize %d", |
184 | private->rdc_data.blk_size); | 188 | private->rdc_data.blk_size); |
185 | return rc; | 189 | return rc; |
186 | } | 190 | } |
@@ -215,7 +219,7 @@ dasd_fba_erp_postaction(struct dasd_ccw_req * cqr) | |||
215 | if (cqr->function == dasd_default_erp_action) | 219 | if (cqr->function == dasd_default_erp_action) |
216 | return dasd_default_erp_postaction; | 220 | return dasd_default_erp_postaction; |
217 | 221 | ||
218 | DEV_MESSAGE(KERN_WARNING, cqr->startdev, "unknown ERP action %p", | 222 | DBF_DEV_EVENT(DBF_WARNING, cqr->startdev, "unknown ERP action %p", |
219 | cqr->function); | 223 | cqr->function); |
220 | return NULL; | 224 | return NULL; |
221 | } | 225 | } |
@@ -233,9 +237,9 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device, | |||
233 | } | 237 | } |
234 | 238 | ||
235 | /* check for unsolicited interrupts */ | 239 | /* check for unsolicited interrupts */ |
236 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 240 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
237 | "unsolicited interrupt received"); | 241 | "unsolicited interrupt received"); |
238 | device->discipline->dump_sense(device, NULL, irb); | 242 | device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited"); |
239 | dasd_schedule_device_bh(device); | 243 | dasd_schedule_device_bh(device); |
240 | return; | 244 | return; |
241 | }; | 245 | }; |
@@ -437,6 +441,25 @@ dasd_fba_fill_info(struct dasd_device * device, | |||
437 | } | 441 | } |
438 | 442 | ||
439 | static void | 443 | static void |
444 | dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, | ||
445 | struct irb *irb, char *reason) | ||
446 | { | ||
447 | int sl; | ||
448 | if (irb->esw.esw0.erw.cons) { | ||
449 | for (sl = 0; sl < 4; sl++) { | ||
450 | DBF_DEV_EVENT(DBF_EMERG, device, | ||
451 | "%s: %08x %08x %08x %08x", | ||
452 | reason, irb->ecw[8 * 0], irb->ecw[8 * 1], | ||
453 | irb->ecw[8 * 2], irb->ecw[8 * 3]); | ||
454 | } | ||
455 | } else { | ||
456 | DBF_DEV_EVENT(DBF_EMERG, device, "%s", | ||
457 | "SORRY - NO VALID SENSE AVAILABLE\n"); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | |||
462 | static void | ||
440 | dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | 463 | dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, |
441 | struct irb *irb) | 464 | struct irb *irb) |
442 | { | 465 | { |
@@ -446,7 +469,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
446 | 469 | ||
447 | page = (char *) get_zeroed_page(GFP_ATOMIC); | 470 | page = (char *) get_zeroed_page(GFP_ATOMIC); |
448 | if (page == NULL) { | 471 | if (page == NULL) { |
449 | DEV_MESSAGE(KERN_ERR, device, " %s", | 472 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
450 | "No memory to dump sense data"); | 473 | "No memory to dump sense data"); |
451 | return; | 474 | return; |
452 | } | 475 | } |
@@ -476,8 +499,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
476 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 499 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
477 | " SORRY - NO VALID SENSE AVAILABLE\n"); | 500 | " SORRY - NO VALID SENSE AVAILABLE\n"); |
478 | } | 501 | } |
479 | MESSAGE_LOG(KERN_ERR, "%s", | 502 | printk(KERN_ERR "%s", page); |
480 | page + sizeof(KERN_ERR PRINTK_HEADER)); | ||
481 | 503 | ||
482 | /* dump the Channel Program */ | 504 | /* dump the Channel Program */ |
483 | /* print first CCWs (maximum 8) */ | 505 | /* print first CCWs (maximum 8) */ |
@@ -498,8 +520,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
498 | len += sprintf(page + len, "\n"); | 520 | len += sprintf(page + len, "\n"); |
499 | act++; | 521 | act++; |
500 | } | 522 | } |
501 | MESSAGE_LOG(KERN_ERR, "%s", | 523 | printk(KERN_ERR "%s", page); |
502 | page + sizeof(KERN_ERR PRINTK_HEADER)); | ||
503 | 524 | ||
504 | 525 | ||
505 | /* print failing CCW area */ | 526 | /* print failing CCW area */ |
@@ -540,8 +561,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
540 | act++; | 561 | act++; |
541 | } | 562 | } |
542 | if (len > 0) | 563 | if (len > 0) |
543 | MESSAGE_LOG(KERN_ERR, "%s", | 564 | printk(KERN_ERR "%s", page); |
544 | page + sizeof(KERN_ERR PRINTK_HEADER)); | ||
545 | free_page((unsigned long) page); | 565 | free_page((unsigned long) page); |
546 | } | 566 | } |
547 | 567 | ||
@@ -576,6 +596,7 @@ static struct dasd_discipline dasd_fba_discipline = { | |||
576 | .build_cp = dasd_fba_build_cp, | 596 | .build_cp = dasd_fba_build_cp, |
577 | .free_cp = dasd_fba_free_cp, | 597 | .free_cp = dasd_fba_free_cp, |
578 | .dump_sense = dasd_fba_dump_sense, | 598 | .dump_sense = dasd_fba_dump_sense, |
599 | .dump_sense_dbf = dasd_fba_dump_sense_dbf, | ||
579 | .fill_info = dasd_fba_fill_info, | 600 | .fill_info = dasd_fba_fill_info, |
580 | }; | 601 | }; |
581 | 602 | ||
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index e99d566b69cc..d3198303b93c 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "dasd" | ||
15 | |||
14 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
15 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
16 | #include <linux/blkpg.h> | 18 | #include <linux/blkpg.h> |
@@ -163,9 +165,8 @@ int dasd_gendisk_init(void) | |||
163 | /* Register to static dasd major 94 */ | 165 | /* Register to static dasd major 94 */ |
164 | rc = register_blkdev(DASD_MAJOR, "dasd"); | 166 | rc = register_blkdev(DASD_MAJOR, "dasd"); |
165 | if (rc != 0) { | 167 | if (rc != 0) { |
166 | MESSAGE(KERN_WARNING, | 168 | pr_warning("Registering the device driver with major number " |
167 | "Couldn't register successfully to " | 169 | "%d failed\n", DASD_MAJOR); |
168 | "major no %d", DASD_MAJOR); | ||
169 | return rc; | 170 | return rc; |
170 | } | 171 | } |
171 | return 0; | 172 | return 0; |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 4a39084d9c95..c1e487f774c6 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -112,6 +112,9 @@ do { \ | |||
112 | d_data); \ | 112 | d_data); \ |
113 | } while(0) | 113 | } while(0) |
114 | 114 | ||
115 | /* limit size for an errorstring */ | ||
116 | #define ERRORLENGTH 30 | ||
117 | |||
115 | /* definition of dbf debug levels */ | 118 | /* definition of dbf debug levels */ |
116 | #define DBF_EMERG 0 /* system is unusable */ | 119 | #define DBF_EMERG 0 /* system is unusable */ |
117 | #define DBF_ALERT 1 /* action must be taken immediately */ | 120 | #define DBF_ALERT 1 /* action must be taken immediately */ |
@@ -157,7 +160,8 @@ struct dasd_ccw_req { | |||
157 | struct dasd_block *block; /* the originating block device */ | 160 | struct dasd_block *block; /* the originating block device */ |
158 | struct dasd_device *memdev; /* the device used to allocate this */ | 161 | struct dasd_device *memdev; /* the device used to allocate this */ |
159 | struct dasd_device *startdev; /* device the request is started on */ | 162 | struct dasd_device *startdev; /* device the request is started on */ |
160 | struct ccw1 *cpaddr; /* address of channel program */ | 163 | void *cpaddr; /* address of ccw or tcw */ |
164 | unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */ | ||
161 | char status; /* status of this request */ | 165 | char status; /* status of this request */ |
162 | short retries; /* A retry counter */ | 166 | short retries; /* A retry counter */ |
163 | unsigned long flags; /* flags of this request */ | 167 | unsigned long flags; /* flags of this request */ |
@@ -280,6 +284,8 @@ struct dasd_discipline { | |||
280 | dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); | 284 | dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); |
281 | void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, | 285 | void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, |
282 | struct irb *); | 286 | struct irb *); |
287 | void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *, | ||
288 | struct irb *, char *); | ||
283 | 289 | ||
284 | void (*handle_unsolicited_interrupt) (struct dasd_device *, | 290 | void (*handle_unsolicited_interrupt) (struct dasd_device *, |
285 | struct irb *); | 291 | struct irb *); |
@@ -378,7 +384,7 @@ struct dasd_block { | |||
378 | struct block_device *bdev; | 384 | struct block_device *bdev; |
379 | atomic_t open_count; | 385 | atomic_t open_count; |
380 | 386 | ||
381 | unsigned long blocks; /* size of volume in blocks */ | 387 | unsigned long long blocks; /* size of volume in blocks */ |
382 | unsigned int bp_block; /* bytes per block */ | 388 | unsigned int bp_block; /* bytes per block */ |
383 | unsigned int s2b_shift; /* log2 (bp_block/512) */ | 389 | unsigned int s2b_shift; /* log2 (bp_block/512) */ |
384 | 390 | ||
@@ -573,12 +579,14 @@ int dasd_generic_notify(struct ccw_device *, int); | |||
573 | void dasd_generic_handle_state_change(struct dasd_device *); | 579 | void dasd_generic_handle_state_change(struct dasd_device *); |
574 | 580 | ||
575 | int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int); | 581 | int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int); |
582 | char *dasd_get_sense(struct irb *); | ||
576 | 583 | ||
577 | /* externals in dasd_devmap.c */ | 584 | /* externals in dasd_devmap.c */ |
578 | extern int dasd_max_devindex; | 585 | extern int dasd_max_devindex; |
579 | extern int dasd_probeonly; | 586 | extern int dasd_probeonly; |
580 | extern int dasd_autodetect; | 587 | extern int dasd_autodetect; |
581 | extern int dasd_nopav; | 588 | extern int dasd_nopav; |
589 | extern int dasd_nofcx; | ||
582 | 590 | ||
583 | int dasd_devmap_init(void); | 591 | int dasd_devmap_init(void); |
584 | void dasd_devmap_exit(void); | 592 | void dasd_devmap_exit(void); |
@@ -623,6 +631,7 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int, | |||
623 | struct dasd_device *); | 631 | struct dasd_device *); |
624 | void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); | 632 | void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); |
625 | void dasd_log_sense(struct dasd_ccw_req *, struct irb *); | 633 | void dasd_log_sense(struct dasd_ccw_req *, struct irb *); |
634 | void dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb); | ||
626 | 635 | ||
627 | /* externals in dasd_3990_erp.c */ | 636 | /* externals in dasd_3990_erp.c */ |
628 | struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *); | 637 | struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *); |
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index b82d816d9ef7..4ce3f72ee1c1 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
@@ -9,6 +9,9 @@ | |||
9 | * | 9 | * |
10 | * i/o controls for the dasd driver. | 10 | * i/o controls for the dasd driver. |
11 | */ | 11 | */ |
12 | |||
13 | #define KMSG_COMPONENT "dasd" | ||
14 | |||
12 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
13 | #include <linux/major.h> | 16 | #include <linux/major.h> |
14 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
@@ -94,7 +97,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) | |||
94 | if (!capable (CAP_SYS_ADMIN)) | 97 | if (!capable (CAP_SYS_ADMIN)) |
95 | return -EACCES; | 98 | return -EACCES; |
96 | 99 | ||
97 | DEV_MESSAGE(KERN_DEBUG, base, "%s", "Quiesce IO on device"); | 100 | dev_info(&base->cdev->dev, "The DASD has been put in the quiesce " |
101 | "state\n"); | ||
98 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); | 102 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); |
99 | base->stopped |= DASD_STOPPED_QUIESCE; | 103 | base->stopped |= DASD_STOPPED_QUIESCE; |
100 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); | 104 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); |
@@ -103,7 +107,7 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) | |||
103 | 107 | ||
104 | 108 | ||
105 | /* | 109 | /* |
106 | * Quiesce device. | 110 | * Resume device. |
107 | */ | 111 | */ |
108 | static int dasd_ioctl_resume(struct dasd_block *block) | 112 | static int dasd_ioctl_resume(struct dasd_block *block) |
109 | { | 113 | { |
@@ -114,7 +118,8 @@ static int dasd_ioctl_resume(struct dasd_block *block) | |||
114 | if (!capable (CAP_SYS_ADMIN)) | 118 | if (!capable (CAP_SYS_ADMIN)) |
115 | return -EACCES; | 119 | return -EACCES; |
116 | 120 | ||
117 | DEV_MESSAGE(KERN_DEBUG, base, "%s", "resume IO on device"); | 121 | dev_info(&base->cdev->dev, "I/O operations have been resumed " |
122 | "on the DASD\n"); | ||
118 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); | 123 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); |
119 | base->stopped &= ~DASD_STOPPED_QUIESCE; | 124 | base->stopped &= ~DASD_STOPPED_QUIESCE; |
120 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); | 125 | 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) | |||
140 | return -EPERM; | 145 | return -EPERM; |
141 | 146 | ||
142 | if (base->state != DASD_STATE_BASIC) { | 147 | if (base->state != DASD_STATE_BASIC) { |
143 | DEV_MESSAGE(KERN_WARNING, base, "%s", | 148 | dev_warn(&base->cdev->dev, |
144 | "dasd_format: device is not disabled! "); | 149 | "The DASD cannot be formatted while it is enabled\n"); |
145 | return -EBUSY; | 150 | return -EBUSY; |
146 | } | 151 | } |
147 | 152 | ||
148 | DBF_DEV_EVENT(DBF_NOTICE, base, | 153 | DBF_DEV_EVENT(DBF_NOTICE, base, |
149 | "formatting units %d to %d (%d B blocks) flags %d", | 154 | "formatting units %u to %u (%u B blocks) flags %u", |
150 | fdata->start_unit, | 155 | fdata->start_unit, |
151 | fdata->stop_unit, fdata->blksize, fdata->intensity); | 156 | fdata->stop_unit, fdata->blksize, fdata->intensity); |
152 | 157 | ||
@@ -169,10 +174,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) | |||
169 | dasd_sfree_request(cqr, cqr->memdev); | 174 | dasd_sfree_request(cqr, cqr->memdev); |
170 | if (rc) { | 175 | if (rc) { |
171 | if (rc != -ERESTARTSYS) | 176 | if (rc != -ERESTARTSYS) |
172 | DEV_MESSAGE(KERN_ERR, base, | 177 | dev_err(&base->cdev->dev, |
173 | " Formatting of unit %d failed " | 178 | "Formatting unit %d failed with " |
174 | "with rc = %d", | 179 | "rc=%d\n", fdata->start_unit, rc); |
175 | fdata->start_unit, rc); | ||
176 | return rc; | 180 | return rc; |
177 | } | 181 | } |
178 | fdata->start_unit++; | 182 | fdata->start_unit++; |
@@ -199,8 +203,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) | |||
199 | if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) | 203 | if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) |
200 | return -EFAULT; | 204 | return -EFAULT; |
201 | if (bdev != bdev->bd_contains) { | 205 | if (bdev != bdev->bd_contains) { |
202 | DEV_MESSAGE(KERN_WARNING, block->base, "%s", | 206 | dev_warn(&block->base->cdev->dev, |
203 | "Cannot low-level format a partition"); | 207 | "The specified DASD is a partition and cannot be " |
208 | "formatted\n"); | ||
204 | return -EINVAL; | 209 | return -EINVAL; |
205 | } | 210 | } |
206 | return dasd_format(block, &fdata); | 211 | return dasd_format(block, &fdata); |
@@ -365,9 +370,9 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, | |||
365 | return ret; | 370 | return ret; |
366 | } | 371 | } |
367 | 372 | ||
368 | int | 373 | static int |
369 | dasd_ioctl(struct block_device *bdev, fmode_t mode, | 374 | dasd_do_ioctl(struct block_device *bdev, fmode_t mode, |
370 | unsigned int cmd, unsigned long arg) | 375 | unsigned int cmd, unsigned long arg) |
371 | { | 376 | { |
372 | struct dasd_block *block = bdev->bd_disk->private_data; | 377 | struct dasd_block *block = bdev->bd_disk->private_data; |
373 | void __user *argp = (void __user *)arg; | 378 | void __user *argp = (void __user *)arg; |
@@ -420,3 +425,14 @@ dasd_ioctl(struct block_device *bdev, fmode_t mode, | |||
420 | return -EINVAL; | 425 | return -EINVAL; |
421 | } | 426 | } |
422 | } | 427 | } |
428 | |||
429 | int dasd_ioctl(struct block_device *bdev, fmode_t mode, | ||
430 | unsigned int cmd, unsigned long arg) | ||
431 | { | ||
432 | int rc; | ||
433 | |||
434 | lock_kernel(); | ||
435 | rc = dasd_do_ioctl(bdev, mode, cmd, arg); | ||
436 | unlock_kernel(); | ||
437 | return rc; | ||
438 | } | ||
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index bf6fd348f20e..2080ba6a69b0 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "dasd" | ||
15 | |||
14 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
15 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
16 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
@@ -112,7 +114,7 @@ dasd_devices_show(struct seq_file *m, void *v) | |||
112 | seq_printf(m, "n/f "); | 114 | seq_printf(m, "n/f "); |
113 | else | 115 | else |
114 | seq_printf(m, | 116 | seq_printf(m, |
115 | "at blocksize: %d, %ld blocks, %ld MB", | 117 | "at blocksize: %d, %lld blocks, %lld MB", |
116 | block->bp_block, block->blocks, | 118 | block->bp_block, block->blocks, |
117 | ((block->bp_block >> 9) * | 119 | ((block->bp_block >> 9) * |
118 | block->blocks) >> 11); | 120 | block->blocks) >> 11); |
@@ -267,7 +269,7 @@ dasd_statistics_write(struct file *file, const char __user *user_buf, | |||
267 | buffer = dasd_get_user_string(user_buf, user_len); | 269 | buffer = dasd_get_user_string(user_buf, user_len); |
268 | if (IS_ERR(buffer)) | 270 | if (IS_ERR(buffer)) |
269 | return PTR_ERR(buffer); | 271 | return PTR_ERR(buffer); |
270 | MESSAGE_LOG(KERN_INFO, "/proc/dasd/statictics: '%s'", buffer); | 272 | DBF_EVENT(DBF_DEBUG, "/proc/dasd/statictics: '%s'\n", buffer); |
271 | 273 | ||
272 | /* check for valid verbs */ | 274 | /* check for valid verbs */ |
273 | for (str = buffer; isspace(*str); str++); | 275 | for (str = buffer; isspace(*str); str++); |
@@ -277,33 +279,33 @@ dasd_statistics_write(struct file *file, const char __user *user_buf, | |||
277 | if (strcmp(str, "on") == 0) { | 279 | if (strcmp(str, "on") == 0) { |
278 | /* switch on statistics profiling */ | 280 | /* switch on statistics profiling */ |
279 | dasd_profile_level = DASD_PROFILE_ON; | 281 | dasd_profile_level = DASD_PROFILE_ON; |
280 | MESSAGE(KERN_INFO, "%s", "Statistics switched on"); | 282 | pr_info("The statistics feature has been switched " |
283 | "on\n"); | ||
281 | } else if (strcmp(str, "off") == 0) { | 284 | } else if (strcmp(str, "off") == 0) { |
282 | /* switch off and reset statistics profiling */ | 285 | /* switch off and reset statistics profiling */ |
283 | memset(&dasd_global_profile, | 286 | memset(&dasd_global_profile, |
284 | 0, sizeof (struct dasd_profile_info_t)); | 287 | 0, sizeof (struct dasd_profile_info_t)); |
285 | dasd_profile_level = DASD_PROFILE_OFF; | 288 | dasd_profile_level = DASD_PROFILE_OFF; |
286 | MESSAGE(KERN_INFO, "%s", "Statistics switched off"); | 289 | pr_info("The statistics feature has been switched " |
290 | "off\n"); | ||
287 | } else | 291 | } else |
288 | goto out_error; | 292 | goto out_error; |
289 | } else if (strncmp(str, "reset", 5) == 0) { | 293 | } else if (strncmp(str, "reset", 5) == 0) { |
290 | /* reset the statistics */ | 294 | /* reset the statistics */ |
291 | memset(&dasd_global_profile, 0, | 295 | memset(&dasd_global_profile, 0, |
292 | sizeof (struct dasd_profile_info_t)); | 296 | sizeof (struct dasd_profile_info_t)); |
293 | MESSAGE(KERN_INFO, "%s", "Statistics reset"); | 297 | pr_info("The statistics have been reset\n"); |
294 | } else | 298 | } else |
295 | goto out_error; | 299 | goto out_error; |
296 | kfree(buffer); | 300 | kfree(buffer); |
297 | return user_len; | 301 | return user_len; |
298 | out_error: | 302 | out_error: |
299 | MESSAGE(KERN_WARNING, "%s", | 303 | pr_warning("%s is not a supported value for /proc/dasd/statistics\n", |
300 | "/proc/dasd/statistics: only 'set on', 'set off' " | 304 | str); |
301 | "and 'reset' are supported verbs"); | ||
302 | kfree(buffer); | 305 | kfree(buffer); |
303 | return -EINVAL; | 306 | return -EINVAL; |
304 | #else | 307 | #else |
305 | MESSAGE(KERN_WARNING, "%s", | 308 | pr_warning("/proc/dasd/statistics: is not activated in this kernel\n"); |
306 | "/proc/dasd/statistics: is not activated in this kernel"); | ||
307 | return user_len; | 309 | return user_len; |
308 | #endif /* CONFIG_DASD_PROFILE */ | 310 | #endif /* CONFIG_DASD_PROFILE */ |
309 | } | 311 | } |
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index d0d565a05dfe..c07809c8016a 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h | |||
@@ -324,8 +324,6 @@ static inline void tape_proc_cleanup (void) {;} | |||
324 | #endif | 324 | #endif |
325 | 325 | ||
326 | /* a function for dumping device sense info */ | 326 | /* a function for dumping device sense info */ |
327 | extern void tape_dump_sense(struct tape_device *, struct tape_request *, | ||
328 | struct irb *); | ||
329 | extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *, | 327 | extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *, |
330 | struct irb *); | 328 | struct irb *); |
331 | 329 | ||
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 22ca34361ed7..807ded5eb049 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "tape" | ||
12 | |||
11 | #include <linux/module.h> | 13 | #include <linux/module.h> |
12 | #include <linux/init.h> | 14 | #include <linux/init.h> |
13 | #include <linux/bio.h> | 15 | #include <linux/bio.h> |
@@ -18,8 +20,6 @@ | |||
18 | #include "tape.h" | 20 | #include "tape.h" |
19 | #include "tape_std.h" | 21 | #include "tape_std.h" |
20 | 22 | ||
21 | #define PRINTK_HEADER "TAPE_34XX: " | ||
22 | |||
23 | /* | 23 | /* |
24 | * Pointer to debug area. | 24 | * Pointer to debug area. |
25 | */ | 25 | */ |
@@ -203,8 +203,7 @@ tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb) | |||
203 | tape_34xx_schedule_work(device, TO_MSEN); | 203 | tape_34xx_schedule_work(device, TO_MSEN); |
204 | } else { | 204 | } else { |
205 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); | 205 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); |
206 | PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); | 206 | tape_dump_sense_dbf(device, NULL, irb); |
207 | tape_dump_sense(device, NULL, irb); | ||
208 | } | 207 | } |
209 | return TAPE_IO_SUCCESS; | 208 | return TAPE_IO_SUCCESS; |
210 | } | 209 | } |
@@ -226,9 +225,7 @@ tape_34xx_erp_read_opposite(struct tape_device *device, | |||
226 | tape_std_read_backward(device, request); | 225 | tape_std_read_backward(device, request); |
227 | return tape_34xx_erp_retry(request); | 226 | return tape_34xx_erp_retry(request); |
228 | } | 227 | } |
229 | if (request->op != TO_RBA) | 228 | |
230 | PRINT_ERR("read_opposite called with state:%s\n", | ||
231 | tape_op_verbose[request->op]); | ||
232 | /* | 229 | /* |
233 | * We tried to read forward and backward, but hat no | 230 | * We tried to read forward and backward, but hat no |
234 | * success -> failed. | 231 | * success -> failed. |
@@ -241,13 +238,9 @@ tape_34xx_erp_bug(struct tape_device *device, struct tape_request *request, | |||
241 | struct irb *irb, int no) | 238 | struct irb *irb, int no) |
242 | { | 239 | { |
243 | if (request->op != TO_ASSIGN) { | 240 | if (request->op != TO_ASSIGN) { |
244 | PRINT_WARN("An unexpected condition #%d was caught in " | 241 | dev_err(&device->cdev->dev, "An unexpected condition %d " |
245 | "tape error recovery.\n", no); | 242 | "occurred in tape error recovery\n", no); |
246 | PRINT_WARN("Please report this incident.\n"); | 243 | tape_dump_sense_dbf(device, request, irb); |
247 | if (request) | ||
248 | PRINT_WARN("Operation of tape:%s\n", | ||
249 | tape_op_verbose[request->op]); | ||
250 | tape_dump_sense(device, request, irb); | ||
251 | } | 244 | } |
252 | return tape_34xx_erp_failed(request, -EIO); | 245 | return tape_34xx_erp_failed(request, -EIO); |
253 | } | 246 | } |
@@ -261,9 +254,8 @@ tape_34xx_erp_overrun(struct tape_device *device, struct tape_request *request, | |||
261 | struct irb *irb) | 254 | struct irb *irb) |
262 | { | 255 | { |
263 | if (irb->ecw[3] == 0x40) { | 256 | if (irb->ecw[3] == 0x40) { |
264 | PRINT_WARN ("Data overrun error between control-unit " | 257 | dev_warn (&device->cdev->dev, "A data overrun occurred between" |
265 | "and drive. Use a faster channel connection, " | 258 | " the control unit and tape unit\n"); |
266 | "if possible! \n"); | ||
267 | return tape_34xx_erp_failed(request, -EIO); | 259 | return tape_34xx_erp_failed(request, -EIO); |
268 | } | 260 | } |
269 | return tape_34xx_erp_bug(device, request, irb, -1); | 261 | return tape_34xx_erp_bug(device, request, irb, -1); |
@@ -280,7 +272,8 @@ tape_34xx_erp_sequence(struct tape_device *device, | |||
280 | /* | 272 | /* |
281 | * cu detected incorrect block-id sequence on tape. | 273 | * cu detected incorrect block-id sequence on tape. |
282 | */ | 274 | */ |
283 | PRINT_WARN("Illegal block-id sequence found!\n"); | 275 | dev_warn (&device->cdev->dev, "The block ID sequence on the " |
276 | "tape is incorrect\n"); | ||
284 | return tape_34xx_erp_failed(request, -EIO); | 277 | return tape_34xx_erp_failed(request, -EIO); |
285 | } | 278 | } |
286 | /* | 279 | /* |
@@ -393,8 +386,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
393 | /* Writing at physical end of volume */ | 386 | /* Writing at physical end of volume */ |
394 | return tape_34xx_erp_failed(request, -ENOSPC); | 387 | return tape_34xx_erp_failed(request, -ENOSPC); |
395 | default: | 388 | default: |
396 | PRINT_ERR("Invalid op in %s:%i\n", | ||
397 | __func__, __LINE__); | ||
398 | return tape_34xx_erp_failed(request, 0); | 389 | return tape_34xx_erp_failed(request, 0); |
399 | } | 390 | } |
400 | } | 391 | } |
@@ -420,7 +411,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
420 | irb, -4); | 411 | irb, -4); |
421 | 412 | ||
422 | /* data check is permanent, CU recovery has failed */ | 413 | /* data check is permanent, CU recovery has failed */ |
423 | PRINT_WARN("Permanent read error\n"); | 414 | dev_warn (&device->cdev->dev, "A read error occurred " |
415 | "that cannot be recovered\n"); | ||
424 | return tape_34xx_erp_failed(request, -EIO); | 416 | return tape_34xx_erp_failed(request, -EIO); |
425 | case 0x25: | 417 | case 0x25: |
426 | // a write data check occurred | 418 | // a write data check occurred |
@@ -433,22 +425,26 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
433 | irb, -5); | 425 | irb, -5); |
434 | 426 | ||
435 | // data check is permanent, cu-recovery has failed | 427 | // data check is permanent, cu-recovery has failed |
436 | PRINT_WARN("Permanent write error\n"); | 428 | dev_warn (&device->cdev->dev, "A write error on the " |
429 | "tape cannot be recovered\n"); | ||
437 | return tape_34xx_erp_failed(request, -EIO); | 430 | return tape_34xx_erp_failed(request, -EIO); |
438 | case 0x26: | 431 | case 0x26: |
439 | /* Data Check (read opposite) occurred. */ | 432 | /* Data Check (read opposite) occurred. */ |
440 | return tape_34xx_erp_read_opposite(device, request); | 433 | return tape_34xx_erp_read_opposite(device, request); |
441 | case 0x28: | 434 | case 0x28: |
442 | /* ID-Mark at tape start couldn't be written */ | 435 | /* ID-Mark at tape start couldn't be written */ |
443 | PRINT_WARN("ID-Mark could not be written.\n"); | 436 | dev_warn (&device->cdev->dev, "Writing the ID-mark " |
437 | "failed\n"); | ||
444 | return tape_34xx_erp_failed(request, -EIO); | 438 | return tape_34xx_erp_failed(request, -EIO); |
445 | case 0x31: | 439 | case 0x31: |
446 | /* Tape void. Tried to read beyond end of device. */ | 440 | /* Tape void. Tried to read beyond end of device. */ |
447 | PRINT_WARN("Read beyond end of recorded area.\n"); | 441 | dev_warn (&device->cdev->dev, "Reading the tape beyond" |
442 | " the end of the recorded area failed\n"); | ||
448 | return tape_34xx_erp_failed(request, -ENOSPC); | 443 | return tape_34xx_erp_failed(request, -ENOSPC); |
449 | case 0x41: | 444 | case 0x41: |
450 | /* Record sequence error. */ | 445 | /* Record sequence error. */ |
451 | PRINT_WARN("Invalid block-id sequence found.\n"); | 446 | dev_warn (&device->cdev->dev, "The tape contains an " |
447 | "incorrect block ID sequence\n"); | ||
452 | return tape_34xx_erp_failed(request, -EIO); | 448 | return tape_34xx_erp_failed(request, -EIO); |
453 | default: | 449 | default: |
454 | /* all data checks for 3480 should result in one of | 450 | /* 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, | |||
470 | switch (sense[3]) { | 466 | switch (sense[3]) { |
471 | case 0x00: | 467 | case 0x00: |
472 | /* Unit check with erpa code 0. Report and ignore. */ | 468 | /* Unit check with erpa code 0. Report and ignore. */ |
473 | PRINT_WARN("Non-error sense was found. " | ||
474 | "Unit-check will be ignored.\n"); | ||
475 | return TAPE_IO_SUCCESS; | 469 | return TAPE_IO_SUCCESS; |
476 | case 0x21: | 470 | case 0x21: |
477 | /* | 471 | /* |
478 | * Data streaming not operational. CU will switch to | 472 | * Data streaming not operational. CU will switch to |
479 | * interlock mode. Reissue the command. | 473 | * interlock mode. Reissue the command. |
480 | */ | 474 | */ |
481 | PRINT_WARN("Data streaming not operational. " | ||
482 | "Switching to interlock-mode.\n"); | ||
483 | return tape_34xx_erp_retry(request); | 475 | return tape_34xx_erp_retry(request); |
484 | case 0x22: | 476 | case 0x22: |
485 | /* | 477 | /* |
@@ -487,11 +479,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
487 | * error on the lower interface, internal path not usable, | 479 | * error on the lower interface, internal path not usable, |
488 | * or error during cartridge load. | 480 | * or error during cartridge load. |
489 | */ | 481 | */ |
490 | PRINT_WARN("A path equipment check occurred. One of the " | 482 | dev_warn (&device->cdev->dev, "A path equipment check occurred" |
491 | "following conditions occurred:\n"); | 483 | " for the tape device\n"); |
492 | PRINT_WARN("drive adapter error, buffer error on the lower " | ||
493 | "interface, internal path not usable, error " | ||
494 | "during cartridge load.\n"); | ||
495 | return tape_34xx_erp_failed(request, -EIO); | 484 | return tape_34xx_erp_failed(request, -EIO); |
496 | case 0x24: | 485 | case 0x24: |
497 | /* | 486 | /* |
@@ -514,7 +503,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
514 | * but the hardware isn't capable to do idrc, or a perform | 503 | * but the hardware isn't capable to do idrc, or a perform |
515 | * subsystem func is issued and the CU is not on-line. | 504 | * subsystem func is issued and the CU is not on-line. |
516 | */ | 505 | */ |
517 | PRINT_WARN ("Function incompatible. Try to switch off idrc\n"); | ||
518 | return tape_34xx_erp_failed(request, -EIO); | 506 | return tape_34xx_erp_failed(request, -EIO); |
519 | case 0x2a: | 507 | case 0x2a: |
520 | /* | 508 | /* |
@@ -552,23 +540,26 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
552 | * reading the format id mark or that that format specified | 540 | * reading the format id mark or that that format specified |
553 | * is not supported by the drive. | 541 | * is not supported by the drive. |
554 | */ | 542 | */ |
555 | PRINT_WARN("Drive not capable processing the tape format!\n"); | 543 | dev_warn (&device->cdev->dev, "The tape unit cannot process " |
544 | "the tape format\n"); | ||
556 | return tape_34xx_erp_failed(request, -EMEDIUMTYPE); | 545 | return tape_34xx_erp_failed(request, -EMEDIUMTYPE); |
557 | case 0x30: | 546 | case 0x30: |
558 | /* The medium is write protected. */ | 547 | /* The medium is write protected. */ |
559 | PRINT_WARN("Medium is write protected!\n"); | 548 | dev_warn (&device->cdev->dev, "The tape medium is write-" |
549 | "protected\n"); | ||
560 | return tape_34xx_erp_failed(request, -EACCES); | 550 | return tape_34xx_erp_failed(request, -EACCES); |
561 | case 0x32: | 551 | case 0x32: |
562 | // Tension loss. We cannot recover this, it's an I/O error. | 552 | // Tension loss. We cannot recover this, it's an I/O error. |
563 | PRINT_WARN("The drive lost tape tension.\n"); | 553 | dev_warn (&device->cdev->dev, "The tape does not have the " |
554 | "required tape tension\n"); | ||
564 | return tape_34xx_erp_failed(request, -EIO); | 555 | return tape_34xx_erp_failed(request, -EIO); |
565 | case 0x33: | 556 | case 0x33: |
566 | /* | 557 | /* |
567 | * Load Failure. The cartridge was not inserted correctly or | 558 | * Load Failure. The cartridge was not inserted correctly or |
568 | * the tape is not threaded correctly. | 559 | * the tape is not threaded correctly. |
569 | */ | 560 | */ |
570 | PRINT_WARN("Cartridge load failure. Reload the cartridge " | 561 | dev_warn (&device->cdev->dev, "The tape unit failed to load" |
571 | "and try again.\n"); | 562 | " the cartridge\n"); |
572 | tape_34xx_delete_sbid_from(device, 0); | 563 | tape_34xx_delete_sbid_from(device, 0); |
573 | return tape_34xx_erp_failed(request, -EIO); | 564 | return tape_34xx_erp_failed(request, -EIO); |
574 | case 0x34: | 565 | case 0x34: |
@@ -576,8 +567,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
576 | * Unload failure. The drive cannot maintain tape tension | 567 | * Unload failure. The drive cannot maintain tape tension |
577 | * and control tape movement during an unload operation. | 568 | * and control tape movement during an unload operation. |
578 | */ | 569 | */ |
579 | PRINT_WARN("Failure during cartridge unload. " | 570 | dev_warn (&device->cdev->dev, "Automatic unloading of the tape" |
580 | "Please try manually.\n"); | 571 | " cartridge failed\n"); |
581 | if (request->op == TO_RUN) | 572 | if (request->op == TO_RUN) |
582 | return tape_34xx_erp_failed(request, -EIO); | 573 | return tape_34xx_erp_failed(request, -EIO); |
583 | return tape_34xx_erp_bug(device, request, irb, sense[3]); | 574 | 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, | |||
589 | * - the cartridge loader does not respond correctly | 580 | * - the cartridge loader does not respond correctly |
590 | * - a failure occurs during an index, load, or unload cycle | 581 | * - a failure occurs during an index, load, or unload cycle |
591 | */ | 582 | */ |
592 | PRINT_WARN("Equipment check! Please check the drive and " | 583 | dev_warn (&device->cdev->dev, "An equipment check has occurred" |
593 | "the cartridge loader.\n"); | 584 | " on the tape unit\n"); |
594 | return tape_34xx_erp_failed(request, -EIO); | 585 | return tape_34xx_erp_failed(request, -EIO); |
595 | case 0x36: | 586 | case 0x36: |
596 | if (device->cdev->id.driver_info == tape_3490) | 587 | if (device->cdev->id.driver_info == tape_3490) |
@@ -603,7 +594,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
603 | * Tape length error. The tape is shorter than reported in | 594 | * Tape length error. The tape is shorter than reported in |
604 | * the beginning-of-tape data. | 595 | * the beginning-of-tape data. |
605 | */ | 596 | */ |
606 | PRINT_WARN("Tape length error.\n"); | 597 | dev_warn (&device->cdev->dev, "The tape information states an" |
598 | " incorrect length\n"); | ||
607 | return tape_34xx_erp_failed(request, -EIO); | 599 | return tape_34xx_erp_failed(request, -EIO); |
608 | case 0x38: | 600 | case 0x38: |
609 | /* | 601 | /* |
@@ -620,12 +612,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
620 | return tape_34xx_erp_failed(request, -EIO); | 612 | return tape_34xx_erp_failed(request, -EIO); |
621 | case 0x3a: | 613 | case 0x3a: |
622 | /* Drive switched to not ready. */ | 614 | /* Drive switched to not ready. */ |
623 | PRINT_WARN("Drive not ready. Turn the ready/not ready switch " | 615 | dev_warn (&device->cdev->dev, "The tape unit is not ready\n"); |
624 | "to ready position and try again.\n"); | ||
625 | return tape_34xx_erp_failed(request, -EIO); | 616 | return tape_34xx_erp_failed(request, -EIO); |
626 | case 0x3b: | 617 | case 0x3b: |
627 | /* Manual rewind or unload. This causes an I/O error. */ | 618 | /* Manual rewind or unload. This causes an I/O error. */ |
628 | PRINT_WARN("Medium was rewound or unloaded manually.\n"); | 619 | dev_warn (&device->cdev->dev, "The tape medium has been " |
620 | "rewound or unloaded manually\n"); | ||
629 | tape_34xx_delete_sbid_from(device, 0); | 621 | tape_34xx_delete_sbid_from(device, 0); |
630 | return tape_34xx_erp_failed(request, -EIO); | 622 | return tape_34xx_erp_failed(request, -EIO); |
631 | case 0x42: | 623 | case 0x42: |
@@ -633,7 +625,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
633 | * Degraded mode. A condition that can cause degraded | 625 | * Degraded mode. A condition that can cause degraded |
634 | * performance is detected. | 626 | * performance is detected. |
635 | */ | 627 | */ |
636 | PRINT_WARN("Subsystem is running in degraded mode.\n"); | 628 | dev_warn (&device->cdev->dev, "The tape subsystem is running " |
629 | "in degraded mode\n"); | ||
637 | return tape_34xx_erp_retry(request); | 630 | return tape_34xx_erp_retry(request); |
638 | case 0x43: | 631 | case 0x43: |
639 | /* Drive not ready. */ | 632 | /* Drive not ready. */ |
@@ -652,7 +645,6 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
652 | break; | 645 | break; |
653 | } | 646 | } |
654 | } | 647 | } |
655 | PRINT_WARN("The drive is not ready.\n"); | ||
656 | return tape_34xx_erp_failed(request, -ENOMEDIUM); | 648 | return tape_34xx_erp_failed(request, -ENOMEDIUM); |
657 | case 0x44: | 649 | case 0x44: |
658 | /* Locate Block unsuccessful. */ | 650 | /* Locate Block unsuccessful. */ |
@@ -663,7 +655,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
663 | return tape_34xx_erp_failed(request, -EIO); | 655 | return tape_34xx_erp_failed(request, -EIO); |
664 | case 0x45: | 656 | case 0x45: |
665 | /* The drive is assigned to a different channel path. */ | 657 | /* The drive is assigned to a different channel path. */ |
666 | PRINT_WARN("The drive is assigned elsewhere.\n"); | 658 | dev_warn (&device->cdev->dev, "The tape unit is already " |
659 | "assigned\n"); | ||
667 | return tape_34xx_erp_failed(request, -EIO); | 660 | return tape_34xx_erp_failed(request, -EIO); |
668 | case 0x46: | 661 | case 0x46: |
669 | /* | 662 | /* |
@@ -671,11 +664,12 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
671 | * the power supply may be switched off or | 664 | * the power supply may be switched off or |
672 | * the drive address may not be set correctly. | 665 | * the drive address may not be set correctly. |
673 | */ | 666 | */ |
674 | PRINT_WARN("The drive is not on-line."); | 667 | dev_warn (&device->cdev->dev, "The tape unit is not online\n"); |
675 | return tape_34xx_erp_failed(request, -EIO); | 668 | return tape_34xx_erp_failed(request, -EIO); |
676 | case 0x47: | 669 | case 0x47: |
677 | /* Volume fenced. CU reports volume integrity is lost. */ | 670 | /* Volume fenced. CU reports volume integrity is lost. */ |
678 | PRINT_WARN("Volume fenced. The volume integrity is lost.\n"); | 671 | dev_warn (&device->cdev->dev, "The control unit has fenced " |
672 | "access to the tape volume\n"); | ||
679 | tape_34xx_delete_sbid_from(device, 0); | 673 | tape_34xx_delete_sbid_from(device, 0); |
680 | return tape_34xx_erp_failed(request, -EIO); | 674 | return tape_34xx_erp_failed(request, -EIO); |
681 | case 0x48: | 675 | case 0x48: |
@@ -683,20 +677,21 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
683 | return tape_34xx_erp_retry(request); | 677 | return tape_34xx_erp_retry(request); |
684 | case 0x49: | 678 | case 0x49: |
685 | /* Bus out check. A parity check error on the bus was found. */ | 679 | /* Bus out check. A parity check error on the bus was found. */ |
686 | PRINT_WARN("Bus out check. A data transfer over the bus " | 680 | dev_warn (&device->cdev->dev, "A parity error occurred on the " |
687 | "has been corrupted.\n"); | 681 | "tape bus\n"); |
688 | return tape_34xx_erp_failed(request, -EIO); | 682 | return tape_34xx_erp_failed(request, -EIO); |
689 | case 0x4a: | 683 | case 0x4a: |
690 | /* Control unit erp failed. */ | 684 | /* Control unit erp failed. */ |
691 | PRINT_WARN("The control unit I/O error recovery failed.\n"); | 685 | dev_warn (&device->cdev->dev, "I/O error recovery failed on " |
686 | "the tape control unit\n"); | ||
692 | return tape_34xx_erp_failed(request, -EIO); | 687 | return tape_34xx_erp_failed(request, -EIO); |
693 | case 0x4b: | 688 | case 0x4b: |
694 | /* | 689 | /* |
695 | * CU and drive incompatible. The drive requests micro-program | 690 | * CU and drive incompatible. The drive requests micro-program |
696 | * patches, which are not available on the CU. | 691 | * patches, which are not available on the CU. |
697 | */ | 692 | */ |
698 | PRINT_WARN("The drive needs microprogram patches from the " | 693 | dev_warn (&device->cdev->dev, "The tape unit requires a " |
699 | "control unit, which are not available.\n"); | 694 | "firmware update\n"); |
700 | return tape_34xx_erp_failed(request, -EIO); | 695 | return tape_34xx_erp_failed(request, -EIO); |
701 | case 0x4c: | 696 | case 0x4c: |
702 | /* | 697 | /* |
@@ -721,8 +716,8 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
721 | * the block to be written is larger than allowed for | 716 | * the block to be written is larger than allowed for |
722 | * buffered mode. | 717 | * buffered mode. |
723 | */ | 718 | */ |
724 | PRINT_WARN("Maximum block size for buffered " | 719 | dev_warn (&device->cdev->dev, "The maximum block size" |
725 | "mode exceeded.\n"); | 720 | " for buffered mode is exceeded\n"); |
726 | return tape_34xx_erp_failed(request, -ENOBUFS); | 721 | return tape_34xx_erp_failed(request, -ENOBUFS); |
727 | } | 722 | } |
728 | /* This erpa is reserved for 3480. */ | 723 | /* This erpa is reserved for 3480. */ |
@@ -759,22 +754,20 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
759 | return tape_34xx_erp_retry(request); | 754 | return tape_34xx_erp_retry(request); |
760 | case 0x55: | 755 | case 0x55: |
761 | /* Channel interface recovery (permanent). */ | 756 | /* Channel interface recovery (permanent). */ |
762 | PRINT_WARN("A permanent channel interface error occurred.\n"); | 757 | dev_warn (&device->cdev->dev, "A channel interface error cannot be" |
758 | " recovered\n"); | ||
763 | return tape_34xx_erp_failed(request, -EIO); | 759 | return tape_34xx_erp_failed(request, -EIO); |
764 | case 0x56: | 760 | case 0x56: |
765 | /* Channel protocol error. */ | 761 | /* Channel protocol error. */ |
766 | PRINT_WARN("A channel protocol error occurred.\n"); | 762 | dev_warn (&device->cdev->dev, "A channel protocol error " |
763 | "occurred\n"); | ||
767 | return tape_34xx_erp_failed(request, -EIO); | 764 | return tape_34xx_erp_failed(request, -EIO); |
768 | case 0x57: | 765 | case 0x57: |
769 | if (device->cdev->id.driver_info == tape_3480) { | 766 | if (device->cdev->id.driver_info == tape_3480) { |
770 | /* Attention intercept. */ | 767 | /* Attention intercept. */ |
771 | PRINT_WARN("An attention intercept occurred, " | ||
772 | "which will be recovered.\n"); | ||
773 | return tape_34xx_erp_retry(request); | 768 | return tape_34xx_erp_retry(request); |
774 | } else { | 769 | } else { |
775 | /* Global status intercept. */ | 770 | /* Global status intercept. */ |
776 | PRINT_WARN("An global status intercept was received, " | ||
777 | "which will be recovered.\n"); | ||
778 | return tape_34xx_erp_retry(request); | 771 | return tape_34xx_erp_retry(request); |
779 | } | 772 | } |
780 | case 0x5a: | 773 | case 0x5a: |
@@ -782,42 +775,31 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request, | |||
782 | * Tape length incompatible. The tape inserted is too long, | 775 | * Tape length incompatible. The tape inserted is too long, |
783 | * which could cause damage to the tape or the drive. | 776 | * which could cause damage to the tape or the drive. |
784 | */ | 777 | */ |
785 | PRINT_WARN("Tape Length Incompatible\n"); | 778 | dev_warn (&device->cdev->dev, "The tape unit does not support " |
786 | PRINT_WARN("Tape length exceeds IBM enhanced capacity " | 779 | "the tape length\n"); |
787 | "cartdridge length or a medium\n"); | ||
788 | PRINT_WARN("with EC-CST identification mark has been mounted " | ||
789 | "in a device that writes\n"); | ||
790 | PRINT_WARN("3480 or 3480 XF format.\n"); | ||
791 | return tape_34xx_erp_failed(request, -EIO); | 780 | return tape_34xx_erp_failed(request, -EIO); |
792 | case 0x5b: | 781 | case 0x5b: |
793 | /* Format 3480 XF incompatible */ | 782 | /* Format 3480 XF incompatible */ |
794 | if (sense[1] & SENSE_BEGINNING_OF_TAPE) | 783 | if (sense[1] & SENSE_BEGINNING_OF_TAPE) |
795 | /* The tape will get overwritten. */ | 784 | /* The tape will get overwritten. */ |
796 | return tape_34xx_erp_retry(request); | 785 | return tape_34xx_erp_retry(request); |
797 | PRINT_WARN("Format 3480 XF Incompatible\n"); | 786 | dev_warn (&device->cdev->dev, "The tape unit does not support" |
798 | PRINT_WARN("Medium has been created in 3480 format. " | 787 | " format 3480 XF\n"); |
799 | "To change the format writes\n"); | ||
800 | PRINT_WARN("must be issued at BOT.\n"); | ||
801 | return tape_34xx_erp_failed(request, -EIO); | 788 | return tape_34xx_erp_failed(request, -EIO); |
802 | case 0x5c: | 789 | case 0x5c: |
803 | /* Format 3480-2 XF incompatible */ | 790 | /* Format 3480-2 XF incompatible */ |
804 | PRINT_WARN("Format 3480-2 XF Incompatible\n"); | 791 | dev_warn (&device->cdev->dev, "The tape unit does not support tape " |
805 | PRINT_WARN("Device can only read 3480 or 3480 XF format.\n"); | 792 | "format 3480-2 XF\n"); |
806 | return tape_34xx_erp_failed(request, -EIO); | 793 | return tape_34xx_erp_failed(request, -EIO); |
807 | case 0x5d: | 794 | case 0x5d: |
808 | /* Tape length violation. */ | 795 | /* Tape length violation. */ |
809 | PRINT_WARN("Tape Length Violation\n"); | 796 | dev_warn (&device->cdev->dev, "The tape unit does not support" |
810 | PRINT_WARN("The mounted tape exceeds IBM Enhanced Capacity " | 797 | " the current tape length\n"); |
811 | "Cartdridge System Tape length.\n"); | ||
812 | PRINT_WARN("This may cause damage to the drive or tape when " | ||
813 | "processing to the EOV\n"); | ||
814 | return tape_34xx_erp_failed(request, -EMEDIUMTYPE); | 798 | return tape_34xx_erp_failed(request, -EMEDIUMTYPE); |
815 | case 0x5e: | 799 | case 0x5e: |
816 | /* Compaction algorithm incompatible. */ | 800 | /* Compaction algorithm incompatible. */ |
817 | PRINT_WARN("Compaction Algorithm Incompatible\n"); | 801 | dev_warn (&device->cdev->dev, "The tape unit does not support" |
818 | PRINT_WARN("The volume is recorded using an incompatible " | 802 | " the compaction algorithm\n"); |
819 | "compaction algorithm,\n"); | ||
820 | PRINT_WARN("which is not supported by the device.\n"); | ||
821 | return tape_34xx_erp_failed(request, -EMEDIUMTYPE); | 803 | return tape_34xx_erp_failed(request, -EMEDIUMTYPE); |
822 | 804 | ||
823 | /* The following erpas should have been covered earlier. */ | 805 | /* The following erpas should have been covered earlier. */ |
@@ -848,7 +830,6 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request, | |||
848 | (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) && | 830 | (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) && |
849 | (request->op == TO_WRI)) { | 831 | (request->op == TO_WRI)) { |
850 | /* Write at end of volume */ | 832 | /* Write at end of volume */ |
851 | PRINT_INFO("End of volume\n"); /* XXX */ | ||
852 | return tape_34xx_erp_failed(request, -ENOSPC); | 833 | return tape_34xx_erp_failed(request, -ENOSPC); |
853 | } | 834 | } |
854 | 835 | ||
@@ -869,9 +850,7 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request, | |||
869 | } | 850 | } |
870 | 851 | ||
871 | DBF_EVENT(6, "xunknownirq\n"); | 852 | DBF_EVENT(6, "xunknownirq\n"); |
872 | PRINT_ERR("Unexpected interrupt.\n"); | 853 | tape_dump_sense_dbf(device, request, irb); |
873 | PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]); | ||
874 | tape_dump_sense(device, request, irb); | ||
875 | return TAPE_IO_STOP; | 854 | return TAPE_IO_STOP; |
876 | } | 855 | } |
877 | 856 | ||
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 71605a179d65..fc1d91294143 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -8,12 +8,15 @@ | |||
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "tape" | ||
12 | |||
11 | #include <linux/module.h> | 13 | #include <linux/module.h> |
12 | #include <linux/init.h> | 14 | #include <linux/init.h> |
13 | #include <linux/bio.h> | 15 | #include <linux/bio.h> |
14 | #include <asm/ebcdic.h> | 16 | #include <asm/ebcdic.h> |
15 | 17 | ||
16 | #define TAPE_DBF_AREA tape_3590_dbf | 18 | #define TAPE_DBF_AREA tape_3590_dbf |
19 | #define BUFSIZE 512 /* size of buffers for dynamic generated messages */ | ||
17 | 20 | ||
18 | #include "tape.h" | 21 | #include "tape.h" |
19 | #include "tape_std.h" | 22 | #include "tape_std.h" |
@@ -36,7 +39,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA); | |||
36 | * - Read Alternate: implemented | 39 | * - Read Alternate: implemented |
37 | *******************************************************************/ | 40 | *******************************************************************/ |
38 | 41 | ||
39 | #define PRINTK_HEADER "TAPE_3590: " | 42 | #define KMSG_COMPONENT "tape" |
40 | 43 | ||
41 | static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { | 44 | static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { |
42 | [0x00] = "", | 45 | [0x00] = "", |
@@ -661,8 +664,7 @@ tape_3590_bread(struct tape_device *device, struct request *req) | |||
661 | ccw++; | 664 | ccw++; |
662 | dst += TAPEBLOCK_HSEC_SIZE; | 665 | dst += TAPEBLOCK_HSEC_SIZE; |
663 | } | 666 | } |
664 | if (off > bv->bv_len) | 667 | BUG_ON(off > bv->bv_len); |
665 | BUG(); | ||
666 | } | 668 | } |
667 | ccw = tape_ccw_end(ccw, NOP, 0, NULL); | 669 | ccw = tape_ccw_end(ccw, NOP, 0, NULL); |
668 | DBF_EVENT(6, "xBREDccwg\n"); | 670 | DBF_EVENT(6, "xBREDccwg\n"); |
@@ -726,7 +728,7 @@ static void tape_3590_med_state_set(struct tape_device *device, | |||
726 | } | 728 | } |
727 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; | 729 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; |
728 | if (sense->flags & MSENSE_CRYPT_MASK) { | 730 | if (sense->flags & MSENSE_CRYPT_MASK) { |
729 | PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); | 731 | DBF_EVENT(6, "Medium is encrypted (%04x)\n", sense->flags); |
730 | c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK; | 732 | c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK; |
731 | } else { | 733 | } else { |
732 | DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags); | 734 | 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) | |||
847 | tape_3590_schedule_work(device, TO_READ_ATTMSG); | 849 | tape_3590_schedule_work(device, TO_READ_ATTMSG); |
848 | } else { | 850 | } else { |
849 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); | 851 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); |
850 | PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); | 852 | tape_dump_sense_dbf(device, NULL, irb); |
851 | tape_dump_sense(device, NULL, irb); | ||
852 | } | 853 | } |
853 | /* check medium state */ | 854 | /* check medium state */ |
854 | tape_3590_schedule_work(device, TO_MSEN); | 855 | tape_3590_schedule_work(device, TO_MSEN); |
@@ -876,8 +877,6 @@ tape_3590_erp_basic(struct tape_device *device, struct tape_request *request, | |||
876 | case SENSE_BRA_DRE: | 877 | case SENSE_BRA_DRE: |
877 | return tape_3590_erp_failed(device, request, irb, rc); | 878 | return tape_3590_erp_failed(device, request, irb, rc); |
878 | default: | 879 | default: |
879 | PRINT_ERR("Unknown BRA %x - This should not happen!\n", | ||
880 | sense->bra); | ||
881 | BUG(); | 880 | BUG(); |
882 | return TAPE_IO_STOP; | 881 | return TAPE_IO_STOP; |
883 | } | 882 | } |
@@ -910,7 +909,8 @@ tape_3590_erp_swap(struct tape_device *device, struct tape_request *request, | |||
910 | * should proceed with the new tape... this | 909 | * should proceed with the new tape... this |
911 | * should probably be done in user space! | 910 | * should probably be done in user space! |
912 | */ | 911 | */ |
913 | PRINT_WARN("(%s): Swap Tape Device!\n", dev_name(&device->cdev->dev)); | 912 | dev_warn (&device->cdev->dev, "The tape medium must be loaded into a " |
913 | "different tape unit\n"); | ||
914 | return tape_3590_erp_basic(device, request, irb, -EIO); | 914 | return tape_3590_erp_basic(device, request, irb, -EIO); |
915 | } | 915 | } |
916 | 916 | ||
@@ -985,8 +985,6 @@ tape_3590_erp_read_opposite(struct tape_device *device, | |||
985 | return tape_3590_erp_failed(device, request, irb, -EIO); | 985 | return tape_3590_erp_failed(device, request, irb, -EIO); |
986 | break; | 986 | break; |
987 | default: | 987 | default: |
988 | PRINT_WARN("read_opposite_recovery_called_with_op: %s\n", | ||
989 | tape_op_verbose[request->op]); | ||
990 | return tape_3590_erp_failed(device, request, irb, -EIO); | 988 | return tape_3590_erp_failed(device, request, irb, -EIO); |
991 | } | 989 | } |
992 | } | 990 | } |
@@ -998,50 +996,61 @@ static void | |||
998 | tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb) | 996 | tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb) |
999 | { | 997 | { |
1000 | struct tape_3590_sense *sense; | 998 | struct tape_3590_sense *sense; |
999 | char *exception, *service; | ||
1000 | |||
1001 | exception = kmalloc(BUFSIZE, GFP_ATOMIC); | ||
1002 | service = kmalloc(BUFSIZE, GFP_ATOMIC); | ||
1003 | |||
1004 | if (!exception || !service) | ||
1005 | goto out_nomem; | ||
1001 | 1006 | ||
1002 | sense = (struct tape_3590_sense *) irb->ecw; | 1007 | sense = (struct tape_3590_sense *) irb->ecw; |
1003 | /* Exception Message */ | 1008 | /* Exception Message */ |
1004 | switch (sense->fmt.f70.emc) { | 1009 | switch (sense->fmt.f70.emc) { |
1005 | case 0x02: | 1010 | case 0x02: |
1006 | PRINT_WARN("(%s): Data degraded\n", | 1011 | snprintf(exception, BUFSIZE, "Data degraded"); |
1007 | dev_name(&device->cdev->dev)); | ||
1008 | break; | 1012 | break; |
1009 | case 0x03: | 1013 | case 0x03: |
1010 | PRINT_WARN("(%s): Data degraded in partion %i\n", | 1014 | snprintf(exception, BUFSIZE, "Data degraded in partion %i", |
1011 | dev_name(&device->cdev->dev), sense->fmt.f70.mp); | 1015 | sense->fmt.f70.mp); |
1012 | break; | 1016 | break; |
1013 | case 0x04: | 1017 | case 0x04: |
1014 | PRINT_WARN("(%s): Medium degraded\n", | 1018 | snprintf(exception, BUFSIZE, "Medium degraded"); |
1015 | dev_name(&device->cdev->dev)); | ||
1016 | break; | 1019 | break; |
1017 | case 0x05: | 1020 | case 0x05: |
1018 | PRINT_WARN("(%s): Medium degraded in partition %i\n", | 1021 | snprintf(exception, BUFSIZE, "Medium degraded in partition %i", |
1019 | dev_name(&device->cdev->dev), sense->fmt.f70.mp); | 1022 | sense->fmt.f70.mp); |
1020 | break; | 1023 | break; |
1021 | case 0x06: | 1024 | case 0x06: |
1022 | PRINT_WARN("(%s): Block 0 Error\n", | 1025 | snprintf(exception, BUFSIZE, "Block 0 Error"); |
1023 | dev_name(&device->cdev->dev)); | ||
1024 | break; | 1026 | break; |
1025 | case 0x07: | 1027 | case 0x07: |
1026 | PRINT_WARN("(%s): Medium Exception 0x%02x\n", | 1028 | snprintf(exception, BUFSIZE, "Medium Exception 0x%02x", |
1027 | dev_name(&device->cdev->dev), sense->fmt.f70.md); | 1029 | sense->fmt.f70.md); |
1028 | break; | 1030 | break; |
1029 | default: | 1031 | default: |
1030 | PRINT_WARN("(%s): MIM ExMsg: 0x%02x\n", | 1032 | snprintf(exception, BUFSIZE, "0x%02x", |
1031 | dev_name(&device->cdev->dev), sense->fmt.f70.emc); | 1033 | sense->fmt.f70.emc); |
1032 | break; | 1034 | break; |
1033 | } | 1035 | } |
1034 | /* Service Message */ | 1036 | /* Service Message */ |
1035 | switch (sense->fmt.f70.smc) { | 1037 | switch (sense->fmt.f70.smc) { |
1036 | case 0x02: | 1038 | case 0x02: |
1037 | PRINT_WARN("(%s): Reference Media maintenance procedure %i\n", | 1039 | snprintf(service, BUFSIZE, "Reference Media maintenance " |
1038 | dev_name(&device->cdev->dev), sense->fmt.f70.md); | 1040 | "procedure %i", sense->fmt.f70.md); |
1039 | break; | 1041 | break; |
1040 | default: | 1042 | default: |
1041 | PRINT_WARN("(%s): MIM ServiceMsg: 0x%02x\n", | 1043 | snprintf(service, BUFSIZE, "0x%02x", |
1042 | dev_name(&device->cdev->dev), sense->fmt.f70.smc); | 1044 | sense->fmt.f70.smc); |
1043 | break; | 1045 | break; |
1044 | } | 1046 | } |
1047 | |||
1048 | dev_warn (&device->cdev->dev, "Tape media information: exception %s, " | ||
1049 | "service %s\n", exception, service); | ||
1050 | |||
1051 | out_nomem: | ||
1052 | kfree(exception); | ||
1053 | kfree(service); | ||
1045 | } | 1054 | } |
1046 | 1055 | ||
1047 | /* | 1056 | /* |
@@ -1051,108 +1060,108 @@ static void | |||
1051 | tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb) | 1060 | tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb) |
1052 | { | 1061 | { |
1053 | struct tape_3590_sense *sense; | 1062 | struct tape_3590_sense *sense; |
1063 | char *exception, *service; | ||
1064 | |||
1065 | exception = kmalloc(BUFSIZE, GFP_ATOMIC); | ||
1066 | service = kmalloc(BUFSIZE, GFP_ATOMIC); | ||
1067 | |||
1068 | if (!exception || !service) | ||
1069 | goto out_nomem; | ||
1054 | 1070 | ||
1055 | sense = (struct tape_3590_sense *) irb->ecw; | 1071 | sense = (struct tape_3590_sense *) irb->ecw; |
1056 | /* Exception Message */ | 1072 | /* Exception Message */ |
1057 | switch (sense->fmt.f71.emc) { | 1073 | switch (sense->fmt.f71.emc) { |
1058 | case 0x01: | 1074 | case 0x01: |
1059 | PRINT_WARN("(%s): Effect of failure is unknown\n", | 1075 | snprintf(exception, BUFSIZE, "Effect of failure is unknown"); |
1060 | dev_name(&device->cdev->dev)); | ||
1061 | break; | 1076 | break; |
1062 | case 0x02: | 1077 | case 0x02: |
1063 | PRINT_WARN("(%s): CU Exception - no performance impact\n", | 1078 | snprintf(exception, BUFSIZE, "CU Exception - no performance " |
1064 | dev_name(&device->cdev->dev)); | 1079 | "impact"); |
1065 | break; | 1080 | break; |
1066 | case 0x03: | 1081 | case 0x03: |
1067 | PRINT_WARN("(%s): CU Exception on channel interface 0x%02x\n", | 1082 | snprintf(exception, BUFSIZE, "CU Exception on channel " |
1068 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1083 | "interface 0x%02x", sense->fmt.f71.md[0]); |
1069 | break; | 1084 | break; |
1070 | case 0x04: | 1085 | case 0x04: |
1071 | PRINT_WARN("(%s): CU Exception on device path 0x%02x\n", | 1086 | snprintf(exception, BUFSIZE, "CU Exception on device path " |
1072 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1087 | "0x%02x", sense->fmt.f71.md[0]); |
1073 | break; | 1088 | break; |
1074 | case 0x05: | 1089 | case 0x05: |
1075 | PRINT_WARN("(%s): CU Exception on library path 0x%02x\n", | 1090 | snprintf(exception, BUFSIZE, "CU Exception on library path " |
1076 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1091 | "0x%02x", sense->fmt.f71.md[0]); |
1077 | break; | 1092 | break; |
1078 | case 0x06: | 1093 | case 0x06: |
1079 | PRINT_WARN("(%s): CU Exception on node 0x%02x\n", | 1094 | snprintf(exception, BUFSIZE, "CU Exception on node 0x%02x", |
1080 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1095 | sense->fmt.f71.md[0]); |
1081 | break; | 1096 | break; |
1082 | case 0x07: | 1097 | case 0x07: |
1083 | PRINT_WARN("(%s): CU Exception on partition 0x%02x\n", | 1098 | snprintf(exception, BUFSIZE, "CU Exception on partition " |
1084 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1099 | "0x%02x", sense->fmt.f71.md[0]); |
1085 | break; | 1100 | break; |
1086 | default: | 1101 | default: |
1087 | PRINT_WARN("(%s): SIM ExMsg: 0x%02x\n", | 1102 | snprintf(exception, BUFSIZE, "0x%02x", |
1088 | dev_name(&device->cdev->dev), sense->fmt.f71.emc); | 1103 | sense->fmt.f71.emc); |
1089 | } | 1104 | } |
1090 | /* Service Message */ | 1105 | /* Service Message */ |
1091 | switch (sense->fmt.f71.smc) { | 1106 | switch (sense->fmt.f71.smc) { |
1092 | case 0x01: | 1107 | case 0x01: |
1093 | PRINT_WARN("(%s): Repair impact is unknown\n", | 1108 | snprintf(service, BUFSIZE, "Repair impact is unknown"); |
1094 | dev_name(&device->cdev->dev)); | ||
1095 | break; | 1109 | break; |
1096 | case 0x02: | 1110 | case 0x02: |
1097 | PRINT_WARN("(%s): Repair will not impact cu performance\n", | 1111 | snprintf(service, BUFSIZE, "Repair will not impact cu " |
1098 | dev_name(&device->cdev->dev)); | 1112 | "performance"); |
1099 | break; | 1113 | break; |
1100 | case 0x03: | 1114 | case 0x03: |
1101 | if (sense->fmt.f71.mdf == 0) | 1115 | if (sense->fmt.f71.mdf == 0) |
1102 | PRINT_WARN("(%s): Repair will disable node " | 1116 | snprintf(service, BUFSIZE, "Repair will disable node " |
1103 | "0x%x on CU\n", | 1117 | "0x%x on CU", sense->fmt.f71.md[1]); |
1104 | dev_name(&device->cdev->dev), | ||
1105 | sense->fmt.f71.md[1]); | ||
1106 | else | 1118 | else |
1107 | PRINT_WARN("(%s): Repair will disable nodes " | 1119 | snprintf(service, BUFSIZE, "Repair will disable " |
1108 | "(0x%x-0x%x) on CU\n", | 1120 | "nodes (0x%x-0x%x) on CU", sense->fmt.f71.md[1], |
1109 | dev_name(&device->cdev->dev), | 1121 | sense->fmt.f71.md[2]); |
1110 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1111 | break; | 1122 | break; |
1112 | case 0x04: | 1123 | case 0x04: |
1113 | if (sense->fmt.f71.mdf == 0) | 1124 | if (sense->fmt.f71.mdf == 0) |
1114 | PRINT_WARN("(%s): Repair will disable cannel path " | 1125 | snprintf(service, BUFSIZE, "Repair will disable " |
1115 | "0x%x on CU\n", | 1126 | "channel path 0x%x on CU", |
1116 | dev_name(&device->cdev->dev), | 1127 | sense->fmt.f71.md[1]); |
1117 | sense->fmt.f71.md[1]); | ||
1118 | else | 1128 | else |
1119 | PRINT_WARN("(%s): Repair will disable cannel paths " | 1129 | snprintf(service, BUFSIZE, "Repair will disable cannel" |
1120 | "(0x%x-0x%x) on CU\n", | 1130 | " paths (0x%x-0x%x) on CU", |
1121 | dev_name(&device->cdev->dev), | 1131 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1122 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1123 | break; | 1132 | break; |
1124 | case 0x05: | 1133 | case 0x05: |
1125 | if (sense->fmt.f71.mdf == 0) | 1134 | if (sense->fmt.f71.mdf == 0) |
1126 | PRINT_WARN("(%s): Repair will disable device path " | 1135 | snprintf(service, BUFSIZE, "Repair will disable device" |
1127 | "0x%x on CU\n", | 1136 | " path 0x%x on CU", sense->fmt.f71.md[1]); |
1128 | dev_name(&device->cdev->dev), | ||
1129 | sense->fmt.f71.md[1]); | ||
1130 | else | 1137 | else |
1131 | PRINT_WARN("(%s): Repair will disable device paths " | 1138 | snprintf(service, BUFSIZE, "Repair will disable device" |
1132 | "(0x%x-0x%x) on CU\n", | 1139 | " paths (0x%x-0x%x) on CU", |
1133 | dev_name(&device->cdev->dev), | 1140 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1134 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1135 | break; | 1141 | break; |
1136 | case 0x06: | 1142 | case 0x06: |
1137 | if (sense->fmt.f71.mdf == 0) | 1143 | if (sense->fmt.f71.mdf == 0) |
1138 | PRINT_WARN("(%s): Repair will disable library path " | 1144 | snprintf(service, BUFSIZE, "Repair will disable " |
1139 | "0x%x on CU\n", | 1145 | "library path 0x%x on CU", |
1140 | dev_name(&device->cdev->dev), | 1146 | sense->fmt.f71.md[1]); |
1141 | sense->fmt.f71.md[1]); | ||
1142 | else | 1147 | else |
1143 | PRINT_WARN("(%s): Repair will disable library paths " | 1148 | snprintf(service, BUFSIZE, "Repair will disable " |
1144 | "(0x%x-0x%x) on CU\n", | 1149 | "library paths (0x%x-0x%x) on CU", |
1145 | dev_name(&device->cdev->dev), | 1150 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1146 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1147 | break; | 1151 | break; |
1148 | case 0x07: | 1152 | case 0x07: |
1149 | PRINT_WARN("(%s): Repair will disable access to CU\n", | 1153 | snprintf(service, BUFSIZE, "Repair will disable access to CU"); |
1150 | dev_name(&device->cdev->dev)); | ||
1151 | break; | 1154 | break; |
1152 | default: | 1155 | default: |
1153 | PRINT_WARN("(%s): SIM ServiceMsg: 0x%02x\n", | 1156 | snprintf(service, BUFSIZE, "0x%02x", |
1154 | dev_name(&device->cdev->dev), sense->fmt.f71.smc); | 1157 | sense->fmt.f71.smc); |
1155 | } | 1158 | } |
1159 | |||
1160 | dev_warn (&device->cdev->dev, "I/O subsystem information: exception" | ||
1161 | " %s, service %s\n", exception, service); | ||
1162 | out_nomem: | ||
1163 | kfree(exception); | ||
1164 | kfree(service); | ||
1156 | } | 1165 | } |
1157 | 1166 | ||
1158 | /* | 1167 | /* |
@@ -1162,111 +1171,109 @@ static void | |||
1162 | tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb) | 1171 | tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb) |
1163 | { | 1172 | { |
1164 | struct tape_3590_sense *sense; | 1173 | struct tape_3590_sense *sense; |
1174 | char *exception, *service; | ||
1175 | |||
1176 | exception = kmalloc(BUFSIZE, GFP_ATOMIC); | ||
1177 | service = kmalloc(BUFSIZE, GFP_ATOMIC); | ||
1178 | |||
1179 | if (!exception || !service) | ||
1180 | goto out_nomem; | ||
1165 | 1181 | ||
1166 | sense = (struct tape_3590_sense *) irb->ecw; | 1182 | sense = (struct tape_3590_sense *) irb->ecw; |
1167 | /* Exception Message */ | 1183 | /* Exception Message */ |
1168 | switch (sense->fmt.f71.emc) { | 1184 | switch (sense->fmt.f71.emc) { |
1169 | case 0x01: | 1185 | case 0x01: |
1170 | PRINT_WARN("(%s): Effect of failure is unknown\n", | 1186 | snprintf(exception, BUFSIZE, "Effect of failure is unknown"); |
1171 | dev_name(&device->cdev->dev)); | ||
1172 | break; | 1187 | break; |
1173 | case 0x02: | 1188 | case 0x02: |
1174 | PRINT_WARN("(%s): DV Exception - no performance impact\n", | 1189 | snprintf(exception, BUFSIZE, "DV Exception - no performance" |
1175 | dev_name(&device->cdev->dev)); | 1190 | " impact"); |
1176 | break; | 1191 | break; |
1177 | case 0x03: | 1192 | case 0x03: |
1178 | PRINT_WARN("(%s): DV Exception on channel interface 0x%02x\n", | 1193 | snprintf(exception, BUFSIZE, "DV Exception on channel " |
1179 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1194 | "interface 0x%02x", sense->fmt.f71.md[0]); |
1180 | break; | 1195 | break; |
1181 | case 0x04: | 1196 | case 0x04: |
1182 | PRINT_WARN("(%s): DV Exception on loader 0x%02x\n", | 1197 | snprintf(exception, BUFSIZE, "DV Exception on loader 0x%02x", |
1183 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1198 | sense->fmt.f71.md[0]); |
1184 | break; | 1199 | break; |
1185 | case 0x05: | 1200 | case 0x05: |
1186 | PRINT_WARN("(%s): DV Exception on message display 0x%02x\n", | 1201 | snprintf(exception, BUFSIZE, "DV Exception on message display" |
1187 | dev_name(&device->cdev->dev), sense->fmt.f71.md[0]); | 1202 | " 0x%02x", sense->fmt.f71.md[0]); |
1188 | break; | 1203 | break; |
1189 | case 0x06: | 1204 | case 0x06: |
1190 | PRINT_WARN("(%s): DV Exception in tape path\n", | 1205 | snprintf(exception, BUFSIZE, "DV Exception in tape path"); |
1191 | dev_name(&device->cdev->dev)); | ||
1192 | break; | 1206 | break; |
1193 | case 0x07: | 1207 | case 0x07: |
1194 | PRINT_WARN("(%s): DV Exception in drive\n", | 1208 | snprintf(exception, BUFSIZE, "DV Exception in drive"); |
1195 | dev_name(&device->cdev->dev)); | ||
1196 | break; | 1209 | break; |
1197 | default: | 1210 | default: |
1198 | PRINT_WARN("(%s): DSIM ExMsg: 0x%02x\n", | 1211 | snprintf(exception, BUFSIZE, "0x%02x", |
1199 | dev_name(&device->cdev->dev), sense->fmt.f71.emc); | 1212 | sense->fmt.f71.emc); |
1200 | } | 1213 | } |
1201 | /* Service Message */ | 1214 | /* Service Message */ |
1202 | switch (sense->fmt.f71.smc) { | 1215 | switch (sense->fmt.f71.smc) { |
1203 | case 0x01: | 1216 | case 0x01: |
1204 | PRINT_WARN("(%s): Repair impact is unknown\n", | 1217 | snprintf(service, BUFSIZE, "Repair impact is unknown"); |
1205 | dev_name(&device->cdev->dev)); | ||
1206 | break; | 1218 | break; |
1207 | case 0x02: | 1219 | case 0x02: |
1208 | PRINT_WARN("(%s): Repair will not impact device performance\n", | 1220 | snprintf(service, BUFSIZE, "Repair will not impact device " |
1209 | dev_name(&device->cdev->dev)); | 1221 | "performance"); |
1210 | break; | 1222 | break; |
1211 | case 0x03: | 1223 | case 0x03: |
1212 | if (sense->fmt.f71.mdf == 0) | 1224 | if (sense->fmt.f71.mdf == 0) |
1213 | PRINT_WARN("(%s): Repair will disable channel path " | 1225 | snprintf(service, BUFSIZE, "Repair will disable " |
1214 | "0x%x on DV\n", | 1226 | "channel path 0x%x on DV", |
1215 | dev_name(&device->cdev->dev), | 1227 | sense->fmt.f71.md[1]); |
1216 | sense->fmt.f71.md[1]); | ||
1217 | else | 1228 | else |
1218 | PRINT_WARN("(%s): Repair will disable channel path " | 1229 | snprintf(service, BUFSIZE, "Repair will disable " |
1219 | "(0x%x-0x%x) on DV\n", | 1230 | "channel path (0x%x-0x%x) on DV", |
1220 | dev_name(&device->cdev->dev), | 1231 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1221 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1222 | break; | 1232 | break; |
1223 | case 0x04: | 1233 | case 0x04: |
1224 | if (sense->fmt.f71.mdf == 0) | 1234 | if (sense->fmt.f71.mdf == 0) |
1225 | PRINT_WARN("(%s): Repair will disable interface 0x%x " | 1235 | snprintf(service, BUFSIZE, "Repair will disable " |
1226 | "on DV\n", | 1236 | "interface 0x%x on DV", sense->fmt.f71.md[1]); |
1227 | dev_name(&device->cdev->dev), | ||
1228 | sense->fmt.f71.md[1]); | ||
1229 | else | 1237 | else |
1230 | PRINT_WARN("(%s): Repair will disable interfaces " | 1238 | snprintf(service, BUFSIZE, "Repair will disable " |
1231 | "(0x%x-0x%x) on DV\n", | 1239 | "interfaces (0x%x-0x%x) on DV", |
1232 | dev_name(&device->cdev->dev), | 1240 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1233 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1234 | break; | 1241 | break; |
1235 | case 0x05: | 1242 | case 0x05: |
1236 | if (sense->fmt.f71.mdf == 0) | 1243 | if (sense->fmt.f71.mdf == 0) |
1237 | PRINT_WARN("(%s): Repair will disable loader 0x%x " | 1244 | snprintf(service, BUFSIZE, "Repair will disable loader" |
1238 | "on DV\n", | 1245 | " 0x%x on DV", sense->fmt.f71.md[1]); |
1239 | dev_name(&device->cdev->dev), | ||
1240 | sense->fmt.f71.md[1]); | ||
1241 | else | 1246 | else |
1242 | PRINT_WARN("(%s): Repair will disable loader " | 1247 | snprintf(service, BUFSIZE, "Repair will disable loader" |
1243 | "(0x%x-0x%x) on DV\n", | 1248 | " (0x%x-0x%x) on DV", |
1244 | dev_name(&device->cdev->dev), | 1249 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1245 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1246 | break; | 1250 | break; |
1247 | case 0x07: | 1251 | case 0x07: |
1248 | PRINT_WARN("(%s): Repair will disable access to DV\n", | 1252 | snprintf(service, BUFSIZE, "Repair will disable access to DV"); |
1249 | dev_name(&device->cdev->dev)); | ||
1250 | break; | 1253 | break; |
1251 | case 0x08: | 1254 | case 0x08: |
1252 | if (sense->fmt.f71.mdf == 0) | 1255 | if (sense->fmt.f71.mdf == 0) |
1253 | PRINT_WARN("(%s): Repair will disable message " | 1256 | snprintf(service, BUFSIZE, "Repair will disable " |
1254 | "display 0x%x on DV\n", | 1257 | "message display 0x%x on DV", |
1255 | dev_name(&device->cdev->dev), | 1258 | sense->fmt.f71.md[1]); |
1256 | sense->fmt.f71.md[1]); | ||
1257 | else | 1259 | else |
1258 | PRINT_WARN("(%s): Repair will disable message " | 1260 | snprintf(service, BUFSIZE, "Repair will disable " |
1259 | "displays (0x%x-0x%x) on DV\n", | 1261 | "message displays (0x%x-0x%x) on DV", |
1260 | dev_name(&device->cdev->dev), | 1262 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); |
1261 | sense->fmt.f71.md[1], sense->fmt.f71.md[2]); | ||
1262 | break; | 1263 | break; |
1263 | case 0x09: | 1264 | case 0x09: |
1264 | PRINT_WARN("(%s): Clean DV\n", dev_name(&device->cdev->dev)); | 1265 | snprintf(service, BUFSIZE, "Clean DV"); |
1265 | break; | 1266 | break; |
1266 | default: | 1267 | default: |
1267 | PRINT_WARN("(%s): DSIM ServiceMsg: 0x%02x\n", | 1268 | snprintf(service, BUFSIZE, "0x%02x", |
1268 | dev_name(&device->cdev->dev), sense->fmt.f71.smc); | 1269 | sense->fmt.f71.smc); |
1269 | } | 1270 | } |
1271 | |||
1272 | dev_warn (&device->cdev->dev, "Device subsystem information: exception" | ||
1273 | " %s, service %s\n", exception, service); | ||
1274 | out_nomem: | ||
1275 | kfree(exception); | ||
1276 | kfree(service); | ||
1270 | } | 1277 | } |
1271 | 1278 | ||
1272 | /* | 1279 | /* |
@@ -1282,46 +1289,44 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) | |||
1282 | return; | 1289 | return; |
1283 | if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) { | 1290 | if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) { |
1284 | if (tape_3590_msg[sense->mc] != NULL) | 1291 | if (tape_3590_msg[sense->mc] != NULL) |
1285 | PRINT_WARN("(%s): %s\n", dev_name(&device->cdev->dev), | 1292 | dev_warn (&device->cdev->dev, "The tape unit has " |
1286 | tape_3590_msg[sense->mc]); | 1293 | "issued sense message %s\n", |
1287 | else { | 1294 | tape_3590_msg[sense->mc]); |
1288 | PRINT_WARN("(%s): Message Code 0x%x\n", | 1295 | else |
1289 | dev_name(&device->cdev->dev), sense->mc); | 1296 | dev_warn (&device->cdev->dev, "The tape unit has " |
1290 | } | 1297 | "issued an unknown sense message code 0x%x\n", |
1298 | sense->mc); | ||
1291 | return; | 1299 | return; |
1292 | } | 1300 | } |
1293 | if (sense->mc == 0xf0) { | 1301 | if (sense->mc == 0xf0) { |
1294 | /* Standard Media Information Message */ | 1302 | /* Standard Media Information Message */ |
1295 | PRINT_WARN("(%s): MIM SEV=%i, MC=%02x, ES=%x/%x, " | 1303 | dev_warn (&device->cdev->dev, "MIM SEV=%i, MC=%02x, ES=%x/%x, " |
1296 | "RC=%02x-%04x-%02x\n", dev_name(&device->cdev->dev), | 1304 | "RC=%02x-%04x-%02x\n", sense->fmt.f70.sev, sense->mc, |
1297 | sense->fmt.f70.sev, sense->mc, | 1305 | sense->fmt.f70.emc, sense->fmt.f70.smc, |
1298 | sense->fmt.f70.emc, sense->fmt.f70.smc, | 1306 | sense->fmt.f70.refcode, sense->fmt.f70.mid, |
1299 | sense->fmt.f70.refcode, sense->fmt.f70.mid, | 1307 | sense->fmt.f70.fid); |
1300 | sense->fmt.f70.fid); | ||
1301 | tape_3590_print_mim_msg_f0(device, irb); | 1308 | tape_3590_print_mim_msg_f0(device, irb); |
1302 | return; | 1309 | return; |
1303 | } | 1310 | } |
1304 | if (sense->mc == 0xf1) { | 1311 | if (sense->mc == 0xf1) { |
1305 | /* Standard I/O Subsystem Service Information Message */ | 1312 | /* Standard I/O Subsystem Service Information Message */ |
1306 | PRINT_WARN("(%s): IOSIM SEV=%i, DEVTYPE=3590/%02x, " | 1313 | dev_warn (&device->cdev->dev, "IOSIM SEV=%i, DEVTYPE=3590/%02x," |
1307 | "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", | 1314 | " MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", |
1308 | dev_name(&device->cdev->dev), sense->fmt.f71.sev, | 1315 | sense->fmt.f71.sev, device->cdev->id.dev_model, |
1309 | device->cdev->id.dev_model, | 1316 | sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, |
1310 | sense->mc, sense->fmt.f71.emc, | 1317 | sense->fmt.f71.refcode1, sense->fmt.f71.refcode2, |
1311 | sense->fmt.f71.smc, sense->fmt.f71.refcode1, | 1318 | sense->fmt.f71.refcode3); |
1312 | sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); | ||
1313 | tape_3590_print_io_sim_msg_f1(device, irb); | 1319 | tape_3590_print_io_sim_msg_f1(device, irb); |
1314 | return; | 1320 | return; |
1315 | } | 1321 | } |
1316 | if (sense->mc == 0xf2) { | 1322 | if (sense->mc == 0xf2) { |
1317 | /* Standard Device Service Information Message */ | 1323 | /* Standard Device Service Information Message */ |
1318 | PRINT_WARN("(%s): DEVSIM SEV=%i, DEVTYPE=3590/%02x, " | 1324 | dev_warn (&device->cdev->dev, "DEVSIM SEV=%i, DEVTYPE=3590/%02x" |
1319 | "MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", | 1325 | ", MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n", |
1320 | dev_name(&device->cdev->dev), sense->fmt.f71.sev, | 1326 | sense->fmt.f71.sev, device->cdev->id.dev_model, |
1321 | device->cdev->id.dev_model, | 1327 | sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc, |
1322 | sense->mc, sense->fmt.f71.emc, | 1328 | sense->fmt.f71.refcode1, sense->fmt.f71.refcode2, |
1323 | sense->fmt.f71.smc, sense->fmt.f71.refcode1, | 1329 | sense->fmt.f71.refcode3); |
1324 | sense->fmt.f71.refcode2, sense->fmt.f71.refcode3); | ||
1325 | tape_3590_print_dev_sim_msg_f2(device, irb); | 1330 | tape_3590_print_dev_sim_msg_f2(device, irb); |
1326 | return; | 1331 | return; |
1327 | } | 1332 | } |
@@ -1329,8 +1334,8 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) | |||
1329 | /* Standard Library Service Information Message */ | 1334 | /* Standard Library Service Information Message */ |
1330 | return; | 1335 | return; |
1331 | } | 1336 | } |
1332 | PRINT_WARN("(%s): Device Message(%x)\n", | 1337 | dev_warn (&device->cdev->dev, "The tape unit has issued an unknown " |
1333 | dev_name(&device->cdev->dev), sense->mc); | 1338 | "sense message code %x\n", sense->mc); |
1334 | } | 1339 | } |
1335 | 1340 | ||
1336 | static int tape_3590_crypt_error(struct tape_device *device, | 1341 | static int tape_3590_crypt_error(struct tape_device *device, |
@@ -1355,9 +1360,8 @@ static int tape_3590_crypt_error(struct tape_device *device, | |||
1355 | /* No connection to EKM */ | 1360 | /* No connection to EKM */ |
1356 | return tape_3590_erp_basic(device, request, irb, -ENOTCONN); | 1361 | return tape_3590_erp_basic(device, request, irb, -ENOTCONN); |
1357 | 1362 | ||
1358 | PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id); | 1363 | dev_err (&device->cdev->dev, "The tape unit failed to obtain the " |
1359 | PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc, | 1364 | "encryption key from EKM\n"); |
1360 | drv_rc, ekm_rc1, ekm_rc2); | ||
1361 | 1365 | ||
1362 | return tape_3590_erp_basic(device, request, irb, -ENOKEY); | 1366 | return tape_3590_erp_basic(device, request, irb, -ENOKEY); |
1363 | } | 1367 | } |
@@ -1443,8 +1447,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1443 | * print additional msg since default msg | 1447 | * print additional msg since default msg |
1444 | * "device intervention" is not very meaningfull | 1448 | * "device intervention" is not very meaningfull |
1445 | */ | 1449 | */ |
1446 | PRINT_WARN("(%s): Tape operation when medium not loaded\n", | ||
1447 | dev_name(&device->cdev->dev)); | ||
1448 | tape_med_state_set(device, MS_UNLOADED); | 1450 | tape_med_state_set(device, MS_UNLOADED); |
1449 | tape_3590_schedule_work(device, TO_CRYPT_OFF); | 1451 | tape_3590_schedule_work(device, TO_CRYPT_OFF); |
1450 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); | 1452 | 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, | |||
1490 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); | 1492 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); |
1491 | 1493 | ||
1492 | case 0x6020: | 1494 | case 0x6020: |
1493 | PRINT_WARN("(%s): Cartridge of wrong type ?\n", | ||
1494 | dev_name(&device->cdev->dev)); | ||
1495 | return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); | 1495 | return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE); |
1496 | 1496 | ||
1497 | case 0x8011: | 1497 | case 0x8011: |
1498 | PRINT_WARN("(%s): Another host has reserved the tape device\n", | ||
1499 | dev_name(&device->cdev->dev)); | ||
1500 | return tape_3590_erp_basic(device, request, irb, -EPERM); | 1498 | return tape_3590_erp_basic(device, request, irb, -EPERM); |
1501 | case 0x8013: | 1499 | case 0x8013: |
1502 | PRINT_WARN("(%s): Another host has privileged access to the " | 1500 | dev_warn (&device->cdev->dev, "A different host has privileged" |
1503 | "tape device\n", dev_name(&device->cdev->dev)); | 1501 | " access to the tape unit\n"); |
1504 | PRINT_WARN("(%s): To solve the problem unload the current " | ||
1505 | "cartridge!\n", dev_name(&device->cdev->dev)); | ||
1506 | return tape_3590_erp_basic(device, request, irb, -EPERM); | 1502 | return tape_3590_erp_basic(device, request, irb, -EPERM); |
1507 | default: | 1503 | default: |
1508 | return tape_3590_erp_basic(device, request, irb, -EIO); | 1504 | return tape_3590_erp_basic(device, request, irb, -EIO); |
@@ -1552,9 +1548,7 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request, | |||
1552 | } | 1548 | } |
1553 | 1549 | ||
1554 | DBF_EVENT(6, "xunknownirq\n"); | 1550 | DBF_EVENT(6, "xunknownirq\n"); |
1555 | PRINT_ERR("Unexpected interrupt.\n"); | 1551 | tape_dump_sense_dbf(device, request, irb); |
1556 | PRINT_ERR("Current op is: %s", tape_op_verbose[request->op]); | ||
1557 | tape_dump_sense(device, request, irb); | ||
1558 | return TAPE_IO_STOP; | 1552 | return TAPE_IO_STOP; |
1559 | } | 1553 | } |
1560 | 1554 | ||
@@ -1609,7 +1603,6 @@ tape_3590_setup_device(struct tape_device *device) | |||
1609 | if (rc) | 1603 | if (rc) |
1610 | goto fail_rdc_data; | 1604 | goto fail_rdc_data; |
1611 | if (rdc_data->data[31] == 0x13) { | 1605 | if (rdc_data->data[31] == 0x13) { |
1612 | PRINT_INFO("Device has crypto support\n"); | ||
1613 | data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; | 1606 | data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; |
1614 | tape_3592_disable_crypt(device); | 1607 | tape_3592_disable_crypt(device); |
1615 | } else { | 1608 | } else { |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index ae18baf59f06..f32e89e7c4f2 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * Stefan Bader <shbader@de.ibm.com> | 10 | * Stefan Bader <shbader@de.ibm.com> |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define KMSG_COMPONENT "tape" | ||
14 | |||
13 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
14 | #include <linux/module.h> | 16 | #include <linux/module.h> |
15 | #include <linux/blkdev.h> | 17 | #include <linux/blkdev.h> |
@@ -23,8 +25,6 @@ | |||
23 | 25 | ||
24 | #include "tape.h" | 26 | #include "tape.h" |
25 | 27 | ||
26 | #define PRINTK_HEADER "TAPE_BLOCK: " | ||
27 | |||
28 | #define TAPEBLOCK_MAX_SEC 100 | 28 | #define TAPEBLOCK_MAX_SEC 100 |
29 | #define TAPEBLOCK_MIN_REQUEUE 3 | 29 | #define TAPEBLOCK_MIN_REQUEUE 3 |
30 | 30 | ||
@@ -279,8 +279,6 @@ tapeblock_cleanup_device(struct tape_device *device) | |||
279 | tape_put_device(device); | 279 | tape_put_device(device); |
280 | 280 | ||
281 | if (!device->blk_data.disk) { | 281 | if (!device->blk_data.disk) { |
282 | PRINT_ERR("(%s): No gendisk to clean up!\n", | ||
283 | dev_name(&device->cdev->dev)); | ||
284 | goto cleanup_queue; | 282 | goto cleanup_queue; |
285 | } | 283 | } |
286 | 284 | ||
@@ -314,7 +312,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) | |||
314 | if (!device->blk_data.medium_changed) | 312 | if (!device->blk_data.medium_changed) |
315 | return 0; | 313 | return 0; |
316 | 314 | ||
317 | PRINT_INFO("Detecting media size...\n"); | 315 | dev_info(&device->cdev->dev, "Determining the size of the recorded " |
316 | "area...\n"); | ||
318 | rc = tape_mtop(device, MTFSFM, 1); | 317 | rc = tape_mtop(device, MTFSFM, 1); |
319 | if (rc) | 318 | if (rc) |
320 | return rc; | 319 | return rc; |
@@ -341,7 +340,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) | |||
341 | device->bof = rc; | 340 | device->bof = rc; |
342 | nr_of_blks -= rc; | 341 | nr_of_blks -= rc; |
343 | 342 | ||
344 | PRINT_INFO("Found %i blocks on media\n", nr_of_blks); | 343 | dev_info(&device->cdev->dev, "The size of the recorded area is %i " |
344 | "blocks\n", nr_of_blks); | ||
345 | set_capacity(device->blk_data.disk, | 345 | set_capacity(device->blk_data.disk, |
346 | nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512)); | 346 | nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512)); |
347 | 347 | ||
@@ -376,8 +376,8 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) | |||
376 | 376 | ||
377 | if (device->required_tapemarks) { | 377 | if (device->required_tapemarks) { |
378 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); | 378 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); |
379 | PRINT_ERR("TBLOCK: Refusing to open tape with missing" | 379 | dev_warn(&device->cdev->dev, "Opening the tape failed because" |
380 | " end of file marks.\n"); | 380 | " of missing end-of-file marks\n"); |
381 | rc = -EPERM; | 381 | rc = -EPERM; |
382 | goto put_device; | 382 | goto put_device; |
383 | } | 383 | } |
@@ -452,7 +452,6 @@ tapeblock_ioctl( | |||
452 | rc = -EINVAL; | 452 | rc = -EINVAL; |
453 | break; | 453 | break; |
454 | default: | 454 | default: |
455 | PRINT_WARN("invalid ioctl 0x%x\n", command); | ||
456 | rc = -EINVAL; | 455 | rc = -EINVAL; |
457 | } | 456 | } |
458 | 457 | ||
@@ -474,7 +473,6 @@ tapeblock_init(void) | |||
474 | 473 | ||
475 | if (tapeblock_major == 0) | 474 | if (tapeblock_major == 0) |
476 | tapeblock_major = rc; | 475 | tapeblock_major = rc; |
477 | PRINT_INFO("tape gets major %d for block device\n", tapeblock_major); | ||
478 | return 0; | 476 | return 0; |
479 | } | 477 | } |
480 | 478 | ||
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index be0ce2215c8d..31566c55adfe 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include "tape_std.h" | 24 | #include "tape_std.h" |
25 | #include "tape_class.h" | 25 | #include "tape_class.h" |
26 | 26 | ||
27 | #define PRINTK_HEADER "TAPE_CHAR: " | ||
28 | |||
29 | #define TAPECHAR_MAJOR 0 /* get dynamic major */ | 27 | #define TAPECHAR_MAJOR 0 /* get dynamic major */ |
30 | 28 | ||
31 | /* | 29 | /* |
@@ -102,8 +100,6 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) | |||
102 | if (block_size > MAX_BLOCKSIZE) { | 100 | if (block_size > MAX_BLOCKSIZE) { |
103 | DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n", | 101 | DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n", |
104 | block_size, MAX_BLOCKSIZE); | 102 | block_size, MAX_BLOCKSIZE); |
105 | PRINT_ERR("Invalid blocksize (%zd> %d)\n", | ||
106 | block_size, MAX_BLOCKSIZE); | ||
107 | return -EINVAL; | 103 | return -EINVAL; |
108 | } | 104 | } |
109 | 105 | ||
@@ -485,7 +481,6 @@ tapechar_init (void) | |||
485 | return -1; | 481 | return -1; |
486 | 482 | ||
487 | tapechar_major = MAJOR(dev); | 483 | tapechar_major = MAJOR(dev); |
488 | PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev)); | ||
489 | 484 | ||
490 | return 0; | 485 | return 0; |
491 | } | 486 | } |
@@ -496,7 +491,5 @@ tapechar_init (void) | |||
496 | void | 491 | void |
497 | tapechar_exit(void) | 492 | tapechar_exit(void) |
498 | { | 493 | { |
499 | PRINT_INFO("tape releases major %d for character devices\n", | ||
500 | tapechar_major); | ||
501 | unregister_chrdev_region(MKDEV(tapechar_major, 0), 256); | 494 | unregister_chrdev_region(MKDEV(tapechar_major, 0), 256); |
502 | } | 495 | } |
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index f9bb51fa7f5b..08c09d3503cf 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Stefan Bader <shbader@de.ibm.com> | 11 | * Stefan Bader <shbader@de.ibm.com> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define KMSG_COMPONENT "tape" | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/init.h> // for kernel parameters | 16 | #include <linux/init.h> // for kernel parameters |
16 | #include <linux/kmod.h> // for requesting modules | 17 | #include <linux/kmod.h> // for requesting modules |
@@ -25,7 +26,6 @@ | |||
25 | #include "tape.h" | 26 | #include "tape.h" |
26 | #include "tape_std.h" | 27 | #include "tape_std.h" |
27 | 28 | ||
28 | #define PRINTK_HEADER "TAPE_CORE: " | ||
29 | #define LONG_BUSY_TIMEOUT 180 /* seconds */ | 29 | #define LONG_BUSY_TIMEOUT 180 /* seconds */ |
30 | 30 | ||
31 | static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *); | 31 | 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) | |||
214 | switch(newstate){ | 214 | switch(newstate){ |
215 | case MS_UNLOADED: | 215 | case MS_UNLOADED: |
216 | device->tape_generic_status |= GMT_DR_OPEN(~0); | 216 | device->tape_generic_status |= GMT_DR_OPEN(~0); |
217 | PRINT_INFO("(%s): Tape is unloaded\n", | 217 | dev_info(&device->cdev->dev, "The tape cartridge has been " |
218 | dev_name(&device->cdev->dev)); | 218 | "successfully unloaded\n"); |
219 | break; | 219 | break; |
220 | case MS_LOADED: | 220 | case MS_LOADED: |
221 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); | 221 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); |
222 | PRINT_INFO("(%s): Tape has been mounted\n", | 222 | dev_info(&device->cdev->dev, "A tape cartridge has been " |
223 | dev_name(&device->cdev->dev)); | 223 | "mounted\n"); |
224 | break; | 224 | break; |
225 | default: | 225 | default: |
226 | // print nothing | 226 | // print nothing |
@@ -333,7 +333,6 @@ tape_generic_online(struct tape_device *device, | |||
333 | /* Let the discipline have a go at the device. */ | 333 | /* Let the discipline have a go at the device. */ |
334 | device->discipline = discipline; | 334 | device->discipline = discipline; |
335 | if (!try_module_get(discipline->owner)) { | 335 | if (!try_module_get(discipline->owner)) { |
336 | PRINT_ERR("Cannot get module. Module gone.\n"); | ||
337 | return -EINVAL; | 336 | return -EINVAL; |
338 | } | 337 | } |
339 | 338 | ||
@@ -391,7 +390,6 @@ int | |||
391 | tape_generic_offline(struct tape_device *device) | 390 | tape_generic_offline(struct tape_device *device) |
392 | { | 391 | { |
393 | if (!device) { | 392 | if (!device) { |
394 | PRINT_ERR("tape_generic_offline: no such device\n"); | ||
395 | return -ENODEV; | 393 | return -ENODEV; |
396 | } | 394 | } |
397 | 395 | ||
@@ -413,9 +411,6 @@ tape_generic_offline(struct tape_device *device) | |||
413 | DBF_EVENT(3, "(%08x): Set offline failed " | 411 | DBF_EVENT(3, "(%08x): Set offline failed " |
414 | "- drive in use.\n", | 412 | "- drive in use.\n", |
415 | device->cdev_id); | 413 | device->cdev_id); |
416 | PRINT_WARN("(%s): Set offline failed " | ||
417 | "- drive in use.\n", | ||
418 | dev_name(&device->cdev->dev)); | ||
419 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 414 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
420 | return -EBUSY; | 415 | return -EBUSY; |
421 | } | 416 | } |
@@ -435,14 +430,11 @@ tape_alloc_device(void) | |||
435 | device = kzalloc(sizeof(struct tape_device), GFP_KERNEL); | 430 | device = kzalloc(sizeof(struct tape_device), GFP_KERNEL); |
436 | if (device == NULL) { | 431 | if (device == NULL) { |
437 | DBF_EXCEPTION(2, "ti:no mem\n"); | 432 | DBF_EXCEPTION(2, "ti:no mem\n"); |
438 | PRINT_INFO ("can't allocate memory for " | ||
439 | "tape info structure\n"); | ||
440 | return ERR_PTR(-ENOMEM); | 433 | return ERR_PTR(-ENOMEM); |
441 | } | 434 | } |
442 | device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA); | 435 | device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA); |
443 | if (device->modeset_byte == NULL) { | 436 | if (device->modeset_byte == NULL) { |
444 | DBF_EXCEPTION(2, "ti:no mem\n"); | 437 | DBF_EXCEPTION(2, "ti:no mem\n"); |
445 | PRINT_INFO("can't allocate memory for modeset byte\n"); | ||
446 | kfree(device); | 438 | kfree(device); |
447 | return ERR_PTR(-ENOMEM); | 439 | return ERR_PTR(-ENOMEM); |
448 | } | 440 | } |
@@ -490,7 +482,6 @@ tape_put_device(struct tape_device *device) | |||
490 | } else { | 482 | } else { |
491 | if (remain < 0) { | 483 | if (remain < 0) { |
492 | DBF_EVENT(4, "put device without reference\n"); | 484 | DBF_EVENT(4, "put device without reference\n"); |
493 | PRINT_ERR("put device without reference\n"); | ||
494 | } else { | 485 | } else { |
495 | DBF_EVENT(4, "tape_free_device(%p)\n", device); | 486 | DBF_EVENT(4, "tape_free_device(%p)\n", device); |
496 | kfree(device->modeset_byte); | 487 | kfree(device->modeset_byte); |
@@ -538,8 +529,6 @@ tape_generic_probe(struct ccw_device *cdev) | |||
538 | ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); | 529 | ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); |
539 | if (ret) { | 530 | if (ret) { |
540 | tape_put_device(device); | 531 | tape_put_device(device); |
541 | PRINT_ERR("probe failed for tape device %s\n", | ||
542 | dev_name(&cdev->dev)); | ||
543 | return ret; | 532 | return ret; |
544 | } | 533 | } |
545 | cdev->dev.driver_data = device; | 534 | cdev->dev.driver_data = device; |
@@ -547,7 +536,6 @@ tape_generic_probe(struct ccw_device *cdev) | |||
547 | device->cdev = cdev; | 536 | device->cdev = cdev; |
548 | ccw_device_get_id(cdev, &dev_id); | 537 | ccw_device_get_id(cdev, &dev_id); |
549 | device->cdev_id = devid_to_int(&dev_id); | 538 | device->cdev_id = devid_to_int(&dev_id); |
550 | PRINT_INFO("tape device %s found\n", dev_name(&cdev->dev)); | ||
551 | return ret; | 539 | return ret; |
552 | } | 540 | } |
553 | 541 | ||
@@ -584,7 +572,6 @@ tape_generic_remove(struct ccw_device *cdev) | |||
584 | 572 | ||
585 | device = cdev->dev.driver_data; | 573 | device = cdev->dev.driver_data; |
586 | if (!device) { | 574 | if (!device) { |
587 | PRINT_ERR("No device pointer in tape_generic_remove!\n"); | ||
588 | return; | 575 | return; |
589 | } | 576 | } |
590 | DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev); | 577 | DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev); |
@@ -615,10 +602,8 @@ tape_generic_remove(struct ccw_device *cdev) | |||
615 | */ | 602 | */ |
616 | DBF_EVENT(3, "(%08x): Drive in use vanished!\n", | 603 | DBF_EVENT(3, "(%08x): Drive in use vanished!\n", |
617 | device->cdev_id); | 604 | device->cdev_id); |
618 | PRINT_WARN("(%s): Drive in use vanished - " | 605 | dev_warn(&device->cdev->dev, "A tape unit was detached" |
619 | "expect trouble!\n", | 606 | " while in use\n"); |
620 | dev_name(&device->cdev->dev)); | ||
621 | PRINT_WARN("State was %i\n", device->tape_state); | ||
622 | tape_state_set(device, TS_NOT_OPER); | 607 | tape_state_set(device, TS_NOT_OPER); |
623 | __tape_discard_requests(device); | 608 | __tape_discard_requests(device); |
624 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 609 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
@@ -639,8 +624,7 @@ tape_alloc_request(int cplength, int datasize) | |||
639 | { | 624 | { |
640 | struct tape_request *request; | 625 | struct tape_request *request; |
641 | 626 | ||
642 | if (datasize > PAGE_SIZE || (cplength*sizeof(struct ccw1)) > PAGE_SIZE) | 627 | BUG_ON(datasize > PAGE_SIZE || (cplength*sizeof(struct ccw1)) > PAGE_SIZE); |
643 | BUG(); | ||
644 | 628 | ||
645 | DBF_LH(6, "tape_alloc_request(%d, %d)\n", cplength, datasize); | 629 | DBF_LH(6, "tape_alloc_request(%d, %d)\n", cplength, datasize); |
646 | 630 | ||
@@ -797,8 +781,7 @@ static void tape_long_busy_timeout(unsigned long data) | |||
797 | device = (struct tape_device *) data; | 781 | device = (struct tape_device *) data; |
798 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | 782 | spin_lock_irq(get_ccwdev_lock(device->cdev)); |
799 | request = list_entry(device->req_queue.next, struct tape_request, list); | 783 | request = list_entry(device->req_queue.next, struct tape_request, list); |
800 | if (request->status != TAPE_REQUEST_LONG_BUSY) | 784 | BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); |
801 | BUG(); | ||
802 | DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); | 785 | DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); |
803 | __tape_start_next_request(device); | 786 | __tape_start_next_request(device); |
804 | device->lb_timeout.data = (unsigned long) tape_put_device(device); | 787 | device->lb_timeout.data = (unsigned long) tape_put_device(device); |
@@ -830,30 +813,6 @@ __tape_end_request( | |||
830 | } | 813 | } |
831 | 814 | ||
832 | /* | 815 | /* |
833 | * Write sense data to console/dbf | ||
834 | */ | ||
835 | void | ||
836 | tape_dump_sense(struct tape_device* device, struct tape_request *request, | ||
837 | struct irb *irb) | ||
838 | { | ||
839 | unsigned int *sptr; | ||
840 | |||
841 | PRINT_INFO("-------------------------------------------------\n"); | ||
842 | PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n", | ||
843 | irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa); | ||
844 | PRINT_INFO("DEVICE: %s\n", dev_name(&device->cdev->dev)); | ||
845 | if (request != NULL) | ||
846 | PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]); | ||
847 | |||
848 | sptr = (unsigned int *) irb->ecw; | ||
849 | PRINT_INFO("Sense data: %08X %08X %08X %08X \n", | ||
850 | sptr[0], sptr[1], sptr[2], sptr[3]); | ||
851 | PRINT_INFO("Sense data: %08X %08X %08X %08X \n", | ||
852 | sptr[4], sptr[5], sptr[6], sptr[7]); | ||
853 | PRINT_INFO("--------------------------------------------------\n"); | ||
854 | } | ||
855 | |||
856 | /* | ||
857 | * Write sense data to dbf | 816 | * Write sense data to dbf |
858 | */ | 817 | */ |
859 | void | 818 | void |
@@ -1051,8 +1010,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1051 | 1010 | ||
1052 | device = (struct tape_device *) cdev->dev.driver_data; | 1011 | device = (struct tape_device *) cdev->dev.driver_data; |
1053 | if (device == NULL) { | 1012 | if (device == NULL) { |
1054 | PRINT_ERR("could not get device structure for %s " | ||
1055 | "in interrupt\n", dev_name(&cdev->dev)); | ||
1056 | return; | 1013 | return; |
1057 | } | 1014 | } |
1058 | request = (struct tape_request *) intparm; | 1015 | request = (struct tape_request *) intparm; |
@@ -1064,13 +1021,13 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1064 | /* FIXME: What to do with the request? */ | 1021 | /* FIXME: What to do with the request? */ |
1065 | switch (PTR_ERR(irb)) { | 1022 | switch (PTR_ERR(irb)) { |
1066 | case -ETIMEDOUT: | 1023 | case -ETIMEDOUT: |
1067 | PRINT_WARN("(%s): Request timed out\n", | 1024 | DBF_LH(1, "(%s): Request timed out\n", |
1068 | dev_name(&cdev->dev)); | 1025 | dev_name(&cdev->dev)); |
1069 | case -EIO: | 1026 | case -EIO: |
1070 | __tape_end_request(device, request, -EIO); | 1027 | __tape_end_request(device, request, -EIO); |
1071 | break; | 1028 | break; |
1072 | default: | 1029 | default: |
1073 | PRINT_ERR("(%s): Unexpected i/o error %li\n", | 1030 | DBF_LH(1, "(%s): Unexpected i/o error %li\n", |
1074 | dev_name(&cdev->dev), | 1031 | dev_name(&cdev->dev), |
1075 | PTR_ERR(irb)); | 1032 | PTR_ERR(irb)); |
1076 | } | 1033 | } |
@@ -1182,8 +1139,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1182 | default: | 1139 | default: |
1183 | if (rc > 0) { | 1140 | if (rc > 0) { |
1184 | DBF_EVENT(6, "xunknownrc\n"); | 1141 | DBF_EVENT(6, "xunknownrc\n"); |
1185 | PRINT_ERR("Invalid return code from discipline " | ||
1186 | "interrupt function.\n"); | ||
1187 | __tape_end_request(device, request, -EIO); | 1142 | __tape_end_request(device, request, -EIO); |
1188 | } else { | 1143 | } else { |
1189 | __tape_end_request(device, request, rc); | 1144 | __tape_end_request(device, request, rc); |
@@ -1323,7 +1278,6 @@ EXPORT_SYMBOL(tape_state_set); | |||
1323 | EXPORT_SYMBOL(tape_med_state_set); | 1278 | EXPORT_SYMBOL(tape_med_state_set); |
1324 | EXPORT_SYMBOL(tape_alloc_request); | 1279 | EXPORT_SYMBOL(tape_alloc_request); |
1325 | EXPORT_SYMBOL(tape_free_request); | 1280 | EXPORT_SYMBOL(tape_free_request); |
1326 | EXPORT_SYMBOL(tape_dump_sense); | ||
1327 | EXPORT_SYMBOL(tape_dump_sense_dbf); | 1281 | EXPORT_SYMBOL(tape_dump_sense_dbf); |
1328 | EXPORT_SYMBOL(tape_do_io); | 1282 | EXPORT_SYMBOL(tape_do_io); |
1329 | EXPORT_SYMBOL(tape_do_io_async); | 1283 | EXPORT_SYMBOL(tape_do_io_async); |
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index 8a376af926a7..202f42132939 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c | |||
@@ -20,8 +20,6 @@ | |||
20 | 20 | ||
21 | #include "tape.h" | 21 | #include "tape.h" |
22 | 22 | ||
23 | #define PRINTK_HEADER "TAPE_PROC: " | ||
24 | |||
25 | static const char *tape_med_st_verbose[MS_SIZE] = | 23 | static const char *tape_med_st_verbose[MS_SIZE] = |
26 | { | 24 | { |
27 | [MS_UNKNOWN] = "UNKNOWN ", | 25 | [MS_UNKNOWN] = "UNKNOWN ", |
@@ -128,7 +126,6 @@ tape_proc_init(void) | |||
128 | proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL, | 126 | proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL, |
129 | &tape_proc_ops); | 127 | &tape_proc_ops); |
130 | if (tape_proc_devices == NULL) { | 128 | if (tape_proc_devices == NULL) { |
131 | PRINT_WARN("tape: Cannot register procfs entry tapedevices\n"); | ||
132 | return; | 129 | return; |
133 | } | 130 | } |
134 | } | 131 | } |
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 5bd573d144d6..1a9420ba518d 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c | |||
@@ -26,8 +26,6 @@ | |||
26 | #include "tape.h" | 26 | #include "tape.h" |
27 | #include "tape_std.h" | 27 | #include "tape_std.h" |
28 | 28 | ||
29 | #define PRINTK_HEADER "TAPE_STD: " | ||
30 | |||
31 | /* | 29 | /* |
32 | * tape_std_assign | 30 | * tape_std_assign |
33 | */ | 31 | */ |
@@ -39,16 +37,15 @@ tape_std_assign_timeout(unsigned long data) | |||
39 | int rc; | 37 | int rc; |
40 | 38 | ||
41 | request = (struct tape_request *) data; | 39 | request = (struct tape_request *) data; |
42 | if ((device = request->device) == NULL) | 40 | device = request->device; |
43 | BUG(); | 41 | BUG_ON(!device); |
44 | 42 | ||
45 | DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", | 43 | DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", |
46 | device->cdev_id); | 44 | device->cdev_id); |
47 | rc = tape_cancel_io(device, request); | 45 | rc = tape_cancel_io(device, request); |
48 | if(rc) | 46 | if(rc) |
49 | PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n", | 47 | DBF_EVENT(3, "(%s): Assign timeout: Cancel failed with rc = %i\n", |
50 | dev_name(&device->cdev->dev), rc); | 48 | dev_name(&device->cdev->dev), rc); |
51 | |||
52 | } | 49 | } |
53 | 50 | ||
54 | int | 51 | int |
@@ -82,8 +79,6 @@ tape_std_assign(struct tape_device *device) | |||
82 | del_timer(&timeout); | 79 | del_timer(&timeout); |
83 | 80 | ||
84 | if (rc != 0) { | 81 | if (rc != 0) { |
85 | PRINT_WARN("%s: assign failed - device might be busy\n", | ||
86 | dev_name(&device->cdev->dev)); | ||
87 | DBF_EVENT(3, "%08x: assign failed - device might be busy\n", | 82 | DBF_EVENT(3, "%08x: assign failed - device might be busy\n", |
88 | device->cdev_id); | 83 | device->cdev_id); |
89 | } else { | 84 | } else { |
@@ -105,8 +100,6 @@ tape_std_unassign (struct tape_device *device) | |||
105 | if (device->tape_state == TS_NOT_OPER) { | 100 | if (device->tape_state == TS_NOT_OPER) { |
106 | DBF_EVENT(3, "(%08x): Can't unassign device\n", | 101 | DBF_EVENT(3, "(%08x): Can't unassign device\n", |
107 | device->cdev_id); | 102 | device->cdev_id); |
108 | PRINT_WARN("(%s): Can't unassign device - device gone\n", | ||
109 | dev_name(&device->cdev->dev)); | ||
110 | return -EIO; | 103 | return -EIO; |
111 | } | 104 | } |
112 | 105 | ||
@@ -120,8 +113,6 @@ tape_std_unassign (struct tape_device *device) | |||
120 | 113 | ||
121 | if ((rc = tape_do_io(device, request)) != 0) { | 114 | if ((rc = tape_do_io(device, request)) != 0) { |
122 | DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id); | 115 | DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id); |
123 | PRINT_WARN("%s: Unassign failed\n", | ||
124 | dev_name(&device->cdev->dev)); | ||
125 | } else { | 116 | } else { |
126 | DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id); | 117 | DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id); |
127 | } | 118 | } |
@@ -242,8 +233,6 @@ tape_std_mtsetblk(struct tape_device *device, int count) | |||
242 | if (count > MAX_BLOCKSIZE) { | 233 | if (count > MAX_BLOCKSIZE) { |
243 | DBF_EVENT(3, "Invalid block size (%d > %d) given.\n", | 234 | DBF_EVENT(3, "Invalid block size (%d > %d) given.\n", |
244 | count, MAX_BLOCKSIZE); | 235 | count, MAX_BLOCKSIZE); |
245 | PRINT_ERR("Invalid block size (%d > %d) given.\n", | ||
246 | count, MAX_BLOCKSIZE); | ||
247 | return -EINVAL; | 236 | return -EINVAL; |
248 | } | 237 | } |
249 | 238 | ||
@@ -633,14 +622,6 @@ tape_std_mtcompression(struct tape_device *device, int mt_count) | |||
633 | 622 | ||
634 | if (mt_count < 0 || mt_count > 1) { | 623 | if (mt_count < 0 || mt_count > 1) { |
635 | DBF_EXCEPTION(6, "xcom parm\n"); | 624 | DBF_EXCEPTION(6, "xcom parm\n"); |
636 | if (*device->modeset_byte & 0x08) | ||
637 | PRINT_INFO("(%s) Compression is currently on\n", | ||
638 | dev_name(&device->cdev->dev)); | ||
639 | else | ||
640 | PRINT_INFO("(%s) Compression is currently off\n", | ||
641 | dev_name(&device->cdev->dev)); | ||
642 | PRINT_INFO("Use 1 to switch compression on, 0 to " | ||
643 | "switch it off\n"); | ||
644 | return -EINVAL; | 625 | return -EINVAL; |
645 | } | 626 | } |
646 | request = tape_alloc_request(2, 0); | 627 | request = tape_alloc_request(2, 0); |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index eefc6611412e..1bbae433fbd8 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * For more information please refer to Documentation/s390/zfcpdump.txt | 6 | * For more information please refer to Documentation/s390/zfcpdump.txt |
7 | * | 7 | * |
8 | * Copyright IBM Corp. 2003,2007 | 8 | * Copyright IBM Corp. 2003,2008 |
9 | * Author(s): Michael Holzheu | 9 | * Author(s): Michael Holzheu |
10 | */ | 10 | */ |
11 | 11 | ||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/debug.h> | 24 | #include <asm/debug.h> |
25 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
26 | #include <asm/irqflags.h> | 26 | #include <asm/irqflags.h> |
27 | #include <asm/checksum.h> | ||
27 | #include "sclp.h" | 28 | #include "sclp.h" |
28 | 29 | ||
29 | #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) | 30 | #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) |
@@ -48,12 +49,19 @@ struct sys_info { | |||
48 | union save_area lc_mask; | 49 | union save_area lc_mask; |
49 | }; | 50 | }; |
50 | 51 | ||
52 | struct ipib_info { | ||
53 | unsigned long ipib; | ||
54 | u32 checksum; | ||
55 | } __attribute__((packed)); | ||
56 | |||
51 | static struct sys_info sys_info; | 57 | static struct sys_info sys_info; |
52 | static struct debug_info *zcore_dbf; | 58 | static struct debug_info *zcore_dbf; |
53 | static int hsa_available; | 59 | static int hsa_available; |
54 | static struct dentry *zcore_dir; | 60 | static struct dentry *zcore_dir; |
55 | static struct dentry *zcore_file; | 61 | static struct dentry *zcore_file; |
56 | static struct dentry *zcore_memmap_file; | 62 | static struct dentry *zcore_memmap_file; |
63 | static struct dentry *zcore_reipl_file; | ||
64 | static struct ipl_parameter_block *ipl_block; | ||
57 | 65 | ||
58 | /* | 66 | /* |
59 | * Copy memory from HSA to kernel or user memory (not reentrant): | 67 | * Copy memory from HSA to kernel or user memory (not reentrant): |
@@ -527,6 +535,33 @@ static const struct file_operations zcore_memmap_fops = { | |||
527 | .release = zcore_memmap_release, | 535 | .release = zcore_memmap_release, |
528 | }; | 536 | }; |
529 | 537 | ||
538 | static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, | ||
539 | size_t count, loff_t *ppos) | ||
540 | { | ||
541 | if (ipl_block) { | ||
542 | diag308(DIAG308_SET, ipl_block); | ||
543 | diag308(DIAG308_IPL, NULL); | ||
544 | } | ||
545 | return count; | ||
546 | } | ||
547 | |||
548 | static int zcore_reipl_open(struct inode *inode, struct file *filp) | ||
549 | { | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static int zcore_reipl_release(struct inode *inode, struct file *filp) | ||
554 | { | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static const struct file_operations zcore_reipl_fops = { | ||
559 | .owner = THIS_MODULE, | ||
560 | .write = zcore_reipl_write, | ||
561 | .open = zcore_reipl_open, | ||
562 | .release = zcore_reipl_release, | ||
563 | }; | ||
564 | |||
530 | 565 | ||
531 | static void __init set_s390_lc_mask(union save_area *map) | 566 | static void __init set_s390_lc_mask(union save_area *map) |
532 | { | 567 | { |
@@ -645,6 +680,40 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr) | |||
645 | return 0; | 680 | return 0; |
646 | } | 681 | } |
647 | 682 | ||
683 | /* | ||
684 | * Provide IPL parameter information block from either HSA or memory | ||
685 | * for future reipl | ||
686 | */ | ||
687 | static int __init zcore_reipl_init(void) | ||
688 | { | ||
689 | struct ipib_info ipib_info; | ||
690 | int rc; | ||
691 | |||
692 | rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info)); | ||
693 | if (rc) | ||
694 | return rc; | ||
695 | if (ipib_info.ipib == 0) | ||
696 | return 0; | ||
697 | ipl_block = (void *) __get_free_page(GFP_KERNEL); | ||
698 | if (!ipl_block) | ||
699 | return -ENOMEM; | ||
700 | if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) | ||
701 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); | ||
702 | else | ||
703 | rc = memcpy_real(ipl_block, ipib_info.ipib, PAGE_SIZE); | ||
704 | if (rc) { | ||
705 | free_page((unsigned long) ipl_block); | ||
706 | return rc; | ||
707 | } | ||
708 | if (csum_partial(ipl_block, ipl_block->hdr.len, 0) != | ||
709 | ipib_info.checksum) { | ||
710 | TRACE("Checksum does not match\n"); | ||
711 | free_page((unsigned long) ipl_block); | ||
712 | ipl_block = NULL; | ||
713 | } | ||
714 | return 0; | ||
715 | } | ||
716 | |||
648 | static int __init zcore_init(void) | 717 | static int __init zcore_init(void) |
649 | { | 718 | { |
650 | unsigned char arch; | 719 | unsigned char arch; |
@@ -690,6 +759,10 @@ static int __init zcore_init(void) | |||
690 | if (rc) | 759 | if (rc) |
691 | goto fail; | 760 | goto fail; |
692 | 761 | ||
762 | rc = zcore_reipl_init(); | ||
763 | if (rc) | ||
764 | goto fail; | ||
765 | |||
693 | zcore_dir = debugfs_create_dir("zcore" , NULL); | 766 | zcore_dir = debugfs_create_dir("zcore" , NULL); |
694 | if (!zcore_dir) { | 767 | if (!zcore_dir) { |
695 | rc = -ENOMEM; | 768 | rc = -ENOMEM; |
@@ -707,9 +780,17 @@ static int __init zcore_init(void) | |||
707 | rc = -ENOMEM; | 780 | rc = -ENOMEM; |
708 | goto fail_file; | 781 | goto fail_file; |
709 | } | 782 | } |
783 | zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, | ||
784 | NULL, &zcore_reipl_fops); | ||
785 | if (!zcore_reipl_file) { | ||
786 | rc = -ENOMEM; | ||
787 | goto fail_memmap_file; | ||
788 | } | ||
710 | hsa_available = 1; | 789 | hsa_available = 1; |
711 | return 0; | 790 | return 0; |
712 | 791 | ||
792 | fail_memmap_file: | ||
793 | debugfs_remove(zcore_memmap_file); | ||
713 | fail_file: | 794 | fail_file: |
714 | debugfs_remove(zcore_file); | 795 | debugfs_remove(zcore_file); |
715 | fail_dir: | 796 | fail_dir: |
@@ -723,10 +804,15 @@ static void __exit zcore_exit(void) | |||
723 | { | 804 | { |
724 | debug_unregister(zcore_dbf); | 805 | debug_unregister(zcore_dbf); |
725 | sclp_sdias_exit(); | 806 | sclp_sdias_exit(); |
807 | free_page((unsigned long) ipl_block); | ||
808 | debugfs_remove(zcore_reipl_file); | ||
809 | debugfs_remove(zcore_memmap_file); | ||
810 | debugfs_remove(zcore_file); | ||
811 | debugfs_remove(zcore_dir); | ||
726 | diag308(DIAG308_REL_HSA, NULL); | 812 | diag308(DIAG308_REL_HSA, NULL); |
727 | } | 813 | } |
728 | 814 | ||
729 | MODULE_AUTHOR("Copyright IBM Corp. 2003,2007"); | 815 | MODULE_AUTHOR("Copyright IBM Corp. 2003,2008"); |
730 | MODULE_DESCRIPTION("zcore module for zfcpdump support"); | 816 | MODULE_DESCRIPTION("zcore module for zfcpdump support"); |
731 | MODULE_LICENSE("GPL"); | 817 | MODULE_LICENSE("GPL"); |
732 | 818 | ||
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index bd79bd165396..adb3dd301528 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \ | 5 | obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \ |
6 | fcx.o itcw.o | 6 | fcx.o itcw.o crw.o |
7 | ccw_device-objs += device.o device_fsm.o device_ops.o | 7 | ccw_device-objs += device.o device_fsm.o device_ops.o |
8 | ccw_device-objs += device_id.o device_pgid.o device_status.o | 8 | ccw_device-objs += device_id.o device_pgid.o device_status.o |
9 | obj-y += ccw_device.o cmf.o | 9 | obj-y += ccw_device.o cmf.o |
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index fe6cea15bbaf..65d2e769dfa1 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c | |||
@@ -34,8 +34,8 @@ struct airq_t { | |||
34 | void *drv_data; | 34 | void *drv_data; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static union indicator_t indicators[MAX_ISC]; | 37 | static union indicator_t indicators[MAX_ISC+1]; |
38 | static struct airq_t *airqs[MAX_ISC][NR_AIRQS]; | 38 | static struct airq_t *airqs[MAX_ISC+1][NR_AIRQS]; |
39 | 39 | ||
40 | static int register_airq(struct airq_t *airq, u8 isc) | 40 | static int register_airq(struct airq_t *airq, u8 isc) |
41 | { | 41 | { |
@@ -133,6 +133,8 @@ void do_adapter_IO(u8 isc) | |||
133 | while (word) { | 133 | while (word) { |
134 | if (word & INDICATOR_MASK) { | 134 | if (word & INDICATOR_MASK) { |
135 | airq = airqs[isc][i]; | 135 | airq = airqs[isc][i]; |
136 | /* Make sure gcc reads from airqs only once. */ | ||
137 | barrier(); | ||
136 | if (likely(airq)) | 138 | if (likely(airq)) |
137 | airq->handler(&indicators[isc].byte[i], | 139 | airq->handler(&indicators[isc].byte[i], |
138 | airq->drv_data); | 140 | airq->drv_data); |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index fe00be3675cd..6565f027791e 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -336,8 +336,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf, | |||
336 | size_t user_len, loff_t *offset) | 336 | size_t user_len, loff_t *offset) |
337 | { | 337 | { |
338 | char *buf; | 338 | char *buf; |
339 | size_t i; | 339 | ssize_t rc, ret, i; |
340 | ssize_t rc, ret; | ||
341 | 340 | ||
342 | if (*offset) | 341 | if (*offset) |
343 | return -EINVAL; | 342 | return -EINVAL; |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index b91c1719b075..22ce765d537e 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -315,16 +315,32 @@ error: | |||
315 | } | 315 | } |
316 | EXPORT_SYMBOL(ccwgroup_create_from_string); | 316 | EXPORT_SYMBOL(ccwgroup_create_from_string); |
317 | 317 | ||
318 | static int __init | 318 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, |
319 | init_ccwgroup (void) | 319 | void *data); |
320 | |||
321 | static struct notifier_block ccwgroup_nb = { | ||
322 | .notifier_call = ccwgroup_notifier | ||
323 | }; | ||
324 | |||
325 | static int __init init_ccwgroup(void) | ||
320 | { | 326 | { |
321 | return bus_register (&ccwgroup_bus_type); | 327 | int ret; |
328 | |||
329 | ret = bus_register(&ccwgroup_bus_type); | ||
330 | if (ret) | ||
331 | return ret; | ||
332 | |||
333 | ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb); | ||
334 | if (ret) | ||
335 | bus_unregister(&ccwgroup_bus_type); | ||
336 | |||
337 | return ret; | ||
322 | } | 338 | } |
323 | 339 | ||
324 | static void __exit | 340 | static void __exit cleanup_ccwgroup(void) |
325 | cleanup_ccwgroup (void) | ||
326 | { | 341 | { |
327 | bus_unregister (&ccwgroup_bus_type); | 342 | bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb); |
343 | bus_unregister(&ccwgroup_bus_type); | ||
328 | } | 344 | } |
329 | 345 | ||
330 | module_init(init_ccwgroup); | 346 | module_init(init_ccwgroup); |
@@ -392,27 +408,28 @@ ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const | |||
392 | unsigned long value; | 408 | unsigned long value; |
393 | int ret; | 409 | int ret; |
394 | 410 | ||
395 | gdev = to_ccwgroupdev(dev); | ||
396 | if (!dev->driver) | 411 | if (!dev->driver) |
397 | return count; | 412 | return -ENODEV; |
413 | |||
414 | gdev = to_ccwgroupdev(dev); | ||
415 | gdrv = to_ccwgroupdrv(dev->driver); | ||
398 | 416 | ||
399 | gdrv = to_ccwgroupdrv (gdev->dev.driver); | ||
400 | if (!try_module_get(gdrv->owner)) | 417 | if (!try_module_get(gdrv->owner)) |
401 | return -EINVAL; | 418 | return -EINVAL; |
402 | 419 | ||
403 | ret = strict_strtoul(buf, 0, &value); | 420 | ret = strict_strtoul(buf, 0, &value); |
404 | if (ret) | 421 | if (ret) |
405 | goto out; | 422 | goto out; |
406 | ret = count; | 423 | |
407 | if (value == 1) | 424 | if (value == 1) |
408 | ccwgroup_set_online(gdev); | 425 | ret = ccwgroup_set_online(gdev); |
409 | else if (value == 0) | 426 | else if (value == 0) |
410 | ccwgroup_set_offline(gdev); | 427 | ret = ccwgroup_set_offline(gdev); |
411 | else | 428 | else |
412 | ret = -EINVAL; | 429 | ret = -EINVAL; |
413 | out: | 430 | out: |
414 | module_put(gdrv->owner); | 431 | module_put(gdrv->owner); |
415 | return ret; | 432 | return (ret == 0) ? count : ret; |
416 | } | 433 | } |
417 | 434 | ||
418 | static ssize_t | 435 | static ssize_t |
@@ -454,13 +471,18 @@ ccwgroup_remove (struct device *dev) | |||
454 | struct ccwgroup_device *gdev; | 471 | struct ccwgroup_device *gdev; |
455 | struct ccwgroup_driver *gdrv; | 472 | struct ccwgroup_driver *gdrv; |
456 | 473 | ||
474 | device_remove_file(dev, &dev_attr_online); | ||
475 | device_remove_file(dev, &dev_attr_ungroup); | ||
476 | |||
477 | if (!dev->driver) | ||
478 | return 0; | ||
479 | |||
457 | gdev = to_ccwgroupdev(dev); | 480 | gdev = to_ccwgroupdev(dev); |
458 | gdrv = to_ccwgroupdrv(dev->driver); | 481 | gdrv = to_ccwgroupdrv(dev->driver); |
459 | 482 | ||
460 | device_remove_file(dev, &dev_attr_online); | 483 | if (gdrv->remove) |
461 | |||
462 | if (gdrv && gdrv->remove) | ||
463 | gdrv->remove(gdev); | 484 | gdrv->remove(gdev); |
485 | |||
464 | return 0; | 486 | return 0; |
465 | } | 487 | } |
466 | 488 | ||
@@ -469,9 +491,13 @@ static void ccwgroup_shutdown(struct device *dev) | |||
469 | struct ccwgroup_device *gdev; | 491 | struct ccwgroup_device *gdev; |
470 | struct ccwgroup_driver *gdrv; | 492 | struct ccwgroup_driver *gdrv; |
471 | 493 | ||
494 | if (!dev->driver) | ||
495 | return; | ||
496 | |||
472 | gdev = to_ccwgroupdev(dev); | 497 | gdev = to_ccwgroupdev(dev); |
473 | gdrv = to_ccwgroupdrv(dev->driver); | 498 | gdrv = to_ccwgroupdrv(dev->driver); |
474 | if (gdrv && gdrv->shutdown) | 499 | |
500 | if (gdrv->shutdown) | ||
475 | gdrv->shutdown(gdev); | 501 | gdrv->shutdown(gdev); |
476 | } | 502 | } |
477 | 503 | ||
@@ -484,6 +510,19 @@ static struct bus_type ccwgroup_bus_type = { | |||
484 | .shutdown = ccwgroup_shutdown, | 510 | .shutdown = ccwgroup_shutdown, |
485 | }; | 511 | }; |
486 | 512 | ||
513 | |||
514 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | ||
515 | void *data) | ||
516 | { | ||
517 | struct device *dev = data; | ||
518 | |||
519 | if (action == BUS_NOTIFY_UNBIND_DRIVER) | ||
520 | device_schedule_callback(dev, ccwgroup_ungroup_callback); | ||
521 | |||
522 | return NOTIFY_OK; | ||
523 | } | ||
524 | |||
525 | |||
487 | /** | 526 | /** |
488 | * ccwgroup_driver_register() - register a ccw group driver | 527 | * ccwgroup_driver_register() - register a ccw group driver |
489 | * @cdriver: driver to be registered | 528 | * @cdriver: driver to be registered |
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 1246f61a5338..3e5f304ad88f 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <asm/chpid.h> | 18 | #include <asm/chpid.h> |
19 | #include <asm/sclp.h> | 19 | #include <asm/sclp.h> |
20 | #include <asm/crw.h> | ||
20 | 21 | ||
21 | #include "../s390mach.h" | ||
22 | #include "cio.h" | 22 | #include "cio.h" |
23 | #include "css.h" | 23 | #include "css.h" |
24 | #include "ioasm.h" | 24 | #include "ioasm.h" |
@@ -706,12 +706,12 @@ static int __init chp_init(void) | |||
706 | struct chp_id chpid; | 706 | struct chp_id chpid; |
707 | int ret; | 707 | int ret; |
708 | 708 | ||
709 | ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw); | 709 | ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw); |
710 | if (ret) | 710 | if (ret) |
711 | return ret; | 711 | return ret; |
712 | chp_wq = create_singlethread_workqueue("cio_chp"); | 712 | chp_wq = create_singlethread_workqueue("cio_chp"); |
713 | if (!chp_wq) { | 713 | if (!chp_wq) { |
714 | s390_unregister_crw_handler(CRW_RSC_CPATH); | 714 | crw_unregister_handler(CRW_RSC_CPATH); |
715 | return -ENOMEM; | 715 | return -ENOMEM; |
716 | } | 716 | } |
717 | INIT_WORK(&cfg_work, cfg_func); | 717 | INIT_WORK(&cfg_work, cfg_func); |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index ebab6ea4659b..883f16f96f22 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include <asm/cio.h> | 19 | #include <asm/cio.h> |
20 | #include <asm/chpid.h> | 20 | #include <asm/chpid.h> |
21 | #include <asm/chsc.h> | 21 | #include <asm/chsc.h> |
22 | #include <asm/crw.h> | ||
22 | 23 | ||
23 | #include "../s390mach.h" | ||
24 | #include "css.h" | 24 | #include "css.h" |
25 | #include "cio.h" | 25 | #include "cio.h" |
26 | #include "cio_debug.h" | 26 | #include "cio_debug.h" |
@@ -589,6 +589,7 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page) | |||
589 | case 0x0102: | 589 | case 0x0102: |
590 | case 0x0103: | 590 | case 0x0103: |
591 | ret = -EINVAL; | 591 | ret = -EINVAL; |
592 | break; | ||
592 | default: | 593 | default: |
593 | ret = chsc_error_from_response(secm_area->response.code); | 594 | ret = chsc_error_from_response(secm_area->response.code); |
594 | } | 595 | } |
@@ -820,7 +821,7 @@ int __init chsc_alloc_sei_area(void) | |||
820 | "chsc machine checks!\n"); | 821 | "chsc machine checks!\n"); |
821 | return -ENOMEM; | 822 | return -ENOMEM; |
822 | } | 823 | } |
823 | ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw); | 824 | ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw); |
824 | if (ret) | 825 | if (ret) |
825 | kfree(sei_page); | 826 | kfree(sei_page); |
826 | return ret; | 827 | return ret; |
@@ -828,7 +829,7 @@ int __init chsc_alloc_sei_area(void) | |||
828 | 829 | ||
829 | void __init chsc_free_sei_area(void) | 830 | void __init chsc_free_sei_area(void) |
830 | { | 831 | { |
831 | s390_unregister_crw_handler(CRW_RSC_CSS); | 832 | crw_unregister_handler(CRW_RSC_CSS); |
832 | kfree(sei_page); | 833 | kfree(sei_page); |
833 | } | 834 | } |
834 | 835 | ||
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 659f8a791656..2aebb9823044 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <asm/isc.h> | 30 | #include <asm/isc.h> |
31 | #include <asm/cpu.h> | 31 | #include <asm/cpu.h> |
32 | #include <asm/fcx.h> | 32 | #include <asm/fcx.h> |
33 | #include <asm/nmi.h> | ||
34 | #include <asm/crw.h> | ||
33 | #include "cio.h" | 35 | #include "cio.h" |
34 | #include "css.h" | 36 | #include "css.h" |
35 | #include "chsc.h" | 37 | #include "chsc.h" |
@@ -38,7 +40,6 @@ | |||
38 | #include "blacklist.h" | 40 | #include "blacklist.h" |
39 | #include "cio_debug.h" | 41 | #include "cio_debug.h" |
40 | #include "chp.h" | 42 | #include "chp.h" |
41 | #include "../s390mach.h" | ||
42 | 43 | ||
43 | debug_info_t *cio_debug_msg_id; | 44 | debug_info_t *cio_debug_msg_id; |
44 | debug_info_t *cio_debug_trace_id; | 45 | debug_info_t *cio_debug_trace_id; |
@@ -471,6 +472,7 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel); | |||
471 | int cio_disable_subchannel(struct subchannel *sch) | 472 | int cio_disable_subchannel(struct subchannel *sch) |
472 | { | 473 | { |
473 | char dbf_txt[15]; | 474 | char dbf_txt[15]; |
475 | int retry; | ||
474 | int ret; | 476 | int ret; |
475 | 477 | ||
476 | CIO_TRACE_EVENT (2, "dissch"); | 478 | CIO_TRACE_EVENT (2, "dissch"); |
@@ -481,16 +483,17 @@ int cio_disable_subchannel(struct subchannel *sch) | |||
481 | if (cio_update_schib(sch)) | 483 | if (cio_update_schib(sch)) |
482 | return -ENODEV; | 484 | return -ENODEV; |
483 | 485 | ||
484 | if (scsw_actl(&sch->schib.scsw) != 0) | ||
485 | /* | ||
486 | * the disable function must not be called while there are | ||
487 | * requests pending for completion ! | ||
488 | */ | ||
489 | return -EBUSY; | ||
490 | |||
491 | sch->config.ena = 0; | 486 | sch->config.ena = 0; |
492 | ret = cio_commit_config(sch); | ||
493 | 487 | ||
488 | for (retry = 0; retry < 3; retry++) { | ||
489 | ret = cio_commit_config(sch); | ||
490 | if (ret == -EBUSY) { | ||
491 | struct irb irb; | ||
492 | if (tsch(sch->schid, &irb) != 0) | ||
493 | break; | ||
494 | } else | ||
495 | break; | ||
496 | } | ||
494 | sprintf (dbf_txt, "ret:%d", ret); | 497 | sprintf (dbf_txt, "ret:%d", ret); |
495 | CIO_TRACE_EVENT (2, dbf_txt); | 498 | CIO_TRACE_EVENT (2, dbf_txt); |
496 | return ret; | 499 | return ret; |
diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c new file mode 100644 index 000000000000..d157665d0e76 --- /dev/null +++ b/drivers/s390/cio/crw.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Channel report handling code | ||
3 | * | ||
4 | * Copyright IBM Corp. 2000,2009 | ||
5 | * Author(s): Ingo Adlung <adlung@de.ibm.com>, | ||
6 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, | ||
7 | * Cornelia Huck <cornelia.huck@de.ibm.com>, | ||
8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, | ||
9 | */ | ||
10 | |||
11 | #include <linux/semaphore.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/kthread.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <asm/crw.h> | ||
16 | |||
17 | static struct semaphore crw_semaphore; | ||
18 | static DEFINE_MUTEX(crw_handler_mutex); | ||
19 | static crw_handler_t crw_handlers[NR_RSCS]; | ||
20 | |||
21 | /** | ||
22 | * crw_register_handler() - register a channel report word handler | ||
23 | * @rsc: reporting source code to handle | ||
24 | * @handler: handler to be registered | ||
25 | * | ||
26 | * Returns %0 on success and a negative error value otherwise. | ||
27 | */ | ||
28 | int crw_register_handler(int rsc, crw_handler_t handler) | ||
29 | { | ||
30 | int rc = 0; | ||
31 | |||
32 | if ((rsc < 0) || (rsc >= NR_RSCS)) | ||
33 | return -EINVAL; | ||
34 | mutex_lock(&crw_handler_mutex); | ||
35 | if (crw_handlers[rsc]) | ||
36 | rc = -EBUSY; | ||
37 | else | ||
38 | crw_handlers[rsc] = handler; | ||
39 | mutex_unlock(&crw_handler_mutex); | ||
40 | return rc; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * crw_unregister_handler() - unregister a channel report word handler | ||
45 | * @rsc: reporting source code to handle | ||
46 | */ | ||
47 | void crw_unregister_handler(int rsc) | ||
48 | { | ||
49 | if ((rsc < 0) || (rsc >= NR_RSCS)) | ||
50 | return; | ||
51 | mutex_lock(&crw_handler_mutex); | ||
52 | crw_handlers[rsc] = NULL; | ||
53 | mutex_unlock(&crw_handler_mutex); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Retrieve CRWs and call function to handle event. | ||
58 | */ | ||
59 | static int crw_collect_info(void *unused) | ||
60 | { | ||
61 | struct crw crw[2]; | ||
62 | int ccode; | ||
63 | unsigned int chain; | ||
64 | int ignore; | ||
65 | |||
66 | repeat: | ||
67 | ignore = down_interruptible(&crw_semaphore); | ||
68 | chain = 0; | ||
69 | while (1) { | ||
70 | crw_handler_t handler; | ||
71 | |||
72 | if (unlikely(chain > 1)) { | ||
73 | struct crw tmp_crw; | ||
74 | |||
75 | printk(KERN_WARNING"%s: Code does not support more " | ||
76 | "than two chained crws; please report to " | ||
77 | "linux390@de.ibm.com!\n", __func__); | ||
78 | ccode = stcrw(&tmp_crw); | ||
79 | printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " | ||
80 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
81 | __func__, tmp_crw.slct, tmp_crw.oflw, | ||
82 | tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, | ||
83 | tmp_crw.erc, tmp_crw.rsid); | ||
84 | printk(KERN_WARNING"%s: This was crw number %x in the " | ||
85 | "chain\n", __func__, chain); | ||
86 | if (ccode != 0) | ||
87 | break; | ||
88 | chain = tmp_crw.chn ? chain + 1 : 0; | ||
89 | continue; | ||
90 | } | ||
91 | ccode = stcrw(&crw[chain]); | ||
92 | if (ccode != 0) | ||
93 | break; | ||
94 | printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " | ||
95 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
96 | crw[chain].slct, crw[chain].oflw, crw[chain].chn, | ||
97 | crw[chain].rsc, crw[chain].anc, crw[chain].erc, | ||
98 | crw[chain].rsid); | ||
99 | /* Check for overflows. */ | ||
100 | if (crw[chain].oflw) { | ||
101 | int i; | ||
102 | |||
103 | pr_debug("%s: crw overflow detected!\n", __func__); | ||
104 | mutex_lock(&crw_handler_mutex); | ||
105 | for (i = 0; i < NR_RSCS; i++) { | ||
106 | if (crw_handlers[i]) | ||
107 | crw_handlers[i](NULL, NULL, 1); | ||
108 | } | ||
109 | mutex_unlock(&crw_handler_mutex); | ||
110 | chain = 0; | ||
111 | continue; | ||
112 | } | ||
113 | if (crw[0].chn && !chain) { | ||
114 | chain++; | ||
115 | continue; | ||
116 | } | ||
117 | mutex_lock(&crw_handler_mutex); | ||
118 | handler = crw_handlers[crw[chain].rsc]; | ||
119 | if (handler) | ||
120 | handler(&crw[0], chain ? &crw[1] : NULL, 0); | ||
121 | mutex_unlock(&crw_handler_mutex); | ||
122 | /* chain is always 0 or 1 here. */ | ||
123 | chain = crw[chain].chn ? chain + 1 : 0; | ||
124 | } | ||
125 | goto repeat; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | void crw_handle_channel_report(void) | ||
130 | { | ||
131 | up(&crw_semaphore); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Separate initcall needed for semaphore initialization since | ||
136 | * crw_handle_channel_report might be called before crw_machine_check_init. | ||
137 | */ | ||
138 | static int __init crw_init_semaphore(void) | ||
139 | { | ||
140 | init_MUTEX_LOCKED(&crw_semaphore); | ||
141 | return 0; | ||
142 | } | ||
143 | pure_initcall(crw_init_semaphore); | ||
144 | |||
145 | /* | ||
146 | * Machine checks for the channel subsystem must be enabled | ||
147 | * after the channel subsystem is initialized | ||
148 | */ | ||
149 | static int __init crw_machine_check_init(void) | ||
150 | { | ||
151 | struct task_struct *task; | ||
152 | |||
153 | task = kthread_run(crw_collect_info, NULL, "kmcheck"); | ||
154 | if (IS_ERR(task)) | ||
155 | return PTR_ERR(task); | ||
156 | ctl_set_bit(14, 28); /* enable channel report MCH */ | ||
157 | return 0; | ||
158 | } | ||
159 | device_initcall(crw_machine_check_init); | ||
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 427d11d88069..0085d8901792 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
20 | #include <asm/isc.h> | 20 | #include <asm/isc.h> |
21 | #include <asm/crw.h> | ||
21 | 22 | ||
22 | #include "../s390mach.h" | ||
23 | #include "css.h" | 23 | #include "css.h" |
24 | #include "cio.h" | 24 | #include "cio.h" |
25 | #include "cio_debug.h" | 25 | #include "cio_debug.h" |
@@ -83,6 +83,25 @@ static int call_fn_unknown_sch(struct subchannel_id schid, void *data) | |||
83 | return rc; | 83 | return rc; |
84 | } | 84 | } |
85 | 85 | ||
86 | static int call_fn_all_sch(struct subchannel_id schid, void *data) | ||
87 | { | ||
88 | struct cb_data *cb = data; | ||
89 | struct subchannel *sch; | ||
90 | int rc = 0; | ||
91 | |||
92 | sch = get_subchannel_by_schid(schid); | ||
93 | if (sch) { | ||
94 | if (cb->fn_known_sch) | ||
95 | rc = cb->fn_known_sch(sch, cb->data); | ||
96 | put_device(&sch->dev); | ||
97 | } else { | ||
98 | if (cb->fn_unknown_sch) | ||
99 | rc = cb->fn_unknown_sch(schid, cb->data); | ||
100 | } | ||
101 | |||
102 | return rc; | ||
103 | } | ||
104 | |||
86 | int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | 105 | int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), |
87 | int (*fn_unknown)(struct subchannel_id, | 106 | int (*fn_unknown)(struct subchannel_id, |
88 | void *), void *data) | 107 | void *), void *data) |
@@ -90,13 +109,17 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | |||
90 | struct cb_data cb; | 109 | struct cb_data cb; |
91 | int rc; | 110 | int rc; |
92 | 111 | ||
93 | cb.set = idset_sch_new(); | ||
94 | if (!cb.set) | ||
95 | return -ENOMEM; | ||
96 | idset_fill(cb.set); | ||
97 | cb.data = data; | 112 | cb.data = data; |
98 | cb.fn_known_sch = fn_known; | 113 | cb.fn_known_sch = fn_known; |
99 | cb.fn_unknown_sch = fn_unknown; | 114 | cb.fn_unknown_sch = fn_unknown; |
115 | |||
116 | cb.set = idset_sch_new(); | ||
117 | if (!cb.set) | ||
118 | /* fall back to brute force scanning in case of oom */ | ||
119 | return for_each_subchannel(call_fn_all_sch, &cb); | ||
120 | |||
121 | idset_fill(cb.set); | ||
122 | |||
100 | /* Process registered subchannels. */ | 123 | /* Process registered subchannels. */ |
101 | rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch); | 124 | rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch); |
102 | if (rc) | 125 | if (rc) |
@@ -510,6 +533,17 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) | |||
510 | return ret; | 533 | return ret; |
511 | } | 534 | } |
512 | 535 | ||
536 | static void reprobe_after_idle(struct work_struct *unused) | ||
537 | { | ||
538 | /* Make sure initial subchannel scan is done. */ | ||
539 | wait_event(ccw_device_init_wq, | ||
540 | atomic_read(&ccw_device_init_count) == 0); | ||
541 | if (need_reprobe) | ||
542 | css_schedule_reprobe(); | ||
543 | } | ||
544 | |||
545 | static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle); | ||
546 | |||
513 | /* Work function used to reprobe all unregistered subchannels. */ | 547 | /* Work function used to reprobe all unregistered subchannels. */ |
514 | static void reprobe_all(struct work_struct *unused) | 548 | static void reprobe_all(struct work_struct *unused) |
515 | { | 549 | { |
@@ -517,10 +551,12 @@ static void reprobe_all(struct work_struct *unused) | |||
517 | 551 | ||
518 | CIO_MSG_EVENT(4, "reprobe start\n"); | 552 | CIO_MSG_EVENT(4, "reprobe start\n"); |
519 | 553 | ||
520 | need_reprobe = 0; | ||
521 | /* Make sure initial subchannel scan is done. */ | 554 | /* Make sure initial subchannel scan is done. */ |
522 | wait_event(ccw_device_init_wq, | 555 | if (atomic_read(&ccw_device_init_count) != 0) { |
523 | atomic_read(&ccw_device_init_count) == 0); | 556 | queue_work(ccw_device_work, &reprobe_idle_work); |
557 | return; | ||
558 | } | ||
559 | need_reprobe = 0; | ||
524 | ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); | 560 | ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); |
525 | 561 | ||
526 | CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, | 562 | 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) | |||
619 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 655 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; |
620 | } else { | 656 | } else { |
621 | #ifdef CONFIG_SMP | 657 | #ifdef CONFIG_SMP |
622 | css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id(); | 658 | css->global_pgid.pgid_high.cpu_addr = stap(); |
623 | #else | 659 | #else |
624 | css->global_pgid.pgid_high.cpu_addr = 0; | 660 | css->global_pgid.pgid_high.cpu_addr = 0; |
625 | #endif | 661 | #endif |
@@ -765,7 +801,7 @@ init_channel_subsystem (void) | |||
765 | if (ret) | 801 | if (ret) |
766 | goto out; | 802 | goto out; |
767 | 803 | ||
768 | ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw); | 804 | ret = crw_register_handler(CRW_RSC_SCH, css_process_crw); |
769 | if (ret) | 805 | if (ret) |
770 | goto out; | 806 | goto out; |
771 | 807 | ||
@@ -845,7 +881,7 @@ out_unregister: | |||
845 | out_bus: | 881 | out_bus: |
846 | bus_unregister(&css_bus_type); | 882 | bus_unregister(&css_bus_type); |
847 | out: | 883 | out: |
848 | s390_unregister_crw_handler(CRW_RSC_CSS); | 884 | crw_unregister_handler(CRW_RSC_CSS); |
849 | chsc_free_sei_area(); | 885 | chsc_free_sei_area(); |
850 | kfree(slow_subchannel_set); | 886 | kfree(slow_subchannel_set); |
851 | pr_alert("The CSS device driver initialization failed with " | 887 | pr_alert("The CSS device driver initialization failed with " |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e28f8ae53453..c4d2f667a2f6 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -457,12 +457,13 @@ int ccw_device_set_online(struct ccw_device *cdev) | |||
457 | return (ret == 0) ? -ENODEV : ret; | 457 | return (ret == 0) ? -ENODEV : ret; |
458 | } | 458 | } |
459 | 459 | ||
460 | static void online_store_handle_offline(struct ccw_device *cdev) | 460 | static int online_store_handle_offline(struct ccw_device *cdev) |
461 | { | 461 | { |
462 | if (cdev->private->state == DEV_STATE_DISCONNECTED) | 462 | if (cdev->private->state == DEV_STATE_DISCONNECTED) |
463 | ccw_device_remove_disconnected(cdev); | 463 | ccw_device_remove_disconnected(cdev); |
464 | else if (cdev->drv && cdev->drv->set_offline) | 464 | else if (cdev->online && cdev->drv && cdev->drv->set_offline) |
465 | ccw_device_set_offline(cdev); | 465 | return ccw_device_set_offline(cdev); |
466 | return 0; | ||
466 | } | 467 | } |
467 | 468 | ||
468 | static int online_store_recog_and_online(struct ccw_device *cdev) | 469 | 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, | |||
530 | goto out; | 531 | goto out; |
531 | switch (i) { | 532 | switch (i) { |
532 | case 0: | 533 | case 0: |
533 | online_store_handle_offline(cdev); | 534 | ret = online_store_handle_offline(cdev); |
534 | ret = count; | ||
535 | break; | 535 | break; |
536 | case 1: | 536 | case 1: |
537 | ret = online_store_handle_online(cdev, force); | 537 | ret = online_store_handle_online(cdev, force); |
538 | if (!ret) | ||
539 | ret = count; | ||
540 | break; | 538 | break; |
541 | default: | 539 | default: |
542 | ret = -EINVAL; | 540 | ret = -EINVAL; |
@@ -545,7 +543,7 @@ out: | |||
545 | if (cdev->drv) | 543 | if (cdev->drv) |
546 | module_put(cdev->drv->owner); | 544 | module_put(cdev->drv->owner); |
547 | atomic_set(&cdev->private->onoff, 0); | 545 | atomic_set(&cdev->private->onoff, 0); |
548 | return ret; | 546 | return (ret < 0) ? ret : count; |
549 | } | 547 | } |
550 | 548 | ||
551 | static ssize_t | 549 | static ssize_t |
@@ -681,35 +679,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css, | |||
681 | return dev ? to_ccwdev(dev) : NULL; | 679 | return dev ? to_ccwdev(dev) : NULL; |
682 | } | 680 | } |
683 | 681 | ||
684 | static void | 682 | void ccw_device_do_unbind_bind(struct work_struct *work) |
685 | ccw_device_add_changed(struct work_struct *work) | ||
686 | { | ||
687 | struct ccw_device_private *priv; | ||
688 | struct ccw_device *cdev; | ||
689 | |||
690 | priv = container_of(work, struct ccw_device_private, kick_work); | ||
691 | cdev = priv->cdev; | ||
692 | if (device_add(&cdev->dev)) { | ||
693 | put_device(&cdev->dev); | ||
694 | return; | ||
695 | } | ||
696 | set_bit(1, &cdev->private->registered); | ||
697 | } | ||
698 | |||
699 | void ccw_device_do_unreg_rereg(struct work_struct *work) | ||
700 | { | 683 | { |
701 | struct ccw_device_private *priv; | 684 | struct ccw_device_private *priv; |
702 | struct ccw_device *cdev; | 685 | struct ccw_device *cdev; |
703 | struct subchannel *sch; | 686 | struct subchannel *sch; |
687 | int ret; | ||
704 | 688 | ||
705 | priv = container_of(work, struct ccw_device_private, kick_work); | 689 | priv = container_of(work, struct ccw_device_private, kick_work); |
706 | cdev = priv->cdev; | 690 | cdev = priv->cdev; |
707 | sch = to_subchannel(cdev->dev.parent); | 691 | sch = to_subchannel(cdev->dev.parent); |
708 | 692 | ||
709 | ccw_device_unregister(cdev); | 693 | if (test_bit(1, &cdev->private->registered)) { |
710 | PREPARE_WORK(&cdev->private->kick_work, | 694 | device_release_driver(&cdev->dev); |
711 | ccw_device_add_changed); | 695 | ret = device_attach(&cdev->dev); |
712 | queue_work(ccw_device_work, &cdev->private->kick_work); | 696 | WARN_ON(ret == -ENODEV); |
697 | } | ||
713 | } | 698 | } |
714 | 699 | ||
715 | static void | 700 | static void |
@@ -1035,8 +1020,6 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) | |||
1035 | void | 1020 | void |
1036 | io_subchannel_recog_done(struct ccw_device *cdev) | 1021 | io_subchannel_recog_done(struct ccw_device *cdev) |
1037 | { | 1022 | { |
1038 | struct subchannel *sch; | ||
1039 | |||
1040 | if (css_init_done == 0) { | 1023 | if (css_init_done == 0) { |
1041 | cdev->private->flags.recog_done = 1; | 1024 | cdev->private->flags.recog_done = 1; |
1042 | return; | 1025 | return; |
@@ -1047,7 +1030,6 @@ io_subchannel_recog_done(struct ccw_device *cdev) | |||
1047 | /* Remove device found not operational. */ | 1030 | /* Remove device found not operational. */ |
1048 | if (!get_device(&cdev->dev)) | 1031 | if (!get_device(&cdev->dev)) |
1049 | break; | 1032 | break; |
1050 | sch = to_subchannel(cdev->dev.parent); | ||
1051 | PREPARE_WORK(&cdev->private->kick_work, | 1033 | PREPARE_WORK(&cdev->private->kick_work, |
1052 | ccw_device_call_sch_unregister); | 1034 | ccw_device_call_sch_unregister); |
1053 | queue_work(slow_path_wq, &cdev->private->kick_work); | 1035 | queue_work(slow_path_wq, &cdev->private->kick_work); |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 0f2e63ea48de..85e01846ca65 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch); | |||
80 | 80 | ||
81 | int ccw_device_cancel_halt_clear(struct ccw_device *); | 81 | int ccw_device_cancel_halt_clear(struct ccw_device *); |
82 | 82 | ||
83 | void ccw_device_do_unreg_rereg(struct work_struct *); | 83 | void ccw_device_do_unbind_bind(struct work_struct *); |
84 | void ccw_device_move_to_orphanage(struct work_struct *); | 84 | void ccw_device_move_to_orphanage(struct work_struct *); |
85 | int ccw_device_is_orphan(struct ccw_device *); | 85 | int ccw_device_is_orphan(struct ccw_device *); |
86 | 86 | ||
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8df5eaafc5ab..87b4bfca080f 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev) | |||
194 | cdev->id.dev_type != cdev->private->senseid.dev_type || | 194 | cdev->id.dev_type != cdev->private->senseid.dev_type || |
195 | cdev->id.dev_model != cdev->private->senseid.dev_model) { | 195 | cdev->id.dev_model != cdev->private->senseid.dev_model) { |
196 | PREPARE_WORK(&cdev->private->kick_work, | 196 | PREPARE_WORK(&cdev->private->kick_work, |
197 | ccw_device_do_unreg_rereg); | 197 | ccw_device_do_unbind_bind); |
198 | queue_work(ccw_device_work, &cdev->private->kick_work); | 198 | queue_work(ccw_device_work, &cdev->private->kick_work); |
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
@@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev) | |||
366 | } | 366 | } |
367 | /* Driver doesn't want device back. */ | 367 | /* Driver doesn't want device back. */ |
368 | ccw_device_set_notoper(cdev); | 368 | ccw_device_set_notoper(cdev); |
369 | PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); | 369 | PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind); |
370 | queue_work(ccw_device_work, &cdev->private->kick_work); | 370 | queue_work(ccw_device_work, &cdev->private->kick_work); |
371 | } | 371 | } |
372 | 372 | ||
@@ -728,7 +728,7 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev, | |||
728 | { | 728 | { |
729 | struct subchannel *sch; | 729 | struct subchannel *sch; |
730 | 730 | ||
731 | cdev->private->state = DEV_STATE_NOT_OPER; | 731 | ccw_device_set_notoper(cdev); |
732 | sch = to_subchannel(cdev->dev.parent); | 732 | sch = to_subchannel(cdev->dev.parent); |
733 | css_schedule_eval(sch->schid); | 733 | css_schedule_eval(sch->schid); |
734 | } | 734 | } |
@@ -1052,7 +1052,7 @@ ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
1052 | sch = to_subchannel(cdev->dev.parent); | 1052 | sch = to_subchannel(cdev->dev.parent); |
1053 | /* | 1053 | /* |
1054 | * An interrupt in state offline means a previous disable was not | 1054 | * An interrupt in state offline means a previous disable was not |
1055 | * successful. Try again. | 1055 | * successful - should not happen, but we try to disable again. |
1056 | */ | 1056 | */ |
1057 | cio_disable_subchannel(sch); | 1057 | cio_disable_subchannel(sch); |
1058 | } | 1058 | } |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index eabcc42d63df..151754d54745 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -680,7 +680,7 @@ int ccw_device_tm_intrg(struct ccw_device *cdev) | |||
680 | if (cdev->private->state != DEV_STATE_ONLINE) | 680 | if (cdev->private->state != DEV_STATE_ONLINE) |
681 | return -EIO; | 681 | return -EIO; |
682 | if (!scsw_is_tm(&sch->schib.scsw) || | 682 | if (!scsw_is_tm(&sch->schib.scsw) || |
683 | !(scsw_actl(&sch->schib.scsw) | SCSW_ACTL_START_PEND)) | 683 | !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_START_PEND)) |
684 | return -EINVAL; | 684 | return -EINVAL; |
685 | return cio_tm_intrg(sch); | 685 | return cio_tm_intrg(sch); |
686 | } | 686 | } |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 42f2b09631b6..13bcb8114388 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -186,6 +186,9 @@ struct qdio_input_q { | |||
186 | /* input buffer acknowledgement flag */ | 186 | /* input buffer acknowledgement flag */ |
187 | int polling; | 187 | int polling; |
188 | 188 | ||
189 | /* first ACK'ed buffer */ | ||
190 | int ack_start; | ||
191 | |||
189 | /* how much sbals are acknowledged with qebsm */ | 192 | /* how much sbals are acknowledged with qebsm */ |
190 | int ack_count; | 193 | int ack_count; |
191 | 194 | ||
@@ -234,7 +237,7 @@ struct qdio_q { | |||
234 | int first_to_check; | 237 | int first_to_check; |
235 | 238 | ||
236 | /* first_to_check of the last time */ | 239 | /* first_to_check of the last time */ |
237 | int last_move_ftc; | 240 | int last_move; |
238 | 241 | ||
239 | /* beginning position for calling the program */ | 242 | /* beginning position for calling the program */ |
240 | int first_to_kick; | 243 | int first_to_kick; |
@@ -244,7 +247,6 @@ struct qdio_q { | |||
244 | 247 | ||
245 | struct qdio_irq *irq_ptr; | 248 | struct qdio_irq *irq_ptr; |
246 | struct tasklet_struct tasklet; | 249 | struct tasklet_struct tasklet; |
247 | spinlock_t lock; | ||
248 | 250 | ||
249 | /* error condition during a data transfer */ | 251 | /* error condition during a data transfer */ |
250 | unsigned int qdio_error; | 252 | unsigned int qdio_error; |
@@ -354,7 +356,7 @@ int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state, | |||
354 | int auto_ack); | 356 | int auto_ack); |
355 | void qdio_check_outbound_after_thinint(struct qdio_q *q); | 357 | void qdio_check_outbound_after_thinint(struct qdio_q *q); |
356 | int qdio_inbound_q_moved(struct qdio_q *q); | 358 | int qdio_inbound_q_moved(struct qdio_q *q); |
357 | void qdio_kick_inbound_handler(struct qdio_q *q); | 359 | void qdio_kick_handler(struct qdio_q *q); |
358 | void qdio_stop_polling(struct qdio_q *q); | 360 | void qdio_stop_polling(struct qdio_q *q); |
359 | int qdio_siga_sync_q(struct qdio_q *q); | 361 | int qdio_siga_sync_q(struct qdio_q *q); |
360 | 362 | ||
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index da7afb04e71f..e3434b34f86c 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c | |||
@@ -63,8 +63,9 @@ static int qstat_show(struct seq_file *m, void *v) | |||
63 | seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); | 63 | seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); |
64 | seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); | 64 | seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); |
65 | seq_printf(m, "ftc: %d\n", q->first_to_check); | 65 | seq_printf(m, "ftc: %d\n", q->first_to_check); |
66 | seq_printf(m, "last_move_ftc: %d\n", q->last_move_ftc); | 66 | seq_printf(m, "last_move: %d\n", q->last_move); |
67 | seq_printf(m, "polling: %d\n", q->u.in.polling); | 67 | seq_printf(m, "polling: %d\n", q->u.in.polling); |
68 | seq_printf(m, "ack start: %d\n", q->u.in.ack_start); | ||
68 | seq_printf(m, "ack count: %d\n", q->u.in.ack_count); | 69 | seq_printf(m, "ack count: %d\n", q->u.in.ack_count); |
69 | seq_printf(m, "slsb buffer states:\n"); | 70 | seq_printf(m, "slsb buffer states:\n"); |
70 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); | 71 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 10cb0f8726e5..9e8a2914259b 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -380,11 +380,11 @@ inline void qdio_stop_polling(struct qdio_q *q) | |||
380 | 380 | ||
381 | /* show the card that we are not polling anymore */ | 381 | /* show the card that we are not polling anymore */ |
382 | if (is_qebsm(q)) { | 382 | if (is_qebsm(q)) { |
383 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, | 383 | set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, |
384 | q->u.in.ack_count); | 384 | q->u.in.ack_count); |
385 | q->u.in.ack_count = 0; | 385 | q->u.in.ack_count = 0; |
386 | } else | 386 | } else |
387 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | 387 | set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); |
388 | } | 388 | } |
389 | 389 | ||
390 | static void announce_buffer_error(struct qdio_q *q, int count) | 390 | 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) | |||
419 | if (!q->u.in.polling) { | 419 | if (!q->u.in.polling) { |
420 | q->u.in.polling = 1; | 420 | q->u.in.polling = 1; |
421 | q->u.in.ack_count = count; | 421 | q->u.in.ack_count = count; |
422 | q->last_move_ftc = q->first_to_check; | 422 | q->u.in.ack_start = q->first_to_check; |
423 | return; | 423 | return; |
424 | } | 424 | } |
425 | 425 | ||
426 | /* delete the previous ACK's */ | 426 | /* delete the previous ACK's */ |
427 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, | 427 | set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, |
428 | q->u.in.ack_count); | 428 | q->u.in.ack_count); |
429 | q->u.in.ack_count = count; | 429 | q->u.in.ack_count = count; |
430 | q->last_move_ftc = q->first_to_check; | 430 | q->u.in.ack_start = q->first_to_check; |
431 | return; | 431 | return; |
432 | } | 432 | } |
433 | 433 | ||
@@ -439,14 +439,13 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
439 | if (q->u.in.polling) { | 439 | if (q->u.in.polling) { |
440 | /* reset the previous ACK but first set the new one */ | 440 | /* reset the previous ACK but first set the new one */ |
441 | set_buf_state(q, new, SLSB_P_INPUT_ACK); | 441 | set_buf_state(q, new, SLSB_P_INPUT_ACK); |
442 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | 442 | set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); |
443 | } | 443 | } else { |
444 | else { | ||
445 | q->u.in.polling = 1; | 444 | q->u.in.polling = 1; |
446 | set_buf_state(q, q->first_to_check, SLSB_P_INPUT_ACK); | 445 | set_buf_state(q, new, SLSB_P_INPUT_ACK); |
447 | } | 446 | } |
448 | 447 | ||
449 | q->last_move_ftc = new; | 448 | q->u.in.ack_start = new; |
450 | count--; | 449 | count--; |
451 | if (!count) | 450 | if (!count) |
452 | return; | 451 | return; |
@@ -455,7 +454,7 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
455 | * Need to change all PRIMED buffers to NOT_INIT, otherwise | 454 | * Need to change all PRIMED buffers to NOT_INIT, otherwise |
456 | * we're loosing initiative in the thinint code. | 455 | * we're loosing initiative in the thinint code. |
457 | */ | 456 | */ |
458 | set_buf_states(q, next_buf(q->first_to_check), SLSB_P_INPUT_NOT_INIT, | 457 | set_buf_states(q, q->first_to_check, SLSB_P_INPUT_NOT_INIT, |
459 | count); | 458 | count); |
460 | } | 459 | } |
461 | 460 | ||
@@ -523,7 +522,8 @@ int qdio_inbound_q_moved(struct qdio_q *q) | |||
523 | 522 | ||
524 | bufnr = get_inbound_buffer_frontier(q); | 523 | bufnr = get_inbound_buffer_frontier(q); |
525 | 524 | ||
526 | if ((bufnr != q->last_move_ftc) || q->qdio_error) { | 525 | if ((bufnr != q->last_move) || q->qdio_error) { |
526 | q->last_move = bufnr; | ||
527 | if (!need_siga_sync(q) && !pci_out_supported(q)) | 527 | if (!need_siga_sync(q) && !pci_out_supported(q)) |
528 | q->u.in.timestamp = get_usecs(); | 528 | q->u.in.timestamp = get_usecs(); |
529 | 529 | ||
@@ -570,29 +570,30 @@ static int qdio_inbound_q_done(struct qdio_q *q) | |||
570 | } | 570 | } |
571 | } | 571 | } |
572 | 572 | ||
573 | void qdio_kick_inbound_handler(struct qdio_q *q) | 573 | void qdio_kick_handler(struct qdio_q *q) |
574 | { | 574 | { |
575 | int count, start, end; | 575 | int start = q->first_to_kick; |
576 | 576 | int end = q->first_to_check; | |
577 | qdio_perf_stat_inc(&perf_stats.inbound_handler); | 577 | int count; |
578 | |||
579 | start = q->first_to_kick; | ||
580 | end = q->first_to_check; | ||
581 | if (end >= start) | ||
582 | count = end - start; | ||
583 | else | ||
584 | count = end + QDIO_MAX_BUFFERS_PER_Q - start; | ||
585 | |||
586 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); | ||
587 | 578 | ||
588 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) | 579 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) |
589 | return; | 580 | return; |
590 | 581 | ||
591 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, | 582 | count = sub_buf(end, start); |
592 | start, count, q->irq_ptr->int_parm); | 583 | |
584 | if (q->is_input_q) { | ||
585 | qdio_perf_stat_inc(&perf_stats.inbound_handler); | ||
586 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); | ||
587 | } else { | ||
588 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: nr:%1d", q->nr); | ||
589 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); | ||
590 | } | ||
591 | |||
592 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, | ||
593 | q->irq_ptr->int_parm); | ||
593 | 594 | ||
594 | /* for the next time */ | 595 | /* for the next time */ |
595 | q->first_to_kick = q->first_to_check; | 596 | q->first_to_kick = end; |
596 | q->qdio_error = 0; | 597 | q->qdio_error = 0; |
597 | } | 598 | } |
598 | 599 | ||
@@ -603,7 +604,7 @@ again: | |||
603 | if (!qdio_inbound_q_moved(q)) | 604 | if (!qdio_inbound_q_moved(q)) |
604 | return; | 605 | return; |
605 | 606 | ||
606 | qdio_kick_inbound_handler(q); | 607 | qdio_kick_handler(q); |
607 | 608 | ||
608 | if (!qdio_inbound_q_done(q)) | 609 | if (!qdio_inbound_q_done(q)) |
609 | /* means poll time is not yet over */ | 610 | /* means poll time is not yet over */ |
@@ -698,21 +699,21 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q) | |||
698 | 699 | ||
699 | bufnr = get_outbound_buffer_frontier(q); | 700 | bufnr = get_outbound_buffer_frontier(q); |
700 | 701 | ||
701 | if ((bufnr != q->last_move_ftc) || q->qdio_error) { | 702 | if ((bufnr != q->last_move) || q->qdio_error) { |
702 | q->last_move_ftc = bufnr; | 703 | q->last_move = bufnr; |
703 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); | 704 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); |
704 | return 1; | 705 | return 1; |
705 | } else | 706 | } else |
706 | return 0; | 707 | return 0; |
707 | } | 708 | } |
708 | 709 | ||
709 | static void qdio_kick_outbound_q(struct qdio_q *q) | 710 | static int qdio_kick_outbound_q(struct qdio_q *q) |
710 | { | 711 | { |
711 | unsigned int busy_bit; | 712 | unsigned int busy_bit; |
712 | int cc; | 713 | int cc; |
713 | 714 | ||
714 | if (!need_siga_out(q)) | 715 | if (!need_siga_out(q)) |
715 | return; | 716 | return 0; |
716 | 717 | ||
717 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr); | 718 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr); |
718 | qdio_perf_stat_inc(&perf_stats.siga_out); | 719 | qdio_perf_stat_inc(&perf_stats.siga_out); |
@@ -724,75 +725,37 @@ static void qdio_kick_outbound_q(struct qdio_q *q) | |||
724 | case 2: | 725 | case 2: |
725 | if (busy_bit) { | 726 | if (busy_bit) { |
726 | DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr); | 727 | DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr); |
727 | q->qdio_error = cc | QDIO_ERROR_SIGA_BUSY; | 728 | cc |= QDIO_ERROR_SIGA_BUSY; |
728 | } else { | 729 | } else |
729 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", | 730 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", q->nr); |
730 | q->nr); | ||
731 | q->qdio_error = cc; | ||
732 | } | ||
733 | break; | 731 | break; |
734 | case 1: | 732 | case 1: |
735 | case 3: | 733 | case 3: |
736 | DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc); | 734 | DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc); |
737 | q->qdio_error = cc; | ||
738 | break; | 735 | break; |
739 | } | 736 | } |
740 | } | 737 | return cc; |
741 | |||
742 | static void qdio_kick_outbound_handler(struct qdio_q *q) | ||
743 | { | ||
744 | int start, end, count; | ||
745 | |||
746 | start = q->first_to_kick; | ||
747 | end = q->last_move_ftc; | ||
748 | if (end >= start) | ||
749 | count = end - start; | ||
750 | else | ||
751 | count = end + QDIO_MAX_BUFFERS_PER_Q - start; | ||
752 | |||
753 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kickouth: %1d", q->nr); | ||
754 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); | ||
755 | |||
756 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) | ||
757 | return; | ||
758 | |||
759 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, | ||
760 | q->irq_ptr->int_parm); | ||
761 | |||
762 | /* for the next time: */ | ||
763 | q->first_to_kick = q->last_move_ftc; | ||
764 | q->qdio_error = 0; | ||
765 | } | 738 | } |
766 | 739 | ||
767 | static void __qdio_outbound_processing(struct qdio_q *q) | 740 | static void __qdio_outbound_processing(struct qdio_q *q) |
768 | { | 741 | { |
769 | unsigned long flags; | ||
770 | |||
771 | qdio_perf_stat_inc(&perf_stats.tasklet_outbound); | 742 | qdio_perf_stat_inc(&perf_stats.tasklet_outbound); |
772 | spin_lock_irqsave(&q->lock, flags); | ||
773 | |||
774 | BUG_ON(atomic_read(&q->nr_buf_used) < 0); | 743 | BUG_ON(atomic_read(&q->nr_buf_used) < 0); |
775 | 744 | ||
776 | if (qdio_outbound_q_moved(q)) | 745 | if (qdio_outbound_q_moved(q)) |
777 | qdio_kick_outbound_handler(q); | 746 | qdio_kick_handler(q); |
778 | |||
779 | spin_unlock_irqrestore(&q->lock, flags); | ||
780 | 747 | ||
781 | if (queue_type(q) == QDIO_ZFCP_QFMT) { | 748 | if (queue_type(q) == QDIO_ZFCP_QFMT) |
782 | if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) | 749 | if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) |
783 | tasklet_schedule(&q->tasklet); | 750 | goto sched; |
784 | return; | ||
785 | } | ||
786 | 751 | ||
787 | /* bail out for HiperSockets unicast queues */ | 752 | /* bail out for HiperSockets unicast queues */ |
788 | if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) | 753 | if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) |
789 | return; | 754 | return; |
790 | 755 | ||
791 | if ((queue_type(q) == QDIO_IQDIO_QFMT) && | 756 | if ((queue_type(q) == QDIO_IQDIO_QFMT) && |
792 | (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) { | 757 | (atomic_read(&q->nr_buf_used)) > QDIO_IQDIO_POLL_LVL) |
793 | tasklet_schedule(&q->tasklet); | 758 | goto sched; |
794 | return; | ||
795 | } | ||
796 | 759 | ||
797 | if (q->u.out.pci_out_enabled) | 760 | if (q->u.out.pci_out_enabled) |
798 | return; | 761 | return; |
@@ -810,6 +773,12 @@ static void __qdio_outbound_processing(struct qdio_q *q) | |||
810 | qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer); | 773 | qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer); |
811 | } | 774 | } |
812 | } | 775 | } |
776 | return; | ||
777 | |||
778 | sched: | ||
779 | if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | ||
780 | return; | ||
781 | tasklet_schedule(&q->tasklet); | ||
813 | } | 782 | } |
814 | 783 | ||
815 | /* outbound tasklet */ | 784 | /* outbound tasklet */ |
@@ -822,6 +791,9 @@ void qdio_outbound_processing(unsigned long data) | |||
822 | void qdio_outbound_timer(unsigned long data) | 791 | void qdio_outbound_timer(unsigned long data) |
823 | { | 792 | { |
824 | struct qdio_q *q = (struct qdio_q *)data; | 793 | struct qdio_q *q = (struct qdio_q *)data; |
794 | |||
795 | if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | ||
796 | return; | ||
825 | tasklet_schedule(&q->tasklet); | 797 | tasklet_schedule(&q->tasklet); |
826 | } | 798 | } |
827 | 799 | ||
@@ -863,6 +835,9 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) | |||
863 | int i; | 835 | int i; |
864 | struct qdio_q *q; | 836 | struct qdio_q *q; |
865 | 837 | ||
838 | if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) | ||
839 | return; | ||
840 | |||
866 | qdio_perf_stat_inc(&perf_stats.pci_int); | 841 | qdio_perf_stat_inc(&perf_stats.pci_int); |
867 | 842 | ||
868 | for_each_input_queue(irq_ptr, q, i) | 843 | for_each_input_queue(irq_ptr, q, i) |
@@ -1065,8 +1040,9 @@ EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | |||
1065 | * @cdev: associated ccw device | 1040 | * @cdev: associated ccw device |
1066 | * @how: use halt or clear to shutdown | 1041 | * @how: use halt or clear to shutdown |
1067 | * | 1042 | * |
1068 | * This function calls qdio_shutdown() for @cdev with method @how | 1043 | * This function calls qdio_shutdown() for @cdev with method @how. |
1069 | * and on success qdio_free() for @cdev. | 1044 | * and qdio_free(). The qdio_free() return value is ignored since |
1045 | * !irq_ptr is already checked. | ||
1070 | */ | 1046 | */ |
1071 | int qdio_cleanup(struct ccw_device *cdev, int how) | 1047 | int qdio_cleanup(struct ccw_device *cdev, int how) |
1072 | { | 1048 | { |
@@ -1077,8 +1053,8 @@ int qdio_cleanup(struct ccw_device *cdev, int how) | |||
1077 | return -ENODEV; | 1053 | return -ENODEV; |
1078 | 1054 | ||
1079 | rc = qdio_shutdown(cdev, how); | 1055 | rc = qdio_shutdown(cdev, how); |
1080 | if (rc == 0) | 1056 | |
1081 | rc = qdio_free(cdev); | 1057 | qdio_free(cdev); |
1082 | return rc; | 1058 | return rc; |
1083 | } | 1059 | } |
1084 | EXPORT_SYMBOL_GPL(qdio_cleanup); | 1060 | EXPORT_SYMBOL_GPL(qdio_cleanup); |
@@ -1090,11 +1066,11 @@ static void qdio_shutdown_queues(struct ccw_device *cdev) | |||
1090 | int i; | 1066 | int i; |
1091 | 1067 | ||
1092 | for_each_input_queue(irq_ptr, q, i) | 1068 | for_each_input_queue(irq_ptr, q, i) |
1093 | tasklet_disable(&q->tasklet); | 1069 | tasklet_kill(&q->tasklet); |
1094 | 1070 | ||
1095 | for_each_output_queue(irq_ptr, q, i) { | 1071 | for_each_output_queue(irq_ptr, q, i) { |
1096 | tasklet_disable(&q->tasklet); | ||
1097 | del_timer(&q->u.out.timer); | 1072 | del_timer(&q->u.out.timer); |
1073 | tasklet_kill(&q->tasklet); | ||
1098 | } | 1074 | } |
1099 | } | 1075 | } |
1100 | 1076 | ||
@@ -1112,6 +1088,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how) | |||
1112 | if (!irq_ptr) | 1088 | if (!irq_ptr) |
1113 | return -ENODEV; | 1089 | return -ENODEV; |
1114 | 1090 | ||
1091 | BUG_ON(irqs_disabled()); | ||
1115 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); | 1092 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); |
1116 | 1093 | ||
1117 | mutex_lock(&irq_ptr->setup_mutex); | 1094 | mutex_lock(&irq_ptr->setup_mutex); |
@@ -1124,6 +1101,12 @@ int qdio_shutdown(struct ccw_device *cdev, int how) | |||
1124 | return 0; | 1101 | return 0; |
1125 | } | 1102 | } |
1126 | 1103 | ||
1104 | /* | ||
1105 | * Indicate that the device is going down. Scheduling the queue | ||
1106 | * tasklets is forbidden from here on. | ||
1107 | */ | ||
1108 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); | ||
1109 | |||
1127 | tiqdio_remove_input_queues(irq_ptr); | 1110 | tiqdio_remove_input_queues(irq_ptr); |
1128 | qdio_shutdown_queues(cdev); | 1111 | qdio_shutdown_queues(cdev); |
1129 | qdio_shutdown_debug_entries(irq_ptr, cdev); | 1112 | qdio_shutdown_debug_entries(irq_ptr, cdev); |
@@ -1403,9 +1386,8 @@ int qdio_activate(struct ccw_device *cdev) | |||
1403 | switch (irq_ptr->state) { | 1386 | switch (irq_ptr->state) { |
1404 | case QDIO_IRQ_STATE_STOPPED: | 1387 | case QDIO_IRQ_STATE_STOPPED: |
1405 | case QDIO_IRQ_STATE_ERR: | 1388 | case QDIO_IRQ_STATE_ERR: |
1406 | mutex_unlock(&irq_ptr->setup_mutex); | 1389 | rc = -EIO; |
1407 | qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); | 1390 | break; |
1408 | return -EIO; | ||
1409 | default: | 1391 | default: |
1410 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ACTIVE); | 1392 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ACTIVE); |
1411 | rc = 0; | 1393 | rc = 0; |
@@ -1442,10 +1424,10 @@ static inline int buf_in_between(int bufnr, int start, int count) | |||
1442 | * @bufnr: first buffer to process | 1424 | * @bufnr: first buffer to process |
1443 | * @count: how many buffers are emptied | 1425 | * @count: how many buffers are emptied |
1444 | */ | 1426 | */ |
1445 | static void handle_inbound(struct qdio_q *q, unsigned int callflags, | 1427 | static int handle_inbound(struct qdio_q *q, unsigned int callflags, |
1446 | int bufnr, int count) | 1428 | int bufnr, int count) |
1447 | { | 1429 | { |
1448 | int used, cc, diff; | 1430 | int used, diff; |
1449 | 1431 | ||
1450 | if (!q->u.in.polling) | 1432 | if (!q->u.in.polling) |
1451 | goto set; | 1433 | goto set; |
@@ -1456,19 +1438,18 @@ static void handle_inbound(struct qdio_q *q, unsigned int callflags, | |||
1456 | q->u.in.polling = 0; | 1438 | q->u.in.polling = 0; |
1457 | q->u.in.ack_count = 0; | 1439 | q->u.in.ack_count = 0; |
1458 | goto set; | 1440 | goto set; |
1459 | } else if (buf_in_between(q->last_move_ftc, bufnr, count)) { | 1441 | } else if (buf_in_between(q->u.in.ack_start, bufnr, count)) { |
1460 | if (is_qebsm(q)) { | 1442 | if (is_qebsm(q)) { |
1461 | /* partial overwrite, just update last_move_ftc */ | 1443 | /* partial overwrite, just update ack_start */ |
1462 | diff = add_buf(bufnr, count); | 1444 | diff = add_buf(bufnr, count); |
1463 | diff = sub_buf(diff, q->last_move_ftc); | 1445 | diff = sub_buf(diff, q->u.in.ack_start); |
1464 | q->u.in.ack_count -= diff; | 1446 | q->u.in.ack_count -= diff; |
1465 | if (q->u.in.ack_count <= 0) { | 1447 | if (q->u.in.ack_count <= 0) { |
1466 | q->u.in.polling = 0; | 1448 | q->u.in.polling = 0; |
1467 | q->u.in.ack_count = 0; | 1449 | q->u.in.ack_count = 0; |
1468 | /* TODO: must we set last_move_ftc to something meaningful? */ | ||
1469 | goto set; | 1450 | goto set; |
1470 | } | 1451 | } |
1471 | q->last_move_ftc = add_buf(q->last_move_ftc, diff); | 1452 | q->u.in.ack_start = add_buf(q->u.in.ack_start, diff); |
1472 | } | 1453 | } |
1473 | else | 1454 | else |
1474 | /* the only ACK will be deleted, so stop polling */ | 1455 | /* the only ACK will be deleted, so stop polling */ |
@@ -1483,13 +1464,11 @@ set: | |||
1483 | 1464 | ||
1484 | /* no need to signal as long as the adapter had free buffers */ | 1465 | /* no need to signal as long as the adapter had free buffers */ |
1485 | if (used) | 1466 | if (used) |
1486 | return; | 1467 | return 0; |
1487 | 1468 | ||
1488 | if (need_siga_in(q)) { | 1469 | if (need_siga_in(q)) |
1489 | cc = qdio_siga_input(q); | 1470 | return qdio_siga_input(q); |
1490 | if (cc) | 1471 | return 0; |
1491 | q->qdio_error = cc; | ||
1492 | } | ||
1493 | } | 1472 | } |
1494 | 1473 | ||
1495 | /** | 1474 | /** |
@@ -1499,11 +1478,11 @@ set: | |||
1499 | * @bufnr: first buffer to process | 1478 | * @bufnr: first buffer to process |
1500 | * @count: how many buffers are filled | 1479 | * @count: how many buffers are filled |
1501 | */ | 1480 | */ |
1502 | static void handle_outbound(struct qdio_q *q, unsigned int callflags, | 1481 | static int handle_outbound(struct qdio_q *q, unsigned int callflags, |
1503 | int bufnr, int count) | 1482 | int bufnr, int count) |
1504 | { | 1483 | { |
1505 | unsigned char state; | 1484 | unsigned char state; |
1506 | int used; | 1485 | int used, rc = 0; |
1507 | 1486 | ||
1508 | qdio_perf_stat_inc(&perf_stats.outbound_handler); | 1487 | qdio_perf_stat_inc(&perf_stats.outbound_handler); |
1509 | 1488 | ||
@@ -1518,27 +1497,26 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1518 | 1497 | ||
1519 | if (queue_type(q) == QDIO_IQDIO_QFMT) { | 1498 | if (queue_type(q) == QDIO_IQDIO_QFMT) { |
1520 | if (multicast_outbound(q)) | 1499 | if (multicast_outbound(q)) |
1521 | qdio_kick_outbound_q(q); | 1500 | rc = qdio_kick_outbound_q(q); |
1522 | else | 1501 | else |
1523 | if ((q->irq_ptr->ssqd_desc.mmwc > 1) && | 1502 | if ((q->irq_ptr->ssqd_desc.mmwc > 1) && |
1524 | (count > 1) && | 1503 | (count > 1) && |
1525 | (count <= q->irq_ptr->ssqd_desc.mmwc)) { | 1504 | (count <= q->irq_ptr->ssqd_desc.mmwc)) { |
1526 | /* exploit enhanced SIGA */ | 1505 | /* exploit enhanced SIGA */ |
1527 | q->u.out.use_enh_siga = 1; | 1506 | q->u.out.use_enh_siga = 1; |
1528 | qdio_kick_outbound_q(q); | 1507 | rc = qdio_kick_outbound_q(q); |
1529 | } else { | 1508 | } else { |
1530 | /* | 1509 | /* |
1531 | * One siga-w per buffer required for unicast | 1510 | * One siga-w per buffer required for unicast |
1532 | * HiperSockets. | 1511 | * HiperSockets. |
1533 | */ | 1512 | */ |
1534 | q->u.out.use_enh_siga = 0; | 1513 | q->u.out.use_enh_siga = 0; |
1535 | while (count--) | 1514 | while (count--) { |
1536 | qdio_kick_outbound_q(q); | 1515 | rc = qdio_kick_outbound_q(q); |
1516 | if (rc) | ||
1517 | goto out; | ||
1518 | } | ||
1537 | } | 1519 | } |
1538 | |||
1539 | /* report CC=2 conditions synchronously */ | ||
1540 | if (q->qdio_error) | ||
1541 | __qdio_outbound_processing(q); | ||
1542 | goto out; | 1520 | goto out; |
1543 | } | 1521 | } |
1544 | 1522 | ||
@@ -1550,14 +1528,14 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1550 | /* try to fast requeue buffers */ | 1528 | /* try to fast requeue buffers */ |
1551 | get_buf_state(q, prev_buf(bufnr), &state, 0); | 1529 | get_buf_state(q, prev_buf(bufnr), &state, 0); |
1552 | if (state != SLSB_CU_OUTPUT_PRIMED) | 1530 | if (state != SLSB_CU_OUTPUT_PRIMED) |
1553 | qdio_kick_outbound_q(q); | 1531 | rc = qdio_kick_outbound_q(q); |
1554 | else { | 1532 | else { |
1555 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req"); | 1533 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req"); |
1556 | qdio_perf_stat_inc(&perf_stats.fast_requeue); | 1534 | qdio_perf_stat_inc(&perf_stats.fast_requeue); |
1557 | } | 1535 | } |
1558 | out: | 1536 | out: |
1559 | /* Fixme: could wait forever if called from process context */ | ||
1560 | tasklet_schedule(&q->tasklet); | 1537 | tasklet_schedule(&q->tasklet); |
1538 | return rc; | ||
1561 | } | 1539 | } |
1562 | 1540 | ||
1563 | /** | 1541 | /** |
@@ -1596,14 +1574,12 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1596 | return -EBUSY; | 1574 | return -EBUSY; |
1597 | 1575 | ||
1598 | if (callflags & QDIO_FLAG_SYNC_INPUT) | 1576 | if (callflags & QDIO_FLAG_SYNC_INPUT) |
1599 | handle_inbound(irq_ptr->input_qs[q_nr], callflags, bufnr, | 1577 | return handle_inbound(irq_ptr->input_qs[q_nr], |
1600 | count); | 1578 | callflags, bufnr, count); |
1601 | else if (callflags & QDIO_FLAG_SYNC_OUTPUT) | 1579 | else if (callflags & QDIO_FLAG_SYNC_OUTPUT) |
1602 | handle_outbound(irq_ptr->output_qs[q_nr], callflags, bufnr, | 1580 | return handle_outbound(irq_ptr->output_qs[q_nr], |
1603 | count); | 1581 | callflags, bufnr, count); |
1604 | else | 1582 | return -EINVAL; |
1605 | return -EINVAL; | ||
1606 | return 0; | ||
1607 | } | 1583 | } |
1608 | EXPORT_SYMBOL_GPL(do_QDIO); | 1584 | EXPORT_SYMBOL_GPL(do_QDIO); |
1609 | 1585 | ||
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index c08356b95bf5..18d54fc21ce9 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
@@ -117,7 +117,6 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, | |||
117 | q->mask = 1 << (31 - i); | 117 | q->mask = 1 << (31 - i); |
118 | q->nr = i; | 118 | q->nr = i; |
119 | q->handler = handler; | 119 | q->handler = handler; |
120 | spin_lock_init(&q->lock); | ||
121 | } | 120 | } |
122 | 121 | ||
123 | static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, | 122 | static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 8e90e147b746..c655d011a78d 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | /* list of thin interrupt input queues */ | 32 | /* list of thin interrupt input queues */ |
33 | static LIST_HEAD(tiq_list); | 33 | static LIST_HEAD(tiq_list); |
34 | DEFINE_MUTEX(tiq_list_lock); | ||
34 | 35 | ||
35 | /* adapter local summary indicator */ | 36 | /* adapter local summary indicator */ |
36 | static unsigned char *tiqdio_alsi; | 37 | static unsigned char *tiqdio_alsi; |
@@ -95,12 +96,11 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
95 | if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync) | 96 | if (!css_qdio_omit_svs && irq_ptr->siga_flag.sync) |
96 | css_qdio_omit_svs = 1; | 97 | css_qdio_omit_svs = 1; |
97 | 98 | ||
98 | for_each_input_queue(irq_ptr, q, i) { | 99 | mutex_lock(&tiq_list_lock); |
100 | for_each_input_queue(irq_ptr, q, i) | ||
99 | list_add_rcu(&q->entry, &tiq_list); | 101 | list_add_rcu(&q->entry, &tiq_list); |
100 | synchronize_rcu(); | 102 | mutex_unlock(&tiq_list_lock); |
101 | } | ||
102 | xchg(irq_ptr->dsci, 1); | 103 | xchg(irq_ptr->dsci, 1); |
103 | tasklet_schedule(&tiqdio_tasklet); | ||
104 | } | 104 | } |
105 | 105 | ||
106 | /* | 106 | /* |
@@ -118,7 +118,10 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | |||
118 | /* if establish triggered an error */ | 118 | /* if establish triggered an error */ |
119 | if (!q || !q->entry.prev || !q->entry.next) | 119 | if (!q || !q->entry.prev || !q->entry.next) |
120 | continue; | 120 | continue; |
121 | |||
122 | mutex_lock(&tiq_list_lock); | ||
121 | list_del_rcu(&q->entry); | 123 | list_del_rcu(&q->entry); |
124 | mutex_unlock(&tiq_list_lock); | ||
122 | synchronize_rcu(); | 125 | synchronize_rcu(); |
123 | } | 126 | } |
124 | } | 127 | } |
@@ -155,15 +158,15 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) | |||
155 | */ | 158 | */ |
156 | qdio_check_outbound_after_thinint(q); | 159 | qdio_check_outbound_after_thinint(q); |
157 | 160 | ||
158 | again: | ||
159 | if (!qdio_inbound_q_moved(q)) | 161 | if (!qdio_inbound_q_moved(q)) |
160 | return; | 162 | return; |
161 | 163 | ||
162 | qdio_kick_inbound_handler(q); | 164 | qdio_kick_handler(q); |
163 | 165 | ||
164 | if (!tiqdio_inbound_q_done(q)) { | 166 | if (!tiqdio_inbound_q_done(q)) { |
165 | qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); | 167 | qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); |
166 | goto again; | 168 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) |
169 | tasklet_schedule(&q->tasklet); | ||
167 | } | 170 | } |
168 | 171 | ||
169 | qdio_stop_polling(q); | 172 | qdio_stop_polling(q); |
@@ -173,7 +176,8 @@ again: | |||
173 | */ | 176 | */ |
174 | if (!tiqdio_inbound_q_done(q)) { | 177 | if (!tiqdio_inbound_q_done(q)) { |
175 | qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2); | 178 | qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2); |
176 | goto again; | 179 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) |
180 | tasklet_schedule(&q->tasklet); | ||
177 | } | 181 | } |
178 | } | 182 | } |
179 | 183 | ||
@@ -366,10 +370,11 @@ void qdio_shutdown_thinint(struct qdio_irq *irq_ptr) | |||
366 | 370 | ||
367 | void __exit tiqdio_unregister_thinints(void) | 371 | void __exit tiqdio_unregister_thinints(void) |
368 | { | 372 | { |
369 | tasklet_disable(&tiqdio_tasklet); | 373 | WARN_ON(!list_empty(&tiq_list)); |
370 | 374 | ||
371 | if (tiqdio_alsi) { | 375 | if (tiqdio_alsi) { |
372 | s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); | 376 | s390_unregister_adapter_interrupt(tiqdio_alsi, QDIO_AIRQ_ISC); |
373 | isc_unregister(QDIO_AIRQ_ISC); | 377 | isc_unregister(QDIO_AIRQ_ISC); |
374 | } | 378 | } |
379 | tasklet_kill(&tiqdio_tasklet); | ||
375 | } | 380 | } |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index cb22b97944b8..65b6a96afe6b 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -128,8 +128,7 @@ static void __zcrypt_increase_preference(struct zcrypt_device *zdev) | |||
128 | if (l == zdev->list.prev) | 128 | if (l == zdev->list.prev) |
129 | return; | 129 | return; |
130 | /* Move zdev behind l */ | 130 | /* Move zdev behind l */ |
131 | list_del(&zdev->list); | 131 | list_move(&zdev->list, l); |
132 | list_add(&zdev->list, l); | ||
133 | } | 132 | } |
134 | 133 | ||
135 | /** | 134 | /** |
@@ -157,8 +156,7 @@ static void __zcrypt_decrease_preference(struct zcrypt_device *zdev) | |||
157 | if (l == zdev->list.next) | 156 | if (l == zdev->list.next) |
158 | return; | 157 | return; |
159 | /* Move zdev before l */ | 158 | /* Move zdev before l */ |
160 | list_del(&zdev->list); | 159 | list_move_tail(&zdev->list, l); |
161 | list_add_tail(&zdev->list, l); | ||
162 | } | 160 | } |
163 | 161 | ||
164 | static void zcrypt_device_release(struct kref *kref) | 162 | static void zcrypt_device_release(struct kref *kref) |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index e7a1e22e77ac..c20d4790258e 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -781,8 +781,7 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, | |||
781 | /* Signal pending. */ | 781 | /* Signal pending. */ |
782 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 782 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
783 | out_free: | 783 | out_free: |
784 | memset(ap_msg.message, 0x0, ap_msg.length); | 784 | kzfree(ap_msg.message); |
785 | kfree(ap_msg.message); | ||
786 | return rc; | 785 | return rc; |
787 | } | 786 | } |
788 | 787 | ||
diff --git a/drivers/s390/ebcdic.c b/drivers/s390/ebcdic.c deleted file mode 100644 index 99c98da15473..000000000000 --- a/drivers/s390/ebcdic.c +++ /dev/null | |||
@@ -1,246 +0,0 @@ | |||
1 | /* | ||
2 | * arch/s390/kernel/ebcdic.c | ||
3 | * ECBDIC -> ASCII, ASCII -> ECBDIC conversion tables. | ||
4 | * | ||
5 | * S390 version | ||
6 | * Copyright (C) 1998 IBM Corporation | ||
7 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
8 | */ | ||
9 | |||
10 | #include <asm/types.h> | ||
11 | |||
12 | /* | ||
13 | * ASCII -> EBCDIC | ||
14 | */ | ||
15 | __u8 _ascebc[256] = | ||
16 | { | ||
17 | /*00 NL SH SX EX ET NQ AK BL */ | ||
18 | 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, | ||
19 | /*08 BS HT LF VT FF CR SO SI */ | ||
20 | 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | ||
21 | /*10 DL D1 D2 D3 D4 NK SN EB */ | ||
22 | 0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26, | ||
23 | /*18 CN EM SB EC FS GS RS US */ | ||
24 | 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, | ||
25 | /*20 SP ! " # $ % & ' */ | ||
26 | 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, | ||
27 | /*28 ( ) * + , - . / */ | ||
28 | 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, | ||
29 | /*30 0 1 2 3 4 5 6 7 */ | ||
30 | 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, | ||
31 | /*38 8 9 : ; < = > ? */ | ||
32 | 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, | ||
33 | /*40 @ A B C D E F G */ | ||
34 | 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, | ||
35 | /*48 H I J K L M N O */ | ||
36 | 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, | ||
37 | /*50 P Q R S T U V W */ | ||
38 | 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, | ||
39 | /*58 X Y Z [ \ ] ^ _ */ | ||
40 | 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, | ||
41 | /*60 ` a b c d e f g */ | ||
42 | 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | ||
43 | /*68 h i j k l m n o */ | ||
44 | 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, | ||
45 | /*70 p q r s t u v w */ | ||
46 | 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, | ||
47 | /*78 x y z { | } ~ DL */ | ||
48 | 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, | ||
49 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
50 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
51 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
52 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
53 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
54 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
55 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
56 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
57 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
58 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
59 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
60 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
61 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
62 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
63 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, | ||
64 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * EBCDIC -> ASCII | ||
69 | */ | ||
70 | __u8 _ebcasc[256] = | ||
71 | { | ||
72 | /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ | ||
73 | 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, | ||
74 | /* 0x08 -GE -SPS -RPT VT FF CR SO SI */ | ||
75 | 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | ||
76 | /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC | ||
77 | -ENP ->LF */ | ||
78 | 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, | ||
79 | /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB | ||
80 | -IUS */ | ||
81 | 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
82 | /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC | ||
83 | -INP */ | ||
84 | 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, | ||
85 | /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL | ||
86 | -SW */ | ||
87 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, | ||
88 | /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ | ||
89 | 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, | ||
90 | /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ | ||
91 | 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, | ||
92 | /* 0x40 SP RSP ä ---- */ | ||
93 | 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, | ||
94 | /* 0x48 . < ( + | */ | ||
95 | 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, | ||
96 | /* 0x50 & ---- */ | ||
97 | 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, | ||
98 | /* 0x58 ß ! $ * ) ; */ | ||
99 | 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, | ||
100 | /* 0x60 - / ---- Ä ---- ---- ---- */ | ||
101 | 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, | ||
102 | /* 0x68 ---- , % _ > ? */ | ||
103 | 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, | ||
104 | /* 0x70 ---- ---- ---- ---- ---- ---- ---- */ | ||
105 | 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
106 | /* 0x78 * ` : # @ ' = " */ | ||
107 | 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, | ||
108 | /* 0x80 * a b c d e f g */ | ||
109 | 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | ||
110 | /* 0x88 h i ---- ---- ---- */ | ||
111 | 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, | ||
112 | /* 0x90 ° j k l m n o p */ | ||
113 | 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, | ||
114 | /* 0x98 q r ---- ---- */ | ||
115 | 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, | ||
116 | /* 0xA0 ~ s t u v w x */ | ||
117 | 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | ||
118 | /* 0xA8 y z ---- ---- ---- ---- */ | ||
119 | 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, | ||
120 | /* 0xB0 ^ ---- § ---- */ | ||
121 | 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, | ||
122 | /* 0xB8 ---- [ ] ---- ---- ---- ---- */ | ||
123 | 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, | ||
124 | /* 0xC0 { A B C D E F G */ | ||
125 | 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, | ||
126 | /* 0xC8 H I ---- ö ---- */ | ||
127 | 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, | ||
128 | /* 0xD0 } J K L M N O P */ | ||
129 | 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, | ||
130 | /* 0xD8 Q R ---- ü */ | ||
131 | 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, | ||
132 | /* 0xE0 \ S T U V W X */ | ||
133 | 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | ||
134 | /* 0xE8 Y Z ---- Ö ---- ---- ---- */ | ||
135 | 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, | ||
136 | /* 0xF0 0 1 2 3 4 5 6 7 */ | ||
137 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | ||
138 | /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ | ||
139 | 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 | ||
140 | }; | ||
141 | |||
142 | /* | ||
143 | * EBCDIC (capitals) -> ASCII (small case) | ||
144 | */ | ||
145 | __u8 _ebcasc_reduce_case[256] = | ||
146 | { | ||
147 | /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ | ||
148 | 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, | ||
149 | |||
150 | /* 0x08 -GE -SPS -RPT VT FF CR SO SI */ | ||
151 | 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | ||
152 | |||
153 | /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC | ||
154 | -ENP ->LF */ | ||
155 | 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, | ||
156 | |||
157 | /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB | ||
158 | -IUS */ | ||
159 | 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
160 | |||
161 | /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC | ||
162 | -INP */ | ||
163 | 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, | ||
164 | |||
165 | /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL | ||
166 | -SW */ | ||
167 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, | ||
168 | |||
169 | /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ | ||
170 | 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, | ||
171 | |||
172 | /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ | ||
173 | 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, | ||
174 | |||
175 | /* 0x40 SP RSP ä ---- */ | ||
176 | 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, | ||
177 | |||
178 | /* 0x48 . < ( + | */ | ||
179 | 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, | ||
180 | |||
181 | /* 0x50 & ---- */ | ||
182 | 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, | ||
183 | |||
184 | /* 0x58 ß ! $ * ) ; */ | ||
185 | 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, | ||
186 | |||
187 | /* 0x60 - / ---- Ä ---- ---- ---- */ | ||
188 | 0x2D, 0x2F, 0x07, 0x84, 0x07, 0x07, 0x07, 0x8F, | ||
189 | |||
190 | /* 0x68 ---- , % _ > ? */ | ||
191 | 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, | ||
192 | |||
193 | /* 0x70 ---- ---- ---- ---- ---- ---- ---- */ | ||
194 | 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
195 | |||
196 | /* 0x78 * ` : # @ ' = " */ | ||
197 | 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, | ||
198 | |||
199 | /* 0x80 * a b c d e f g */ | ||
200 | 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | ||
201 | |||
202 | /* 0x88 h i ---- ---- ---- */ | ||
203 | 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, | ||
204 | |||
205 | /* 0x90 ° j k l m n o p */ | ||
206 | 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, | ||
207 | |||
208 | /* 0x98 q r ---- ---- */ | ||
209 | 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, | ||
210 | |||
211 | /* 0xA0 ~ s t u v w x */ | ||
212 | 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | ||
213 | |||
214 | /* 0xA8 y z ---- ---- ---- ---- */ | ||
215 | 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, | ||
216 | |||
217 | /* 0xB0 ^ ---- § ---- */ | ||
218 | 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, | ||
219 | |||
220 | /* 0xB8 ---- [ ] ---- ---- ---- ---- */ | ||
221 | 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07, | ||
222 | |||
223 | /* 0xC0 { A B C D E F G */ | ||
224 | 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | ||
225 | |||
226 | /* 0xC8 H I ---- ö ---- */ | ||
227 | 0x68, 0x69, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, | ||
228 | |||
229 | /* 0xD0 } J K L M N O P */ | ||
230 | 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, | ||
231 | |||
232 | /* 0xD8 Q R ---- ü */ | ||
233 | 0x71, 0x72, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, | ||
234 | |||
235 | /* 0xE0 \ S T U V W X */ | ||
236 | 0x5C, 0xF6, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | ||
237 | |||
238 | /* 0xE8 Y Z ---- Ö ---- ---- ---- */ | ||
239 | 0x79, 0x7A, 0xFD, 0x07, 0x94, 0x07, 0x07, 0x07, | ||
240 | |||
241 | /* 0xF0 0 1 2 3 4 5 6 7 */ | ||
242 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | ||
243 | |||
244 | /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ | ||
245 | 0x38, 0x39, 0x07, 0x07, 0x81, 0x07, 0x07, 0x07 | ||
246 | }; | ||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6fec3cfcf978..c827d69b5a91 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -2680,40 +2680,21 @@ static int qeth_handle_send_error(struct qeth_card *card, | |||
2680 | struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) | 2680 | struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err) |
2681 | { | 2681 | { |
2682 | int sbalf15 = buffer->buffer->element[15].flags & 0xff; | 2682 | int sbalf15 = buffer->buffer->element[15].flags & 0xff; |
2683 | int cc = qdio_err & 3; | ||
2684 | 2683 | ||
2685 | QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); | 2684 | QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); |
2686 | qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); | 2685 | qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); |
2687 | switch (cc) { | 2686 | |
2688 | case 0: | 2687 | if (!qdio_err) |
2689 | if (qdio_err) { | ||
2690 | QETH_DBF_TEXT(TRACE, 1, "lnkfail"); | ||
2691 | QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); | ||
2692 | QETH_DBF_TEXT_(TRACE, 1, "%04x %02x", | ||
2693 | (u16)qdio_err, (u8)sbalf15); | ||
2694 | return QETH_SEND_ERROR_LINK_FAILURE; | ||
2695 | } | ||
2696 | return QETH_SEND_ERROR_NONE; | 2688 | return QETH_SEND_ERROR_NONE; |
2697 | case 2: | 2689 | |
2698 | if (qdio_err & QDIO_ERROR_SIGA_BUSY) { | 2690 | if ((sbalf15 >= 15) && (sbalf15 <= 31)) |
2699 | QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B"); | 2691 | return QETH_SEND_ERROR_RETRY; |
2700 | QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); | 2692 | |
2701 | return QETH_SEND_ERROR_KICK_IT; | 2693 | QETH_DBF_TEXT(TRACE, 1, "lnkfail"); |
2702 | } | 2694 | QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); |
2703 | if ((sbalf15 >= 15) && (sbalf15 <= 31)) | 2695 | QETH_DBF_TEXT_(TRACE, 1, "%04x %02x", |
2704 | return QETH_SEND_ERROR_RETRY; | 2696 | (u16)qdio_err, (u8)sbalf15); |
2705 | return QETH_SEND_ERROR_LINK_FAILURE; | 2697 | return QETH_SEND_ERROR_LINK_FAILURE; |
2706 | /* look at qdio_error and sbalf 15 */ | ||
2707 | case 1: | ||
2708 | QETH_DBF_TEXT(TRACE, 1, "SIGAcc1"); | ||
2709 | QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); | ||
2710 | return QETH_SEND_ERROR_LINK_FAILURE; | ||
2711 | case 3: | ||
2712 | default: | ||
2713 | QETH_DBF_TEXT(TRACE, 1, "SIGAcc3"); | ||
2714 | QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card)); | ||
2715 | return QETH_SEND_ERROR_KICK_IT; | ||
2716 | } | ||
2717 | } | 2698 | } |
2718 | 2699 | ||
2719 | /* | 2700 | /* |
@@ -2849,10 +2830,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
2849 | qeth_get_micros() - | 2830 | qeth_get_micros() - |
2850 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2831 | queue->card->perf_stats.outbound_do_qdio_start_time; |
2851 | if (rc) { | 2832 | if (rc) { |
2833 | queue->card->stats.tx_errors += count; | ||
2834 | /* ignore temporary SIGA errors without busy condition */ | ||
2835 | if (rc == QDIO_ERROR_SIGA_TARGET) | ||
2836 | return; | ||
2852 | QETH_DBF_TEXT(TRACE, 2, "flushbuf"); | 2837 | QETH_DBF_TEXT(TRACE, 2, "flushbuf"); |
2853 | QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); | 2838 | QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); |
2854 | QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card)); | 2839 | QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card)); |
2855 | queue->card->stats.tx_errors += count; | 2840 | |
2856 | /* this must not happen under normal circumstances. if it | 2841 | /* this must not happen under normal circumstances. if it |
2857 | * happens something is really wrong -> recover */ | 2842 | * happens something is really wrong -> recover */ |
2858 | qeth_schedule_recovery(queue->card); | 2843 | qeth_schedule_recovery(queue->card); |
@@ -2927,13 +2912,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
2927 | } | 2912 | } |
2928 | for (i = first_element; i < (first_element + count); ++i) { | 2913 | for (i = first_element; i < (first_element + count); ++i) { |
2929 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 2914 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
2930 | /*we only handle the KICK_IT error by doing a recovery */ | 2915 | qeth_handle_send_error(card, buffer, qdio_error); |
2931 | if (qeth_handle_send_error(card, buffer, qdio_error) | ||
2932 | == QETH_SEND_ERROR_KICK_IT){ | ||
2933 | netif_stop_queue(card->dev); | ||
2934 | qeth_schedule_recovery(card); | ||
2935 | return; | ||
2936 | } | ||
2937 | qeth_clear_output_buffer(queue, buffer); | 2916 | qeth_clear_output_buffer(queue, buffer); |
2938 | } | 2917 | } |
2939 | atomic_sub(count, &queue->used_buffers); | 2918 | atomic_sub(count, &queue->used_buffers); |
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h deleted file mode 100644 index d39f8b697d27..000000000000 --- a/drivers/s390/s390mach.h +++ /dev/null | |||
@@ -1,122 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/s390/s390mach.h | ||
3 | * S/390 data definitions for machine check processing | ||
4 | * | ||
5 | * S390 version | ||
6 | * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
7 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | ||
8 | */ | ||
9 | |||
10 | #ifndef __s390mach_h | ||
11 | #define __s390mach_h | ||
12 | |||
13 | #include <asm/types.h> | ||
14 | |||
15 | struct mci { | ||
16 | __u32 sd : 1; /* 00 system damage */ | ||
17 | __u32 pd : 1; /* 01 instruction-processing damage */ | ||
18 | __u32 sr : 1; /* 02 system recovery */ | ||
19 | __u32 to_be_defined_1 : 1; /* 03 */ | ||
20 | __u32 cd : 1; /* 04 timing-facility damage */ | ||
21 | __u32 ed : 1; /* 05 external damage */ | ||
22 | __u32 to_be_defined_2 : 1; /* 06 */ | ||
23 | __u32 dg : 1; /* 07 degradation */ | ||
24 | __u32 w : 1; /* 08 warning pending */ | ||
25 | __u32 cp : 1; /* 09 channel-report pending */ | ||
26 | __u32 sp : 1; /* 10 service-processor damage */ | ||
27 | __u32 ck : 1; /* 11 channel-subsystem damage */ | ||
28 | __u32 to_be_defined_3 : 2; /* 12-13 */ | ||
29 | __u32 b : 1; /* 14 backed up */ | ||
30 | __u32 to_be_defined_4 : 1; /* 15 */ | ||
31 | __u32 se : 1; /* 16 storage error uncorrected */ | ||
32 | __u32 sc : 1; /* 17 storage error corrected */ | ||
33 | __u32 ke : 1; /* 18 storage-key error uncorrected */ | ||
34 | __u32 ds : 1; /* 19 storage degradation */ | ||
35 | __u32 wp : 1; /* 20 psw mwp validity */ | ||
36 | __u32 ms : 1; /* 21 psw mask and key validity */ | ||
37 | __u32 pm : 1; /* 22 psw program mask and cc validity */ | ||
38 | __u32 ia : 1; /* 23 psw instruction address validity */ | ||
39 | __u32 fa : 1; /* 24 failing storage address validity */ | ||
40 | __u32 to_be_defined_5 : 1; /* 25 */ | ||
41 | __u32 ec : 1; /* 26 external damage code validity */ | ||
42 | __u32 fp : 1; /* 27 floating point register validity */ | ||
43 | __u32 gr : 1; /* 28 general register validity */ | ||
44 | __u32 cr : 1; /* 29 control register validity */ | ||
45 | __u32 to_be_defined_6 : 1; /* 30 */ | ||
46 | __u32 st : 1; /* 31 storage logical validity */ | ||
47 | __u32 ie : 1; /* 32 indirect storage error */ | ||
48 | __u32 ar : 1; /* 33 access register validity */ | ||
49 | __u32 da : 1; /* 34 delayed access exception */ | ||
50 | __u32 to_be_defined_7 : 7; /* 35-41 */ | ||
51 | __u32 pr : 1; /* 42 tod programmable register validity */ | ||
52 | __u32 fc : 1; /* 43 fp control register validity */ | ||
53 | __u32 ap : 1; /* 44 ancillary report */ | ||
54 | __u32 to_be_defined_8 : 1; /* 45 */ | ||
55 | __u32 ct : 1; /* 46 cpu timer validity */ | ||
56 | __u32 cc : 1; /* 47 clock comparator validity */ | ||
57 | __u32 to_be_defined_9 : 16; /* 47-63 */ | ||
58 | }; | ||
59 | |||
60 | /* | ||
61 | * Channel Report Word | ||
62 | */ | ||
63 | struct crw { | ||
64 | __u32 res1 : 1; /* reserved zero */ | ||
65 | __u32 slct : 1; /* solicited */ | ||
66 | __u32 oflw : 1; /* overflow */ | ||
67 | __u32 chn : 1; /* chained */ | ||
68 | __u32 rsc : 4; /* reporting source code */ | ||
69 | __u32 anc : 1; /* ancillary report */ | ||
70 | __u32 res2 : 1; /* reserved zero */ | ||
71 | __u32 erc : 6; /* error-recovery code */ | ||
72 | __u32 rsid : 16; /* reporting-source ID */ | ||
73 | } __attribute__ ((packed)); | ||
74 | |||
75 | typedef void (*crw_handler_t)(struct crw *, struct crw *, int); | ||
76 | |||
77 | extern int s390_register_crw_handler(int rsc, crw_handler_t handler); | ||
78 | extern void s390_unregister_crw_handler(int rsc); | ||
79 | |||
80 | #define NR_RSCS 16 | ||
81 | |||
82 | #define CRW_RSC_MONITOR 0x2 /* monitoring facility */ | ||
83 | #define CRW_RSC_SCH 0x3 /* subchannel */ | ||
84 | #define CRW_RSC_CPATH 0x4 /* channel path */ | ||
85 | #define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */ | ||
86 | #define CRW_RSC_CSS 0xB /* channel subsystem */ | ||
87 | |||
88 | #define CRW_ERC_EVENT 0x00 /* event information pending */ | ||
89 | #define CRW_ERC_AVAIL 0x01 /* available */ | ||
90 | #define CRW_ERC_INIT 0x02 /* initialized */ | ||
91 | #define CRW_ERC_TERROR 0x03 /* temporary error */ | ||
92 | #define CRW_ERC_IPARM 0x04 /* installed parm initialized */ | ||
93 | #define CRW_ERC_TERM 0x05 /* terminal */ | ||
94 | #define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */ | ||
95 | #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ | ||
96 | #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ | ||
97 | |||
98 | static inline int stcrw(struct crw *pcrw ) | ||
99 | { | ||
100 | int ccode; | ||
101 | |||
102 | __asm__ __volatile__( | ||
103 | "stcrw 0(%2)\n\t" | ||
104 | "ipm %0\n\t" | ||
105 | "srl %0,28\n\t" | ||
106 | : "=d" (ccode), "=m" (*pcrw) | ||
107 | : "a" (pcrw) | ||
108 | : "cc" ); | ||
109 | return ccode; | ||
110 | } | ||
111 | |||
112 | #define ED_ETR_SYNC 12 /* External damage ETR sync check */ | ||
113 | #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ | ||
114 | |||
115 | #define ED_STP_SYNC 7 /* External damage STP sync check */ | ||
116 | #define ED_STP_ISLAND 6 /* External damage STP island check */ | ||
117 | |||
118 | struct pt_regs; | ||
119 | |||
120 | void s390_handle_mcck(void); | ||
121 | void s390_do_machine_check(struct pt_regs *regs); | ||
122 | #endif /* __s390mach */ | ||
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 1e064c4a4f86..46297683cd34 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c | |||
@@ -21,20 +21,38 @@ | |||
21 | * compute the block number from a | 21 | * compute the block number from a |
22 | * cyl-cyl-head-head structure | 22 | * cyl-cyl-head-head structure |
23 | */ | 23 | */ |
24 | static inline int | 24 | static sector_t |
25 | cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { | 25 | cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { |
26 | return ptr->cc * geo->heads * geo->sectors + | 26 | |
27 | ptr->hh * geo->sectors; | 27 | sector_t cyl; |
28 | __u16 head; | ||
29 | |||
30 | /*decode cylinder and heads for large volumes */ | ||
31 | cyl = ptr->hh & 0xFFF0; | ||
32 | cyl <<= 12; | ||
33 | cyl |= ptr->cc; | ||
34 | head = ptr->hh & 0x000F; | ||
35 | return cyl * geo->heads * geo->sectors + | ||
36 | head * geo->sectors; | ||
28 | } | 37 | } |
29 | 38 | ||
30 | /* | 39 | /* |
31 | * compute the block number from a | 40 | * compute the block number from a |
32 | * cyl-cyl-head-head-block structure | 41 | * cyl-cyl-head-head-block structure |
33 | */ | 42 | */ |
34 | static inline int | 43 | static sector_t |
35 | cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | 44 | cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { |
36 | return ptr->cc * geo->heads * geo->sectors + | 45 | |
37 | ptr->hh * geo->sectors + | 46 | sector_t cyl; |
47 | __u16 head; | ||
48 | |||
49 | /*decode cylinder and heads for large volumes */ | ||
50 | cyl = ptr->hh & 0xFFF0; | ||
51 | cyl <<= 12; | ||
52 | cyl |= ptr->cc; | ||
53 | head = ptr->hh & 0x000F; | ||
54 | return cyl * geo->heads * geo->sectors + | ||
55 | head * geo->sectors + | ||
38 | ptr->b; | 56 | ptr->b; |
39 | } | 57 | } |
40 | 58 | ||
@@ -43,14 +61,15 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { | |||
43 | int | 61 | int |
44 | ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | 62 | ibm_partition(struct parsed_partitions *state, struct block_device *bdev) |
45 | { | 63 | { |
46 | int blocksize, offset, size,res; | 64 | int blocksize, res; |
47 | loff_t i_size; | 65 | loff_t i_size, offset, size, fmt_size; |
48 | dasd_information2_t *info; | 66 | dasd_information2_t *info; |
49 | struct hd_geometry *geo; | 67 | struct hd_geometry *geo; |
50 | char type[5] = {0,}; | 68 | char type[5] = {0,}; |
51 | char name[7] = {0,}; | 69 | char name[7] = {0,}; |
52 | union label_t { | 70 | union label_t { |
53 | struct vtoc_volume_label vol; | 71 | struct vtoc_volume_label_cdl vol; |
72 | struct vtoc_volume_label_ldl lnx; | ||
54 | struct vtoc_cms_label cms; | 73 | struct vtoc_cms_label cms; |
55 | } *label; | 74 | } *label; |
56 | unsigned char *data; | 75 | unsigned char *data; |
@@ -85,14 +104,16 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
85 | if (data == NULL) | 104 | if (data == NULL) |
86 | goto out_readerr; | 105 | goto out_readerr; |
87 | 106 | ||
88 | strncpy (type, data, 4); | ||
89 | if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) | ||
90 | strncpy(name, data + 8, 6); | ||
91 | else | ||
92 | strncpy(name, data + 4, 6); | ||
93 | memcpy(label, data, sizeof(union label_t)); | 107 | memcpy(label, data, sizeof(union label_t)); |
94 | put_dev_sector(sect); | 108 | put_dev_sector(sect); |
95 | 109 | ||
110 | if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { | ||
111 | strncpy(type, label->vol.vollbl, 4); | ||
112 | strncpy(name, label->vol.volid, 6); | ||
113 | } else { | ||
114 | strncpy(type, label->lnx.vollbl, 4); | ||
115 | strncpy(name, label->lnx.volid, 6); | ||
116 | } | ||
96 | EBCASC(type, 4); | 117 | EBCASC(type, 4); |
97 | EBCASC(name, 6); | 118 | EBCASC(name, 6); |
98 | 119 | ||
@@ -110,36 +131,54 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
110 | /* | 131 | /* |
111 | * VM style CMS1 labeled disk | 132 | * VM style CMS1 labeled disk |
112 | */ | 133 | */ |
134 | blocksize = label->cms.block_size; | ||
113 | if (label->cms.disk_offset != 0) { | 135 | if (label->cms.disk_offset != 0) { |
114 | printk("CMS1/%8s(MDSK):", name); | 136 | printk("CMS1/%8s(MDSK):", name); |
115 | /* disk is reserved minidisk */ | 137 | /* disk is reserved minidisk */ |
116 | blocksize = label->cms.block_size; | ||
117 | offset = label->cms.disk_offset; | 138 | offset = label->cms.disk_offset; |
118 | size = (label->cms.block_count - 1) | 139 | size = (label->cms.block_count - 1) |
119 | * (blocksize >> 9); | 140 | * (blocksize >> 9); |
120 | } else { | 141 | } else { |
121 | printk("CMS1/%8s:", name); | 142 | printk("CMS1/%8s:", name); |
122 | offset = (info->label_block + 1); | 143 | offset = (info->label_block + 1); |
123 | size = i_size >> 9; | 144 | size = label->cms.block_count |
145 | * (blocksize >> 9); | ||
124 | } | 146 | } |
147 | put_partition(state, 1, offset*(blocksize >> 9), | ||
148 | size-offset*(blocksize >> 9)); | ||
125 | } else { | 149 | } else { |
126 | /* | 150 | if (strncmp(type, "LNX1", 4) == 0) { |
127 | * Old style LNX1 or unlabeled disk | 151 | printk("LNX1/%8s:", name); |
128 | */ | 152 | if (label->lnx.ldl_version == 0xf2) { |
129 | if (strncmp(type, "LNX1", 4) == 0) | 153 | fmt_size = label->lnx.formatted_blocks |
130 | printk ("LNX1/%8s:", name); | 154 | * (blocksize >> 9); |
131 | else | 155 | } else if (!strcmp(info->type, "ECKD")) { |
156 | /* formated w/o large volume support */ | ||
157 | fmt_size = geo->cylinders * geo->heads | ||
158 | * geo->sectors * (blocksize >> 9); | ||
159 | } else { | ||
160 | /* old label and no usable disk geometry | ||
161 | * (e.g. DIAG) */ | ||
162 | fmt_size = i_size >> 9; | ||
163 | } | ||
164 | size = i_size >> 9; | ||
165 | if (fmt_size < size) | ||
166 | size = fmt_size; | ||
167 | offset = (info->label_block + 1); | ||
168 | } else { | ||
169 | /* unlabeled disk */ | ||
132 | printk("(nonl)"); | 170 | printk("(nonl)"); |
133 | offset = (info->label_block + 1); | 171 | size = i_size >> 9; |
134 | size = i_size >> 9; | 172 | offset = (info->label_block + 1); |
135 | } | 173 | } |
136 | put_partition(state, 1, offset*(blocksize >> 9), | 174 | put_partition(state, 1, offset*(blocksize >> 9), |
137 | size-offset*(blocksize >> 9)); | 175 | size-offset*(blocksize >> 9)); |
176 | } | ||
138 | } else if (info->format == DASD_FORMAT_CDL) { | 177 | } else if (info->format == DASD_FORMAT_CDL) { |
139 | /* | 178 | /* |
140 | * New style CDL formatted disk | 179 | * New style CDL formatted disk |
141 | */ | 180 | */ |
142 | unsigned int blk; | 181 | sector_t blk; |
143 | int counter; | 182 | int counter; |
144 | 183 | ||
145 | /* | 184 | /* |
@@ -166,7 +205,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
166 | /* skip FMT4 / FMT5 / FMT7 labels */ | 205 | /* skip FMT4 / FMT5 / FMT7 labels */ |
167 | if (f1.DS1FMTID == _ascebc['4'] | 206 | if (f1.DS1FMTID == _ascebc['4'] |
168 | || f1.DS1FMTID == _ascebc['5'] | 207 | || f1.DS1FMTID == _ascebc['5'] |
169 | || f1.DS1FMTID == _ascebc['7']) { | 208 | || f1.DS1FMTID == _ascebc['7'] |
209 | || f1.DS1FMTID == _ascebc['9']) { | ||
170 | blk++; | 210 | blk++; |
171 | data = read_dev_sector(bdev, blk * | 211 | data = read_dev_sector(bdev, blk * |
172 | (blocksize/512), | 212 | (blocksize/512), |
@@ -174,8 +214,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
174 | continue; | 214 | continue; |
175 | } | 215 | } |
176 | 216 | ||
177 | /* only FMT1 valid at this point */ | 217 | /* only FMT1 and 8 labels valid at this point */ |
178 | if (f1.DS1FMTID != _ascebc['1']) | 218 | if (f1.DS1FMTID != _ascebc['1'] && |
219 | f1.DS1FMTID != _ascebc['8']) | ||
179 | break; | 220 | break; |
180 | 221 | ||
181 | /* OK, we got valid partition data */ | 222 | /* OK, we got valid partition data */ |