diff options
31 files changed, 459 insertions, 348 deletions
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index 2775d2618332..95f5160df27f 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #define CRYPT_S390_PRIORITY 300 | 24 | #define CRYPT_S390_PRIORITY 300 |
25 | #define CRYPT_S390_COMPOSITE_PRIORITY 400 | 25 | #define CRYPT_S390_COMPOSITE_PRIORITY 400 |
26 | 26 | ||
27 | /* s930 cryptographic operations */ | 27 | /* s390 cryptographic operations */ |
28 | enum crypt_s390_operations { | 28 | enum crypt_s390_operations { |
29 | CRYPT_S390_KM = 0x0100, | 29 | CRYPT_S390_KM = 0x0100, |
30 | CRYPT_S390_KMC = 0x0200, | 30 | CRYPT_S390_KMC = 0x0200, |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 50538e545618..e6289ee74ecd 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -171,37 +171,6 @@ static inline int memory_fast_detect(void) | |||
171 | } | 171 | } |
172 | #endif | 172 | #endif |
173 | 173 | ||
174 | #define ADDR2G (1UL << 31) | ||
175 | |||
176 | static noinline __init unsigned long sclp_memory_detect(void) | ||
177 | { | ||
178 | struct sclp_readinfo_sccb *sccb; | ||
179 | unsigned long long memsize; | ||
180 | |||
181 | sccb = &s390_readinfo_sccb; | ||
182 | |||
183 | if (sccb->header.response_code != 0x10) | ||
184 | return 0; | ||
185 | |||
186 | if (sccb->rnsize) | ||
187 | memsize = sccb->rnsize << 20; | ||
188 | else | ||
189 | memsize = sccb->rnsize2 << 20; | ||
190 | if (sccb->rnmax) | ||
191 | memsize *= sccb->rnmax; | ||
192 | else | ||
193 | memsize *= sccb->rnmax2; | ||
194 | #ifndef CONFIG_64BIT | ||
195 | /* | ||
196 | * Can't deal with more than 2G in 31 bit addressing mode, so | ||
197 | * limit the value in order to avoid strange side effects. | ||
198 | */ | ||
199 | if (memsize > ADDR2G) | ||
200 | memsize = ADDR2G; | ||
201 | #endif | ||
202 | return (unsigned long) memsize; | ||
203 | } | ||
204 | |||
205 | static inline __init unsigned long __tprot(unsigned long addr) | 174 | static inline __init unsigned long __tprot(unsigned long addr) |
206 | { | 175 | { |
207 | int cc = -1; | 176 | int cc = -1; |
@@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr) | |||
218 | 187 | ||
219 | /* Checking memory in 128KB increments. */ | 188 | /* Checking memory in 128KB increments. */ |
220 | #define CHUNK_INCR (1UL << 17) | 189 | #define CHUNK_INCR (1UL << 17) |
190 | #define ADDR2G (1UL << 31) | ||
221 | 191 | ||
222 | static noinline __init void find_memory_chunks(unsigned long memsize) | 192 | static noinline __init void find_memory_chunks(unsigned long memsize) |
223 | { | 193 | { |
@@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void) | |||
293 | */ | 263 | */ |
294 | void __init startup_init(void) | 264 | void __init startup_init(void) |
295 | { | 265 | { |
296 | unsigned long memsize; | 266 | unsigned long long memsize; |
297 | 267 | ||
298 | ipl_save_parameters(); | 268 | ipl_save_parameters(); |
299 | clear_bss_section(); | 269 | clear_bss_section(); |
@@ -305,8 +275,17 @@ void __init startup_init(void) | |||
305 | sort_main_extable(); | 275 | sort_main_extable(); |
306 | setup_lowcore_early(); | 276 | setup_lowcore_early(); |
307 | sclp_readinfo_early(); | 277 | sclp_readinfo_early(); |
278 | sclp_facilities_detect(); | ||
308 | memsize = sclp_memory_detect(); | 279 | memsize = sclp_memory_detect(); |
280 | #ifndef CONFIG_64BIT | ||
281 | /* | ||
282 | * Can't deal with more than 2G in 31 bit addressing mode, so | ||
283 | * limit the value in order to avoid strange side effects. | ||
284 | */ | ||
285 | if (memsize > ADDR2G) | ||
286 | memsize = ADDR2G; | ||
287 | #endif | ||
309 | if (memory_fast_detect() < 0) | 288 | if (memory_fast_detect() < 0) |
310 | find_memory_chunks(memsize); | 289 | find_memory_chunks((unsigned long) memsize); |
311 | lockdep_on(); | 290 | lockdep_on(); |
312 | } | 291 | } |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 6234c6978a1f..bc7ff3658c3d 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -107,6 +107,11 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
107 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 | 107 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 |
108 | .endm | 108 | .endm |
109 | 109 | ||
110 | .macro SAVE_ALL_SVC psworg,savearea | ||
111 | la %r12,\psworg | ||
112 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp | ||
113 | .endm | ||
114 | |||
110 | .macro SAVE_ALL_SYNC psworg,savearea | 115 | .macro SAVE_ALL_SYNC psworg,savearea |
111 | la %r12,\psworg | 116 | la %r12,\psworg |
112 | tm \psworg+1,0x01 # test problem state bit | 117 | tm \psworg+1,0x01 # test problem state bit |
@@ -218,7 +223,7 @@ system_call: | |||
218 | STORE_TIMER __LC_SYNC_ENTER_TIMER | 223 | STORE_TIMER __LC_SYNC_ENTER_TIMER |
219 | sysc_saveall: | 224 | sysc_saveall: |
220 | SAVE_ALL_BASE __LC_SAVE_AREA | 225 | SAVE_ALL_BASE __LC_SAVE_AREA |
221 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 226 | SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
222 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 227 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
223 | lh %r7,0x8a # get svc number from lowcore | 228 | lh %r7,0x8a # get svc number from lowcore |
224 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 229 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 685f11faa4bc..2a7b1304418b 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -99,6 +99,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ | |||
99 | larl %r13,system_call | 99 | larl %r13,system_call |
100 | .endm | 100 | .endm |
101 | 101 | ||
102 | .macro SAVE_ALL_SVC psworg,savearea | ||
103 | la %r12,\psworg | ||
104 | lg %r15,__LC_KERNEL_STACK # problem state -> load ksp | ||
105 | .endm | ||
106 | |||
102 | .macro SAVE_ALL_SYNC psworg,savearea | 107 | .macro SAVE_ALL_SYNC psworg,savearea |
103 | la %r12,\psworg | 108 | la %r12,\psworg |
104 | tm \psworg+1,0x01 # test problem state bit | 109 | tm \psworg+1,0x01 # test problem state bit |
@@ -207,7 +212,7 @@ system_call: | |||
207 | STORE_TIMER __LC_SYNC_ENTER_TIMER | 212 | STORE_TIMER __LC_SYNC_ENTER_TIMER |
208 | sysc_saveall: | 213 | sysc_saveall: |
209 | SAVE_ALL_BASE __LC_SAVE_AREA | 214 | SAVE_ALL_BASE __LC_SAVE_AREA |
210 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 215 | SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
211 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 216 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
212 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 217 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore |
213 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 218 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 367caf92ea78..82b131ddd7ff 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -25,10 +25,6 @@ | |||
25 | 25 | ||
26 | #define IPL_PARM_BLOCK_VERSION 0 | 26 | #define IPL_PARM_BLOCK_VERSION 0 |
27 | 27 | ||
28 | #define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10) | ||
29 | #define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm) | ||
30 | #define SCCB_FLAG (s390_readinfo_sccb.flags) | ||
31 | |||
32 | #define IPL_UNKNOWN_STR "unknown" | 28 | #define IPL_UNKNOWN_STR "unknown" |
33 | #define IPL_CCW_STR "ccw" | 29 | #define IPL_CCW_STR "ccw" |
34 | #define IPL_FCP_STR "fcp" | 30 | #define IPL_FCP_STR "fcp" |
@@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw; | |||
146 | 142 | ||
147 | static enum shutdown_action on_panic_action = SHUTDOWN_STOP; | 143 | static enum shutdown_action on_panic_action = SHUTDOWN_STOP; |
148 | 144 | ||
145 | static struct sclp_ipl_info sclp_ipl_info; | ||
146 | |||
149 | int diag308(unsigned long subcode, void *addr) | 147 | int diag308(unsigned long subcode, void *addr) |
150 | { | 148 | { |
151 | register unsigned long _addr asm("0") = (unsigned long) addr; | 149 | register unsigned long _addr asm("0") = (unsigned long) addr; |
@@ -375,9 +373,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) | |||
375 | { | 373 | { |
376 | char loadparm[LOADPARM_LEN + 1] = {}; | 374 | char loadparm[LOADPARM_LEN + 1] = {}; |
377 | 375 | ||
378 | if (!SCCB_VALID) | 376 | if (!sclp_ipl_info.is_valid) |
379 | return sprintf(page, "#unknown#\n"); | 377 | return sprintf(page, "#unknown#\n"); |
380 | memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN); | 378 | memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); |
381 | EBCASC(loadparm, LOADPARM_LEN); | 379 | EBCASC(loadparm, LOADPARM_LEN); |
382 | strstrip(loadparm); | 380 | strstrip(loadparm); |
383 | return sprintf(page, "%s\n", loadparm); | 381 | return sprintf(page, "%s\n", loadparm); |
@@ -910,9 +908,9 @@ static int __init reipl_ccw_init(void) | |||
910 | reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; | 908 | reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; |
911 | reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; | 909 | reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; |
912 | /* check if read scp info worked and set loadparm */ | 910 | /* check if read scp info worked and set loadparm */ |
913 | if (SCCB_VALID) | 911 | if (sclp_ipl_info.is_valid) |
914 | memcpy(reipl_block_ccw->ipl_info.ccw.load_param, | 912 | memcpy(reipl_block_ccw->ipl_info.ccw.load_param, |
915 | SCCB_LOADPARM, LOADPARM_LEN); | 913 | &sclp_ipl_info.loadparm, LOADPARM_LEN); |
916 | else | 914 | else |
917 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ | 915 | /* read scp info failed: set empty loadparm (EBCDIC blanks) */ |
918 | memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, | 916 | memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, |
@@ -1007,7 +1005,7 @@ static int __init dump_fcp_init(void) | |||
1007 | { | 1005 | { |
1008 | int rc; | 1006 | int rc; |
1009 | 1007 | ||
1010 | if(!(SCCB_FLAG & 0x2) || !SCCB_VALID) | 1008 | if (!sclp_ipl_info.has_dump) |
1011 | return 0; /* LDIPL DUMP is not installed */ | 1009 | return 0; /* LDIPL DUMP is not installed */ |
1012 | if (!diag308_set_works) | 1010 | if (!diag308_set_works) |
1013 | return 0; | 1011 | return 0; |
@@ -1088,6 +1086,7 @@ static int __init s390_ipl_init(void) | |||
1088 | { | 1086 | { |
1089 | int rc; | 1087 | int rc; |
1090 | 1088 | ||
1089 | sclp_get_ipl_info(&sclp_ipl_info); | ||
1091 | reipl_probe(); | 1090 | reipl_probe(); |
1092 | rc = ipl_init(); | 1091 | rc = ipl_init(); |
1093 | if (rc) | 1092 | if (rc) |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index eb43c3b31269..441975b796fb 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -93,8 +93,8 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code) | |||
93 | /* disable monitor call class 0 */ | 93 | /* disable monitor call class 0 */ |
94 | __ctl_clear_bit(8, 15); | 94 | __ctl_clear_bit(8, 15); |
95 | 95 | ||
96 | atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE, | 96 | atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE, |
97 | (void *)(long) smp_processor_id()); | 97 | (void *)(long) smp_processor_id()); |
98 | } | 98 | } |
99 | 99 | ||
100 | extern void s390_handle_mcck(void); | 100 | extern void s390_handle_mcck(void); |
@@ -115,7 +115,7 @@ static void default_idle(void) | |||
115 | } | 115 | } |
116 | 116 | ||
117 | rc = atomic_notifier_call_chain(&idle_chain, | 117 | rc = atomic_notifier_call_chain(&idle_chain, |
118 | CPU_IDLE, (void *)(long) cpu); | 118 | S390_CPU_IDLE, (void *)(long) cpu); |
119 | if (rc != NOTIFY_OK && rc != NOTIFY_DONE) | 119 | if (rc != NOTIFY_OK && rc != NOTIFY_DONE) |
120 | BUG(); | 120 | BUG(); |
121 | if (rc != NOTIFY_OK) { | 121 | if (rc != NOTIFY_OK) { |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8ff2feaf9b00..182c085ae4dd 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -410,58 +410,40 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); | |||
410 | unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \ | 410 | unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \ |
411 | __attribute__((__section__(".data"))); | 411 | __attribute__((__section__(".data"))); |
412 | 412 | ||
413 | static void __init smp_get_save_areas(void) | 413 | static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) |
414 | { | 414 | { |
415 | unsigned int cpu, cpu_num, rc; | ||
416 | __u16 boot_cpu_addr; | ||
417 | |||
418 | if (ipl_info.type != IPL_TYPE_FCP_DUMP) | 415 | if (ipl_info.type != IPL_TYPE_FCP_DUMP) |
419 | return; | 416 | return; |
420 | boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; | 417 | if (cpu >= NR_CPUS) { |
421 | cpu_num = 1; | 418 | printk(KERN_WARNING "Registers for cpu %i not saved since dump " |
422 | for (cpu = 0; cpu <= 65535; cpu++) { | 419 | "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS); |
423 | if ((u16) cpu == boot_cpu_addr) | 420 | return; |
424 | continue; | ||
425 | __cpu_logical_map[1] = (__u16) cpu; | ||
426 | if (signal_processor(1, sigp_sense) == sigp_not_operational) | ||
427 | continue; | ||
428 | if (cpu_num >= NR_CPUS) { | ||
429 | printk("WARNING: Registers for cpu %i are not " | ||
430 | "saved, since dump kernel was compiled with" | ||
431 | "NR_CPUS=%i!\n", cpu_num, NR_CPUS); | ||
432 | continue; | ||
433 | } | ||
434 | zfcpdump_save_areas[cpu_num] = | ||
435 | alloc_bootmem(sizeof(union save_area)); | ||
436 | while (1) { | ||
437 | rc = signal_processor(1, sigp_stop_and_store_status); | ||
438 | if (rc != sigp_busy) | ||
439 | break; | ||
440 | cpu_relax(); | ||
441 | } | ||
442 | memcpy(zfcpdump_save_areas[cpu_num], | ||
443 | (void *)(unsigned long) store_prefix() + | ||
444 | SAVE_AREA_BASE, SAVE_AREA_SIZE); | ||
445 | #ifdef __s390x__ | ||
446 | /* copy original prefix register */ | ||
447 | zfcpdump_save_areas[cpu_num]->s390x.pref_reg = | ||
448 | zfcpdump_prefix_array[cpu_num]; | ||
449 | #endif | ||
450 | cpu_num++; | ||
451 | } | 421 | } |
422 | zfcpdump_save_areas[cpu] = alloc_bootmem(sizeof(union save_area)); | ||
423 | __cpu_logical_map[1] = (__u16) phy_cpu; | ||
424 | while (signal_processor(1, sigp_stop_and_store_status) == sigp_busy) | ||
425 | cpu_relax(); | ||
426 | memcpy(zfcpdump_save_areas[cpu], | ||
427 | (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE, | ||
428 | SAVE_AREA_SIZE); | ||
429 | #ifdef CONFIG_64BIT | ||
430 | /* copy original prefix register */ | ||
431 | zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu]; | ||
432 | #endif | ||
452 | } | 433 | } |
453 | 434 | ||
454 | union save_area *zfcpdump_save_areas[NR_CPUS + 1]; | 435 | union save_area *zfcpdump_save_areas[NR_CPUS + 1]; |
455 | EXPORT_SYMBOL_GPL(zfcpdump_save_areas); | 436 | EXPORT_SYMBOL_GPL(zfcpdump_save_areas); |
456 | 437 | ||
457 | #else | 438 | #else |
458 | #define smp_get_save_areas() do { } while (0) | 439 | |
459 | #endif | 440 | static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } |
441 | |||
442 | #endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */ | ||
460 | 443 | ||
461 | /* | 444 | /* |
462 | * Lets check how many CPUs we have. | 445 | * Lets check how many CPUs we have. |
463 | */ | 446 | */ |
464 | |||
465 | static unsigned int __init smp_count_cpus(void) | 447 | static unsigned int __init smp_count_cpus(void) |
466 | { | 448 | { |
467 | unsigned int cpu, num_cpus; | 449 | unsigned int cpu, num_cpus; |
@@ -470,7 +452,6 @@ static unsigned int __init smp_count_cpus(void) | |||
470 | /* | 452 | /* |
471 | * cpu 0 is the boot cpu. See smp_prepare_boot_cpu. | 453 | * cpu 0 is the boot cpu. See smp_prepare_boot_cpu. |
472 | */ | 454 | */ |
473 | |||
474 | boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; | 455 | boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; |
475 | current_thread_info()->cpu = 0; | 456 | current_thread_info()->cpu = 0; |
476 | num_cpus = 1; | 457 | num_cpus = 1; |
@@ -480,12 +461,11 @@ static unsigned int __init smp_count_cpus(void) | |||
480 | __cpu_logical_map[1] = (__u16) cpu; | 461 | __cpu_logical_map[1] = (__u16) cpu; |
481 | if (signal_processor(1, sigp_sense) == sigp_not_operational) | 462 | if (signal_processor(1, sigp_sense) == sigp_not_operational) |
482 | continue; | 463 | continue; |
464 | smp_get_save_area(num_cpus, cpu); | ||
483 | num_cpus++; | 465 | num_cpus++; |
484 | } | 466 | } |
485 | |||
486 | printk("Detected %d CPU's\n", (int) num_cpus); | 467 | printk("Detected %d CPU's\n", (int) num_cpus); |
487 | printk("Boot cpu address %2X\n", boot_cpu_addr); | 468 | printk("Boot cpu address %2X\n", boot_cpu_addr); |
488 | |||
489 | return num_cpus; | 469 | return num_cpus; |
490 | } | 470 | } |
491 | 471 | ||
@@ -606,7 +586,6 @@ void __init smp_setup_cpu_possible_map(void) | |||
606 | { | 586 | { |
607 | unsigned int phy_cpus, pos_cpus, cpu; | 587 | unsigned int phy_cpus, pos_cpus, cpu; |
608 | 588 | ||
609 | smp_get_save_areas(); | ||
610 | phy_cpus = smp_count_cpus(); | 589 | phy_cpus = smp_count_cpus(); |
611 | pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS); | 590 | pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS); |
612 | 591 | ||
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 9c2872a7cca7..48dae49bc1ec 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -226,10 +226,10 @@ static int nohz_idle_notify(struct notifier_block *self, | |||
226 | unsigned long action, void *hcpu) | 226 | unsigned long action, void *hcpu) |
227 | { | 227 | { |
228 | switch (action) { | 228 | switch (action) { |
229 | case CPU_IDLE: | 229 | case S390_CPU_IDLE: |
230 | stop_hz_timer(); | 230 | stop_hz_timer(); |
231 | break; | 231 | break; |
232 | case CPU_NOT_IDLE: | 232 | case S390_CPU_NOT_IDLE: |
233 | start_hz_timer(); | 233 | start_hz_timer(); |
234 | break; | 234 | break; |
235 | } | 235 | } |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 1e1a6ee2cac1..b6ed143e8597 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -545,10 +545,10 @@ static int vtimer_idle_notify(struct notifier_block *self, | |||
545 | unsigned long action, void *hcpu) | 545 | unsigned long action, void *hcpu) |
546 | { | 546 | { |
547 | switch (action) { | 547 | switch (action) { |
548 | case CPU_IDLE: | 548 | case S390_CPU_IDLE: |
549 | stop_cpu_timer(); | 549 | stop_cpu_timer(); |
550 | break; | 550 | break; |
551 | case CPU_NOT_IDLE: | 551 | case S390_CPU_NOT_IDLE: |
552 | start_cpu_timer(); | 552 | start_cpu_timer(); |
553 | break; | 553 | break; |
554 | } | 554 | } |
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index 59aea65ce99f..52084436ab69 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
6 | 6 | ||
7 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o | 7 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o |
8 | obj-$(CONFIG_32BIT) += div64.o | 8 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o |
9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o | 9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o |
10 | lib-$(CONFIG_SMP) += spinlock.o | 10 | lib-$(CONFIG_SMP) += spinlock.o |
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 8b3b0f4a157c..ac7e8ef504cb 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c | |||
@@ -28,6 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL; | |||
28 | static struct proc_dir_entry *dasd_devices_entry = NULL; | 28 | static struct proc_dir_entry *dasd_devices_entry = NULL; |
29 | static struct proc_dir_entry *dasd_statistics_entry = NULL; | 29 | static struct proc_dir_entry *dasd_statistics_entry = NULL; |
30 | 30 | ||
31 | #ifdef CONFIG_DASD_PROFILE | ||
31 | static char * | 32 | static char * |
32 | dasd_get_user_string(const char __user *user_buf, size_t user_len) | 33 | dasd_get_user_string(const char __user *user_buf, size_t user_len) |
33 | { | 34 | { |
@@ -47,6 +48,7 @@ dasd_get_user_string(const char __user *user_buf, size_t user_len) | |||
47 | buffer[user_len] = 0; | 48 | buffer[user_len] = 0; |
48 | return buffer; | 49 | return buffer; |
49 | } | 50 | } |
51 | #endif /* CONFIG_DASD_PROFILE */ | ||
50 | 52 | ||
51 | static int | 53 | static int |
52 | dasd_devices_show(struct seq_file *m, void *v) | 54 | dasd_devices_show(struct seq_file *m, void *v) |
@@ -167,6 +169,7 @@ dasd_calc_metrics(char *page, char **start, off_t off, | |||
167 | return len; | 169 | return len; |
168 | } | 170 | } |
169 | 171 | ||
172 | #ifdef CONFIG_DASD_PROFILE | ||
170 | static char * | 173 | static char * |
171 | dasd_statistics_array(char *str, unsigned int *array, int shift) | 174 | dasd_statistics_array(char *str, unsigned int *array, int shift) |
172 | { | 175 | { |
@@ -180,6 +183,7 @@ dasd_statistics_array(char *str, unsigned int *array, int shift) | |||
180 | str += sprintf(str,"\n"); | 183 | str += sprintf(str,"\n"); |
181 | return str; | 184 | return str; |
182 | } | 185 | } |
186 | #endif /* CONFIG_DASD_PROFILE */ | ||
183 | 187 | ||
184 | static int | 188 | static int |
185 | dasd_statistics_read(char *page, char **start, off_t off, | 189 | dasd_statistics_read(char *page, char **start, off_t off, |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index dbb99d1b6f57..c7318a125852 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -72,6 +72,18 @@ typedef unsigned int sclp_cmdw_t; | |||
72 | 72 | ||
73 | typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ | 73 | typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ |
74 | 74 | ||
75 | struct sccb_header { | ||
76 | u16 length; | ||
77 | u8 function_code; | ||
78 | u8 control_mask[3]; | ||
79 | u16 response_code; | ||
80 | } __attribute__((packed)); | ||
81 | |||
82 | extern u64 sclp_facilities; | ||
83 | |||
84 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) | ||
85 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) | ||
86 | |||
75 | struct gds_subvector { | 87 | struct gds_subvector { |
76 | u8 length; | 88 | u8 length; |
77 | u8 key; | 89 | u8 key; |
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c index a66b914519b5..c68f5e7e63a0 100644 --- a/drivers/s390/char/sclp_chp.c +++ b/drivers/s390/char/sclp_chp.c | |||
@@ -55,6 +55,8 @@ static int do_configure(sclp_cmdw_t cmd) | |||
55 | struct chp_cfg_data *data; | 55 | struct chp_cfg_data *data; |
56 | int rc; | 56 | int rc; |
57 | 57 | ||
58 | if (!SCLP_HAS_CHP_RECONFIG) | ||
59 | return -EOPNOTSUPP; | ||
58 | /* Prepare sccb. */ | 60 | /* Prepare sccb. */ |
59 | data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | 61 | data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
60 | if (!data) | 62 | if (!data) |
@@ -152,6 +154,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info) | |||
152 | struct chp_info_data *data; | 154 | struct chp_info_data *data; |
153 | int rc; | 155 | int rc; |
154 | 156 | ||
157 | if (!SCLP_HAS_CHP_INFO) | ||
158 | return -EOPNOTSUPP; | ||
155 | /* Prepare sccb. */ | 159 | /* Prepare sccb. */ |
156 | data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | 160 | data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
157 | if (!data) | 161 | if (!data) |
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c index 7bcbe643b087..a1136e052750 100644 --- a/drivers/s390/char/sclp_info.c +++ b/drivers/s390/char/sclp_info.c | |||
@@ -11,47 +11,106 @@ | |||
11 | #include <asm/sclp.h> | 11 | #include <asm/sclp.h> |
12 | #include "sclp.h" | 12 | #include "sclp.h" |
13 | 13 | ||
14 | struct sclp_readinfo_sccb s390_readinfo_sccb; | 14 | struct sclp_readinfo_sccb { |
15 | struct sccb_header header; /* 0-7 */ | ||
16 | u16 rnmax; /* 8-9 */ | ||
17 | u8 rnsize; /* 10 */ | ||
18 | u8 _reserved0[24 - 11]; /* 11-23 */ | ||
19 | u8 loadparm[8]; /* 24-31 */ | ||
20 | u8 _reserved1[48 - 32]; /* 32-47 */ | ||
21 | u64 facilities; /* 48-55 */ | ||
22 | u8 _reserved2[91 - 56]; /* 56-90 */ | ||
23 | u8 flags; /* 91 */ | ||
24 | u8 _reserved3[100 - 92]; /* 92-99 */ | ||
25 | u32 rnsize2; /* 100-103 */ | ||
26 | u64 rnmax2; /* 104-111 */ | ||
27 | u8 _reserved4[4096 - 112]; /* 112-4095 */ | ||
28 | } __attribute__((packed, aligned(4096))); | ||
29 | |||
30 | static struct sclp_readinfo_sccb __initdata early_readinfo_sccb; | ||
31 | static int __initdata early_readinfo_sccb_valid; | ||
32 | |||
33 | u64 sclp_facilities; | ||
15 | 34 | ||
16 | void __init sclp_readinfo_early(void) | 35 | void __init sclp_readinfo_early(void) |
17 | { | 36 | { |
18 | sclp_cmdw_t command; | ||
19 | struct sccb_header *sccb; | ||
20 | int ret; | 37 | int ret; |
38 | int i; | ||
39 | struct sclp_readinfo_sccb *sccb; | ||
40 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | ||
41 | SCLP_CMDW_READ_SCP_INFO}; | ||
21 | 42 | ||
22 | __ctl_set_bit(0, 9); /* enable service signal subclass mask */ | 43 | /* Enable service signal subclass mask. */ |
23 | 44 | __ctl_set_bit(0, 9); | |
24 | sccb = &s390_readinfo_sccb.header; | 45 | sccb = &early_readinfo_sccb; |
25 | command = SCLP_CMDW_READ_SCP_INFO_FORCED; | 46 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
26 | while (1) { | 47 | do { |
27 | u16 response; | 48 | memset(sccb, 0, sizeof(*sccb)); |
28 | 49 | sccb->header.length = sizeof(*sccb); | |
29 | memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); | 50 | sccb->header.control_mask[2] = 0x80; |
30 | sccb->length = sizeof(s390_readinfo_sccb); | 51 | ret = sclp_service_call(commands[i], sccb); |
31 | sccb->control_mask[2] = 0x80; | 52 | } while (ret == -EBUSY); |
32 | |||
33 | ret = sclp_service_call(command, &s390_readinfo_sccb); | ||
34 | |||
35 | if (ret == -EIO) | ||
36 | goto out; | ||
37 | if (ret == -EBUSY) | ||
38 | continue; | ||
39 | 53 | ||
54 | if (ret) | ||
55 | break; | ||
40 | __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | | 56 | __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | |
41 | PSW_MASK_WAIT | PSW_DEFAULT_KEY); | 57 | PSW_MASK_WAIT | PSW_DEFAULT_KEY); |
42 | local_irq_disable(); | 58 | local_irq_disable(); |
59 | /* | ||
60 | * Contents of the sccb might have changed | ||
61 | * therefore a barrier is needed. | ||
62 | */ | ||
43 | barrier(); | 63 | barrier(); |
64 | if (sccb->header.response_code == 0x10) { | ||
65 | early_readinfo_sccb_valid = 1; | ||
66 | break; | ||
67 | } | ||
68 | if (sccb->header.response_code != 0x1f0) | ||
69 | break; | ||
70 | } | ||
71 | /* Disable service signal subclass mask again. */ | ||
72 | __ctl_clear_bit(0, 9); | ||
73 | } | ||
44 | 74 | ||
45 | response = sccb->response_code; | 75 | void __init sclp_facilities_detect(void) |
76 | { | ||
77 | if (!early_readinfo_sccb_valid) | ||
78 | return; | ||
79 | sclp_facilities = early_readinfo_sccb.facilities; | ||
80 | } | ||
46 | 81 | ||
47 | if (response == 0x10) | 82 | unsigned long long __init sclp_memory_detect(void) |
48 | break; | 83 | { |
84 | unsigned long long memsize; | ||
85 | struct sclp_readinfo_sccb *sccb; | ||
49 | 86 | ||
50 | if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) | 87 | if (!early_readinfo_sccb_valid) |
51 | break; | 88 | return 0; |
89 | sccb = &early_readinfo_sccb; | ||
90 | if (sccb->rnsize) | ||
91 | memsize = sccb->rnsize << 20; | ||
92 | else | ||
93 | memsize = sccb->rnsize2 << 20; | ||
94 | if (sccb->rnmax) | ||
95 | memsize *= sccb->rnmax; | ||
96 | else | ||
97 | memsize *= sccb->rnmax2; | ||
98 | return memsize; | ||
99 | } | ||
52 | 100 | ||
53 | command = SCLP_CMDW_READ_SCP_INFO; | 101 | /* |
54 | } | 102 | * This function will be called after sclp_memory_detect(), which gets called |
55 | out: | 103 | * early from early.c code. Therefore the sccb should have valid contents. |
56 | __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ | 104 | */ |
105 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | ||
106 | { | ||
107 | struct sclp_readinfo_sccb *sccb; | ||
108 | |||
109 | if (!early_readinfo_sccb_valid) | ||
110 | return; | ||
111 | sccb = &early_readinfo_sccb; | ||
112 | info->is_valid = 1; | ||
113 | if (sccb->flags & 0x2) | ||
114 | info->has_dump = 1; | ||
115 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
57 | } | 116 | } |
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index fce3dac5cb3e..82e6a6b253eb 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c | |||
@@ -175,13 +175,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
175 | 175 | ||
176 | static const struct file_operations vmcp_fops = { | 176 | static const struct file_operations vmcp_fops = { |
177 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
178 | .open = &vmcp_open, | 178 | .open = vmcp_open, |
179 | .release = &vmcp_release, | 179 | .release = vmcp_release, |
180 | .read = &vmcp_read, | 180 | .read = vmcp_read, |
181 | .llseek = &no_llseek, | 181 | .write = vmcp_write, |
182 | .write = &vmcp_write, | 182 | .unlocked_ioctl = vmcp_ioctl, |
183 | .unlocked_ioctl = &vmcp_ioctl, | 183 | .compat_ioctl = vmcp_ioctl |
184 | .compat_ioctl = &vmcp_ioctl | ||
185 | }; | 184 | }; |
186 | 185 | ||
187 | static struct miscdevice vmcp_dev = { | 186 | static struct miscdevice vmcp_dev = { |
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index a5a00e9ae4d0..12f7a4ce82c1 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
@@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void) | |||
835 | } | 835 | } |
836 | 836 | ||
837 | 837 | ||
838 | static int vmlogrdr_init(void) | 838 | static int __init vmlogrdr_init(void) |
839 | { | 839 | { |
840 | int rc; | 840 | int rc; |
841 | int i; | 841 | int i; |
@@ -885,7 +885,7 @@ cleanup: | |||
885 | } | 885 | } |
886 | 886 | ||
887 | 887 | ||
888 | static void vmlogrdr_exit(void) | 888 | static void __exit vmlogrdr_exit(void) |
889 | { | 889 | { |
890 | vmlogrdr_cleanup(); | 890 | vmlogrdr_cleanup(); |
891 | printk (KERN_INFO "vmlogrdr: driver unloaded\n"); | 891 | printk (KERN_INFO "vmlogrdr: driver unloaded\n"); |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 4e711a985d59..3712ede16723 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -156,7 +156,7 @@ static int memcpy_real(void *dest, unsigned long src, size_t count) | |||
156 | return rc; | 156 | return rc; |
157 | } | 157 | } |
158 | 158 | ||
159 | static int memcpy_real_user(__user void *dest, unsigned long src, size_t count) | 159 | static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) |
160 | { | 160 | { |
161 | static char buf[4096]; | 161 | static char buf[4096]; |
162 | int offs = 0, size; | 162 | int offs = 0, size; |
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 997f46874537..60b9347f7c92 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c | |||
@@ -27,7 +27,6 @@ | |||
27 | /* | 27 | /* |
28 | * diag210 is used under VM to get information about a virtual device | 28 | * diag210 is used under VM to get information about a virtual device |
29 | */ | 29 | */ |
30 | #ifdef CONFIG_64BIT | ||
31 | int | 30 | int |
32 | diag210(struct diag210 * addr) | 31 | diag210(struct diag210 * addr) |
33 | { | 32 | { |
@@ -43,6 +42,7 @@ diag210(struct diag210 * addr) | |||
43 | spin_lock_irqsave(&diag210_lock, flags); | 42 | spin_lock_irqsave(&diag210_lock, flags); |
44 | diag210_tmp = *addr; | 43 | diag210_tmp = *addr; |
45 | 44 | ||
45 | #ifdef CONFIG_64BIT | ||
46 | asm volatile( | 46 | asm volatile( |
47 | " lhi %0,-1\n" | 47 | " lhi %0,-1\n" |
48 | " sam31\n" | 48 | " sam31\n" |
@@ -51,19 +51,8 @@ diag210(struct diag210 * addr) | |||
51 | " srl %0,28\n" | 51 | " srl %0,28\n" |
52 | "1: sam64\n" | 52 | "1: sam64\n" |
53 | EX_TABLE(0b,1b) | 53 | EX_TABLE(0b,1b) |
54 | : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory"); | 54 | : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); |
55 | |||
56 | *addr = diag210_tmp; | ||
57 | spin_unlock_irqrestore(&diag210_lock, flags); | ||
58 | |||
59 | return ccode; | ||
60 | } | ||
61 | #else | 55 | #else |
62 | int | ||
63 | diag210(struct diag210 * addr) | ||
64 | { | ||
65 | int ccode; | ||
66 | |||
67 | asm volatile( | 56 | asm volatile( |
68 | " lhi %0,-1\n" | 57 | " lhi %0,-1\n" |
69 | " diag %1,0,0x210\n" | 58 | " diag %1,0,0x210\n" |
@@ -71,11 +60,14 @@ diag210(struct diag210 * addr) | |||
71 | " srl %0,28\n" | 60 | " srl %0,28\n" |
72 | "1:\n" | 61 | "1:\n" |
73 | EX_TABLE(0b,1b) | 62 | EX_TABLE(0b,1b) |
74 | : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory"); | 63 | : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); |
64 | #endif | ||
65 | |||
66 | *addr = diag210_tmp; | ||
67 | spin_unlock_irqrestore(&diag210_lock, flags); | ||
75 | 68 | ||
76 | return ccode; | 69 | return ccode; |
77 | } | 70 | } |
78 | #endif | ||
79 | 71 | ||
80 | /* | 72 | /* |
81 | * Input : | 73 | * Input : |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 5aac0ec36368..90bd22014513 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long); | |||
43 | static void ap_poll_timeout(unsigned long); | 43 | static void ap_poll_timeout(unsigned long); |
44 | static int ap_poll_thread_start(void); | 44 | static int ap_poll_thread_start(void); |
45 | static void ap_poll_thread_stop(void); | 45 | static void ap_poll_thread_stop(void); |
46 | static void ap_request_timeout(unsigned long); | ||
46 | 47 | ||
47 | /** | 48 | /** |
48 | * Module description. | 49 | * Module description. |
@@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) | |||
189 | case AP_RESPONSE_NORMAL: | 190 | case AP_RESPONSE_NORMAL: |
190 | return 0; | 191 | return 0; |
191 | case AP_RESPONSE_Q_FULL: | 192 | case AP_RESPONSE_Q_FULL: |
193 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
192 | return -EBUSY; | 194 | return -EBUSY; |
193 | default: /* Device is gone. */ | 195 | default: /* Device is gone. */ |
194 | return -ENODEV; | 196 | return -ENODEV; |
@@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) | |||
252 | if (status.queue_empty) | 254 | if (status.queue_empty) |
253 | return -ENOENT; | 255 | return -ENOENT; |
254 | return -EBUSY; | 256 | return -EBUSY; |
257 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
258 | return -EBUSY; | ||
255 | default: | 259 | default: |
256 | return -ENODEV; | 260 | return -ENODEV; |
257 | } | 261 | } |
@@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid) | |||
326 | i = AP_MAX_RESET; /* return with -ENODEV */ | 330 | i = AP_MAX_RESET; /* return with -ENODEV */ |
327 | break; | 331 | break; |
328 | case AP_RESPONSE_RESET_IN_PROGRESS: | 332 | case AP_RESPONSE_RESET_IN_PROGRESS: |
333 | rc = -EBUSY; | ||
329 | case AP_RESPONSE_BUSY: | 334 | case AP_RESPONSE_BUSY: |
330 | default: | 335 | default: |
331 | break; | 336 | break; |
332 | } | 337 | } |
333 | if (rc != -ENODEV) | 338 | if (rc != -ENODEV && rc != -EBUSY) |
334 | break; | 339 | break; |
335 | if (i < AP_MAX_RESET - 1) { | 340 | if (i < AP_MAX_RESET - 1) { |
336 | udelay(5); | 341 | udelay(5); |
@@ -341,6 +346,40 @@ static int ap_init_queue(ap_qid_t qid) | |||
341 | } | 346 | } |
342 | 347 | ||
343 | /** | 348 | /** |
349 | * Arm request timeout if a AP device was idle and a new request is submitted. | ||
350 | */ | ||
351 | static void ap_increase_queue_count(struct ap_device *ap_dev) | ||
352 | { | ||
353 | int timeout = ap_dev->drv->request_timeout; | ||
354 | |||
355 | ap_dev->queue_count++; | ||
356 | if (ap_dev->queue_count == 1) { | ||
357 | mod_timer(&ap_dev->timeout, jiffies + timeout); | ||
358 | ap_dev->reset = AP_RESET_ARMED; | ||
359 | } | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * AP device is still alive, re-schedule request timeout if there are still | ||
364 | * pending requests. | ||
365 | */ | ||
366 | static void ap_decrease_queue_count(struct ap_device *ap_dev) | ||
367 | { | ||
368 | int timeout = ap_dev->drv->request_timeout; | ||
369 | |||
370 | ap_dev->queue_count--; | ||
371 | if (ap_dev->queue_count > 0) | ||
372 | mod_timer(&ap_dev->timeout, jiffies + timeout); | ||
373 | else | ||
374 | /** | ||
375 | * The timeout timer should to be disabled now - since | ||
376 | * del_timer_sync() is very expensive, we just tell via the | ||
377 | * reset flag to ignore the pending timeout timer. | ||
378 | */ | ||
379 | ap_dev->reset = AP_RESET_IGNORE; | ||
380 | } | ||
381 | |||
382 | /** | ||
344 | * AP device related attributes. | 383 | * AP device related attributes. |
345 | */ | 384 | */ |
346 | static ssize_t ap_hwtype_show(struct device *dev, | 385 | static ssize_t ap_hwtype_show(struct device *dev, |
@@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev) | |||
498 | struct ap_driver *ap_drv = ap_dev->drv; | 537 | struct ap_driver *ap_drv = ap_dev->drv; |
499 | 538 | ||
500 | ap_flush_queue(ap_dev); | 539 | ap_flush_queue(ap_dev); |
540 | del_timer_sync(&ap_dev->timeout); | ||
501 | if (ap_drv->remove) | 541 | if (ap_drv->remove) |
502 | ap_drv->remove(ap_dev); | 542 | ap_drv->remove(ap_dev); |
503 | spin_lock_bh(&ap_device_lock); | 543 | spin_lock_bh(&ap_device_lock); |
@@ -759,17 +799,21 @@ static void ap_scan_bus(struct work_struct *unused) | |||
759 | __ap_scan_bus); | 799 | __ap_scan_bus); |
760 | rc = ap_query_queue(qid, &queue_depth, &device_type); | 800 | rc = ap_query_queue(qid, &queue_depth, &device_type); |
761 | if (dev) { | 801 | if (dev) { |
802 | if (rc == -EBUSY) { | ||
803 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
804 | schedule_timeout(AP_RESET_TIMEOUT); | ||
805 | rc = ap_query_queue(qid, &queue_depth, | ||
806 | &device_type); | ||
807 | } | ||
762 | ap_dev = to_ap_dev(dev); | 808 | ap_dev = to_ap_dev(dev); |
763 | spin_lock_bh(&ap_dev->lock); | 809 | spin_lock_bh(&ap_dev->lock); |
764 | if (rc || ap_dev->unregistered) { | 810 | if (rc || ap_dev->unregistered) { |
765 | spin_unlock_bh(&ap_dev->lock); | 811 | spin_unlock_bh(&ap_dev->lock); |
766 | put_device(dev); | ||
767 | device_unregister(dev); | 812 | device_unregister(dev); |
813 | put_device(dev); | ||
768 | continue; | 814 | continue; |
769 | } else | 815 | } |
770 | spin_unlock_bh(&ap_dev->lock); | 816 | spin_unlock_bh(&ap_dev->lock); |
771 | } | ||
772 | if (dev) { | ||
773 | put_device(dev); | 817 | put_device(dev); |
774 | continue; | 818 | continue; |
775 | } | 819 | } |
@@ -788,6 +832,8 @@ static void ap_scan_bus(struct work_struct *unused) | |||
788 | INIT_LIST_HEAD(&ap_dev->pendingq); | 832 | INIT_LIST_HEAD(&ap_dev->pendingq); |
789 | INIT_LIST_HEAD(&ap_dev->requestq); | 833 | INIT_LIST_HEAD(&ap_dev->requestq); |
790 | INIT_LIST_HEAD(&ap_dev->list); | 834 | INIT_LIST_HEAD(&ap_dev->list); |
835 | setup_timer(&ap_dev->timeout, ap_request_timeout, | ||
836 | (unsigned long) ap_dev); | ||
791 | if (device_type == 0) | 837 | if (device_type == 0) |
792 | ap_probe_device_type(ap_dev); | 838 | ap_probe_device_type(ap_dev); |
793 | else | 839 | else |
@@ -853,7 +899,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) | |||
853 | switch (status.response_code) { | 899 | switch (status.response_code) { |
854 | case AP_RESPONSE_NORMAL: | 900 | case AP_RESPONSE_NORMAL: |
855 | atomic_dec(&ap_poll_requests); | 901 | atomic_dec(&ap_poll_requests); |
856 | ap_dev->queue_count--; | 902 | ap_decrease_queue_count(ap_dev); |
857 | list_for_each_entry(ap_msg, &ap_dev->pendingq, list) { | 903 | list_for_each_entry(ap_msg, &ap_dev->pendingq, list) { |
858 | if (ap_msg->psmid != ap_dev->reply->psmid) | 904 | if (ap_msg->psmid != ap_dev->reply->psmid) |
859 | continue; | 905 | continue; |
@@ -904,7 +950,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) | |||
904 | switch (status.response_code) { | 950 | switch (status.response_code) { |
905 | case AP_RESPONSE_NORMAL: | 951 | case AP_RESPONSE_NORMAL: |
906 | atomic_inc(&ap_poll_requests); | 952 | atomic_inc(&ap_poll_requests); |
907 | ap_dev->queue_count++; | 953 | ap_increase_queue_count(ap_dev); |
908 | list_move_tail(&ap_msg->list, &ap_dev->pendingq); | 954 | list_move_tail(&ap_msg->list, &ap_dev->pendingq); |
909 | ap_dev->requestq_count--; | 955 | ap_dev->requestq_count--; |
910 | ap_dev->pendingq_count++; | 956 | ap_dev->pendingq_count++; |
@@ -914,6 +960,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) | |||
914 | *flags |= 2; | 960 | *flags |= 2; |
915 | break; | 961 | break; |
916 | case AP_RESPONSE_Q_FULL: | 962 | case AP_RESPONSE_Q_FULL: |
963 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
917 | *flags |= 2; | 964 | *flags |= 2; |
918 | break; | 965 | break; |
919 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 966 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
@@ -960,10 +1007,11 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms | |||
960 | list_add_tail(&ap_msg->list, &ap_dev->pendingq); | 1007 | list_add_tail(&ap_msg->list, &ap_dev->pendingq); |
961 | atomic_inc(&ap_poll_requests); | 1008 | atomic_inc(&ap_poll_requests); |
962 | ap_dev->pendingq_count++; | 1009 | ap_dev->pendingq_count++; |
963 | ap_dev->queue_count++; | 1010 | ap_increase_queue_count(ap_dev); |
964 | ap_dev->total_request_count++; | 1011 | ap_dev->total_request_count++; |
965 | break; | 1012 | break; |
966 | case AP_RESPONSE_Q_FULL: | 1013 | case AP_RESPONSE_Q_FULL: |
1014 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
967 | list_add_tail(&ap_msg->list, &ap_dev->requestq); | 1015 | list_add_tail(&ap_msg->list, &ap_dev->requestq); |
968 | ap_dev->requestq_count++; | 1016 | ap_dev->requestq_count++; |
969 | ap_dev->total_request_count++; | 1017 | ap_dev->total_request_count++; |
@@ -1046,6 +1094,25 @@ static void ap_poll_timeout(unsigned long unused) | |||
1046 | } | 1094 | } |
1047 | 1095 | ||
1048 | /** | 1096 | /** |
1097 | * Reset a not responding AP device and move all requests from the | ||
1098 | * pending queue to the request queue. | ||
1099 | */ | ||
1100 | static void ap_reset(struct ap_device *ap_dev) | ||
1101 | { | ||
1102 | int rc; | ||
1103 | |||
1104 | ap_dev->reset = AP_RESET_IGNORE; | ||
1105 | atomic_sub(ap_dev->queue_count, &ap_poll_requests); | ||
1106 | ap_dev->queue_count = 0; | ||
1107 | list_splice_init(&ap_dev->pendingq, &ap_dev->requestq); | ||
1108 | ap_dev->requestq_count += ap_dev->pendingq_count; | ||
1109 | ap_dev->pendingq_count = 0; | ||
1110 | rc = ap_init_queue(ap_dev->qid); | ||
1111 | if (rc == -ENODEV) | ||
1112 | ap_dev->unregistered = 1; | ||
1113 | } | ||
1114 | |||
1115 | /** | ||
1049 | * Poll all AP devices on the bus in a round robin fashion. Continue | 1116 | * Poll all AP devices on the bus in a round robin fashion. Continue |
1050 | * polling until bit 2^0 of the control flags is not set. If bit 2^1 | 1117 | * polling until bit 2^0 of the control flags is not set. If bit 2^1 |
1051 | * of the control flags has been set arm the poll timer. | 1118 | * of the control flags has been set arm the poll timer. |
@@ -1056,6 +1123,8 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags) | |||
1056 | if (!ap_dev->unregistered) { | 1123 | if (!ap_dev->unregistered) { |
1057 | if (ap_poll_queue(ap_dev, flags)) | 1124 | if (ap_poll_queue(ap_dev, flags)) |
1058 | ap_dev->unregistered = 1; | 1125 | ap_dev->unregistered = 1; |
1126 | if (ap_dev->reset == AP_RESET_DO) | ||
1127 | ap_reset(ap_dev); | ||
1059 | } | 1128 | } |
1060 | spin_unlock(&ap_dev->lock); | 1129 | spin_unlock(&ap_dev->lock); |
1061 | return 0; | 1130 | return 0; |
@@ -1147,6 +1216,17 @@ static void ap_poll_thread_stop(void) | |||
1147 | mutex_unlock(&ap_poll_thread_mutex); | 1216 | mutex_unlock(&ap_poll_thread_mutex); |
1148 | } | 1217 | } |
1149 | 1218 | ||
1219 | /** | ||
1220 | * Handling of request timeouts | ||
1221 | */ | ||
1222 | static void ap_request_timeout(unsigned long data) | ||
1223 | { | ||
1224 | struct ap_device *ap_dev = (struct ap_device *) data; | ||
1225 | |||
1226 | if (ap_dev->reset == AP_RESET_ARMED) | ||
1227 | ap_dev->reset = AP_RESET_DO; | ||
1228 | } | ||
1229 | |||
1150 | static void ap_reset_domain(void) | 1230 | static void ap_reset_domain(void) |
1151 | { | 1231 | { |
1152 | int i; | 1232 | int i; |
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 008559ea742b..87c2d6442875 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define AP_DEVICES 64 /* Number of AP devices. */ | 33 | #define AP_DEVICES 64 /* Number of AP devices. */ |
34 | #define AP_DOMAINS 16 /* Number of AP domains. */ | 34 | #define AP_DOMAINS 16 /* Number of AP domains. */ |
35 | #define AP_MAX_RESET 90 /* Maximum number of resets. */ | 35 | #define AP_MAX_RESET 90 /* Maximum number of resets. */ |
36 | #define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */ | ||
36 | #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ | 37 | #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ |
37 | #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ | 38 | #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ |
38 | 39 | ||
@@ -83,6 +84,13 @@ struct ap_queue_status { | |||
83 | #define AP_DEVICE_TYPE_CEX2A 6 | 84 | #define AP_DEVICE_TYPE_CEX2A 6 |
84 | #define AP_DEVICE_TYPE_CEX2C 7 | 85 | #define AP_DEVICE_TYPE_CEX2C 7 |
85 | 86 | ||
87 | /** | ||
88 | * AP reset flag states | ||
89 | */ | ||
90 | #define AP_RESET_IGNORE 0 /* request timeout will be ignored */ | ||
91 | #define AP_RESET_ARMED 1 /* request timeout timer is active */ | ||
92 | #define AP_RESET_DO 2 /* AP reset required */ | ||
93 | |||
86 | struct ap_device; | 94 | struct ap_device; |
87 | struct ap_message; | 95 | struct ap_message; |
88 | 96 | ||
@@ -95,6 +103,7 @@ struct ap_driver { | |||
95 | /* receive is called from tasklet context */ | 103 | /* receive is called from tasklet context */ |
96 | void (*receive)(struct ap_device *, struct ap_message *, | 104 | void (*receive)(struct ap_device *, struct ap_message *, |
97 | struct ap_message *); | 105 | struct ap_message *); |
106 | int request_timeout; /* request timeout in jiffies */ | ||
98 | }; | 107 | }; |
99 | 108 | ||
100 | #define to_ap_drv(x) container_of((x), struct ap_driver, driver) | 109 | #define to_ap_drv(x) container_of((x), struct ap_driver, driver) |
@@ -112,6 +121,8 @@ struct ap_device { | |||
112 | int queue_depth; /* AP queue depth.*/ | 121 | int queue_depth; /* AP queue depth.*/ |
113 | int device_type; /* AP device type. */ | 122 | int device_type; /* AP device type. */ |
114 | int unregistered; /* marks AP device as unregistered */ | 123 | int unregistered; /* marks AP device as unregistered */ |
124 | struct timer_list timeout; /* Timer for request timeouts. */ | ||
125 | int reset; /* Reset required after req. timeout. */ | ||
115 | 126 | ||
116 | int queue_count; /* # messages currently on AP queue. */ | 127 | int queue_count; /* # messages currently on AP queue. */ |
117 | 128 | ||
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index 5bb13a9d0898..08657f604b8c 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c | |||
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_cex2a_driver = { | |||
70 | .remove = zcrypt_cex2a_remove, | 70 | .remove = zcrypt_cex2a_remove, |
71 | .receive = zcrypt_cex2a_receive, | 71 | .receive = zcrypt_cex2a_receive, |
72 | .ids = zcrypt_cex2a_ids, | 72 | .ids = zcrypt_cex2a_ids, |
73 | .request_timeout = CEX2A_CLEANUP_TIME, | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /** | 76 | /** |
@@ -306,18 +307,13 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, | |||
306 | goto out_free; | 307 | goto out_free; |
307 | init_completion(&work); | 308 | init_completion(&work); |
308 | ap_queue_message(zdev->ap_dev, &ap_msg); | 309 | ap_queue_message(zdev->ap_dev, &ap_msg); |
309 | rc = wait_for_completion_interruptible_timeout( | 310 | rc = wait_for_completion_interruptible(&work); |
310 | &work, CEX2A_CLEANUP_TIME); | 311 | if (rc == 0) |
311 | if (rc > 0) | ||
312 | rc = convert_response(zdev, &ap_msg, mex->outputdata, | 312 | rc = convert_response(zdev, &ap_msg, mex->outputdata, |
313 | mex->outputdatalength); | 313 | mex->outputdatalength); |
314 | else { | 314 | else |
315 | /* Signal pending or message timed out. */ | 315 | /* Signal pending. */ |
316 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 316 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
317 | if (rc == 0) | ||
318 | /* Message timed out. */ | ||
319 | rc = -ETIME; | ||
320 | } | ||
321 | out_free: | 317 | out_free: |
322 | kfree(ap_msg.message); | 318 | kfree(ap_msg.message); |
323 | return rc; | 319 | return rc; |
@@ -348,18 +344,13 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, | |||
348 | goto out_free; | 344 | goto out_free; |
349 | init_completion(&work); | 345 | init_completion(&work); |
350 | ap_queue_message(zdev->ap_dev, &ap_msg); | 346 | ap_queue_message(zdev->ap_dev, &ap_msg); |
351 | rc = wait_for_completion_interruptible_timeout( | 347 | rc = wait_for_completion_interruptible(&work); |
352 | &work, CEX2A_CLEANUP_TIME); | 348 | if (rc == 0) |
353 | if (rc > 0) | ||
354 | rc = convert_response(zdev, &ap_msg, crt->outputdata, | 349 | rc = convert_response(zdev, &ap_msg, crt->outputdata, |
355 | crt->outputdatalength); | 350 | crt->outputdatalength); |
356 | else { | 351 | else |
357 | /* Signal pending or message timed out. */ | 352 | /* Signal pending. */ |
358 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 353 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
359 | if (rc == 0) | ||
360 | /* Message timed out. */ | ||
361 | rc = -ETIME; | ||
362 | } | ||
363 | out_free: | 354 | out_free: |
364 | kfree(ap_msg.message); | 355 | kfree(ap_msg.message); |
365 | return rc; | 356 | return rc; |
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index 818ffe05ac00..6e93b4751782 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_pcica_driver = { | |||
70 | .remove = zcrypt_pcica_remove, | 70 | .remove = zcrypt_pcica_remove, |
71 | .receive = zcrypt_pcica_receive, | 71 | .receive = zcrypt_pcica_receive, |
72 | .ids = zcrypt_pcica_ids, | 72 | .ids = zcrypt_pcica_ids, |
73 | .request_timeout = PCICA_CLEANUP_TIME, | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /** | 76 | /** |
@@ -290,18 +291,13 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev, | |||
290 | goto out_free; | 291 | goto out_free; |
291 | init_completion(&work); | 292 | init_completion(&work); |
292 | ap_queue_message(zdev->ap_dev, &ap_msg); | 293 | ap_queue_message(zdev->ap_dev, &ap_msg); |
293 | rc = wait_for_completion_interruptible_timeout( | 294 | rc = wait_for_completion_interruptible(&work); |
294 | &work, PCICA_CLEANUP_TIME); | 295 | if (rc == 0) |
295 | if (rc > 0) | ||
296 | rc = convert_response(zdev, &ap_msg, mex->outputdata, | 296 | rc = convert_response(zdev, &ap_msg, mex->outputdata, |
297 | mex->outputdatalength); | 297 | mex->outputdatalength); |
298 | else { | 298 | else |
299 | /* Signal pending or message timed out. */ | 299 | /* Signal pending. */ |
300 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 300 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
301 | if (rc == 0) | ||
302 | /* Message timed out. */ | ||
303 | rc = -ETIME; | ||
304 | } | ||
305 | out_free: | 301 | out_free: |
306 | kfree(ap_msg.message); | 302 | kfree(ap_msg.message); |
307 | return rc; | 303 | return rc; |
@@ -332,18 +328,13 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev, | |||
332 | goto out_free; | 328 | goto out_free; |
333 | init_completion(&work); | 329 | init_completion(&work); |
334 | ap_queue_message(zdev->ap_dev, &ap_msg); | 330 | ap_queue_message(zdev->ap_dev, &ap_msg); |
335 | rc = wait_for_completion_interruptible_timeout( | 331 | rc = wait_for_completion_interruptible(&work); |
336 | &work, PCICA_CLEANUP_TIME); | 332 | if (rc == 0) |
337 | if (rc > 0) | ||
338 | rc = convert_response(zdev, &ap_msg, crt->outputdata, | 333 | rc = convert_response(zdev, &ap_msg, crt->outputdata, |
339 | crt->outputdatalength); | 334 | crt->outputdatalength); |
340 | else { | 335 | else |
341 | /* Signal pending or message timed out. */ | 336 | /* Signal pending. */ |
342 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 337 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
343 | if (rc == 0) | ||
344 | /* Message timed out. */ | ||
345 | rc = -ETIME; | ||
346 | } | ||
347 | out_free: | 338 | out_free: |
348 | kfree(ap_msg.message); | 339 | kfree(ap_msg.message); |
349 | return rc; | 340 | return rc; |
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index f295a403b29a..d6d59bf9ac38 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c | |||
@@ -82,6 +82,7 @@ static struct ap_driver zcrypt_pcicc_driver = { | |||
82 | .remove = zcrypt_pcicc_remove, | 82 | .remove = zcrypt_pcicc_remove, |
83 | .receive = zcrypt_pcicc_receive, | 83 | .receive = zcrypt_pcicc_receive, |
84 | .ids = zcrypt_pcicc_ids, | 84 | .ids = zcrypt_pcicc_ids, |
85 | .request_timeout = PCICC_CLEANUP_TIME, | ||
85 | }; | 86 | }; |
86 | 87 | ||
87 | /** | 88 | /** |
@@ -501,18 +502,13 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev, | |||
501 | goto out_free; | 502 | goto out_free; |
502 | init_completion(&work); | 503 | init_completion(&work); |
503 | ap_queue_message(zdev->ap_dev, &ap_msg); | 504 | ap_queue_message(zdev->ap_dev, &ap_msg); |
504 | rc = wait_for_completion_interruptible_timeout( | 505 | rc = wait_for_completion_interruptible(&work); |
505 | &work, PCICC_CLEANUP_TIME); | 506 | if (rc == 0) |
506 | if (rc > 0) | ||
507 | rc = convert_response(zdev, &ap_msg, mex->outputdata, | 507 | rc = convert_response(zdev, &ap_msg, mex->outputdata, |
508 | mex->outputdatalength); | 508 | mex->outputdatalength); |
509 | else { | 509 | else |
510 | /* Signal pending or message timed out. */ | 510 | /* Signal pending. */ |
511 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 511 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
512 | if (rc == 0) | ||
513 | /* Message timed out. */ | ||
514 | rc = -ETIME; | ||
515 | } | ||
516 | out_free: | 512 | out_free: |
517 | free_page((unsigned long) ap_msg.message); | 513 | free_page((unsigned long) ap_msg.message); |
518 | return rc; | 514 | return rc; |
@@ -544,18 +540,13 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev, | |||
544 | goto out_free; | 540 | goto out_free; |
545 | init_completion(&work); | 541 | init_completion(&work); |
546 | ap_queue_message(zdev->ap_dev, &ap_msg); | 542 | ap_queue_message(zdev->ap_dev, &ap_msg); |
547 | rc = wait_for_completion_interruptible_timeout( | 543 | rc = wait_for_completion_interruptible(&work); |
548 | &work, PCICC_CLEANUP_TIME); | 544 | if (rc == 0) |
549 | if (rc > 0) | ||
550 | rc = convert_response(zdev, &ap_msg, crt->outputdata, | 545 | rc = convert_response(zdev, &ap_msg, crt->outputdata, |
551 | crt->outputdatalength); | 546 | crt->outputdatalength); |
552 | else { | 547 | else |
553 | /* Signal pending or message timed out. */ | 548 | /* Signal pending. */ |
554 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 549 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
555 | if (rc == 0) | ||
556 | /* Message timed out. */ | ||
557 | rc = -ETIME; | ||
558 | } | ||
559 | out_free: | 550 | out_free: |
560 | free_page((unsigned long) ap_msg.message); | 551 | free_page((unsigned long) ap_msg.message); |
561 | return rc; | 552 | return rc; |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 252443b6bd1b..64948788d301 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -93,6 +93,7 @@ static struct ap_driver zcrypt_pcixcc_driver = { | |||
93 | .remove = zcrypt_pcixcc_remove, | 93 | .remove = zcrypt_pcixcc_remove, |
94 | .receive = zcrypt_pcixcc_receive, | 94 | .receive = zcrypt_pcixcc_receive, |
95 | .ids = zcrypt_pcixcc_ids, | 95 | .ids = zcrypt_pcixcc_ids, |
96 | .request_timeout = PCIXCC_CLEANUP_TIME, | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | /** | 99 | /** |
@@ -641,18 +642,13 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev, | |||
641 | goto out_free; | 642 | goto out_free; |
642 | init_completion(&resp_type.work); | 643 | init_completion(&resp_type.work); |
643 | ap_queue_message(zdev->ap_dev, &ap_msg); | 644 | ap_queue_message(zdev->ap_dev, &ap_msg); |
644 | rc = wait_for_completion_interruptible_timeout( | 645 | rc = wait_for_completion_interruptible(&resp_type.work); |
645 | &resp_type.work, PCIXCC_CLEANUP_TIME); | 646 | if (rc == 0) |
646 | if (rc > 0) | ||
647 | rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, | 647 | rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, |
648 | mex->outputdatalength); | 648 | mex->outputdatalength); |
649 | else { | 649 | else |
650 | /* Signal pending or message timed out. */ | 650 | /* Signal pending. */ |
651 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 651 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
652 | if (rc == 0) | ||
653 | /* Message timed out. */ | ||
654 | rc = -ETIME; | ||
655 | } | ||
656 | out_free: | 652 | out_free: |
657 | free_page((unsigned long) ap_msg.message); | 653 | free_page((unsigned long) ap_msg.message); |
658 | return rc; | 654 | return rc; |
@@ -685,18 +681,13 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, | |||
685 | goto out_free; | 681 | goto out_free; |
686 | init_completion(&resp_type.work); | 682 | init_completion(&resp_type.work); |
687 | ap_queue_message(zdev->ap_dev, &ap_msg); | 683 | ap_queue_message(zdev->ap_dev, &ap_msg); |
688 | rc = wait_for_completion_interruptible_timeout( | 684 | rc = wait_for_completion_interruptible(&resp_type.work); |
689 | &resp_type.work, PCIXCC_CLEANUP_TIME); | 685 | if (rc == 0) |
690 | if (rc > 0) | ||
691 | rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, | 686 | rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, |
692 | crt->outputdatalength); | 687 | crt->outputdatalength); |
693 | else { | 688 | else |
694 | /* Signal pending or message timed out. */ | 689 | /* Signal pending. */ |
695 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 690 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
696 | if (rc == 0) | ||
697 | /* Message timed out. */ | ||
698 | rc = -ETIME; | ||
699 | } | ||
700 | out_free: | 691 | out_free: |
701 | free_page((unsigned long) ap_msg.message); | 692 | free_page((unsigned long) ap_msg.message); |
702 | return rc; | 693 | return rc; |
@@ -729,17 +720,12 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, | |||
729 | goto out_free; | 720 | goto out_free; |
730 | init_completion(&resp_type.work); | 721 | init_completion(&resp_type.work); |
731 | ap_queue_message(zdev->ap_dev, &ap_msg); | 722 | ap_queue_message(zdev->ap_dev, &ap_msg); |
732 | rc = wait_for_completion_interruptible_timeout( | 723 | rc = wait_for_completion_interruptible(&resp_type.work); |
733 | &resp_type.work, PCIXCC_CLEANUP_TIME); | 724 | if (rc == 0) |
734 | if (rc > 0) | ||
735 | rc = convert_response_xcrb(zdev, &ap_msg, xcRB); | 725 | rc = convert_response_xcrb(zdev, &ap_msg, xcRB); |
736 | else { | 726 | else |
737 | /* Signal pending or message timed out. */ | 727 | /* Signal pending. */ |
738 | ap_cancel_message(zdev->ap_dev, &ap_msg); | 728 | ap_cancel_message(zdev->ap_dev, &ap_msg); |
739 | if (rc == 0) | ||
740 | /* Message timed out. */ | ||
741 | rc = -ETIME; | ||
742 | } | ||
743 | out_free: | 729 | out_free: |
744 | memset(ap_msg.message, 0x0, ap_msg.length); | 730 | memset(ap_msg.message, 0x0, ap_msg.length); |
745 | kfree(ap_msg.message); | 731 | kfree(ap_msg.message); |
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 9f7ad4244f63..1e064c4a4f86 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c | |||
@@ -45,7 +45,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
45 | { | 45 | { |
46 | int blocksize, offset, size,res; | 46 | int blocksize, offset, size,res; |
47 | loff_t i_size; | 47 | loff_t i_size; |
48 | dasd_information_t *info; | 48 | dasd_information2_t *info; |
49 | struct hd_geometry *geo; | 49 | struct hd_geometry *geo; |
50 | char type[5] = {0,}; | 50 | char type[5] = {0,}; |
51 | char name[7] = {0,}; | 51 | char name[7] = {0,}; |
@@ -64,14 +64,17 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
64 | if (i_size == 0) | 64 | if (i_size == 0) |
65 | goto out_exit; | 65 | goto out_exit; |
66 | 66 | ||
67 | if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL) | 67 | info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); |
68 | if (info == NULL) | ||
68 | goto out_exit; | 69 | goto out_exit; |
69 | if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) | 70 | geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL); |
71 | if (geo == NULL) | ||
70 | goto out_nogeo; | 72 | goto out_nogeo; |
71 | if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL) | 73 | label = kmalloc(sizeof(union label_t), GFP_KERNEL); |
74 | if (label == NULL) | ||
72 | goto out_nolab; | 75 | goto out_nolab; |
73 | 76 | ||
74 | if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || | 77 | if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || |
75 | ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) | 78 | ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) |
76 | goto out_freeall; | 79 | goto out_freeall; |
77 | 80 | ||
@@ -96,84 +99,108 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
96 | res = 1; | 99 | res = 1; |
97 | 100 | ||
98 | /* | 101 | /* |
99 | * Three different types: CMS1, VOL1 and LNX1/unlabeled | 102 | * Three different formats: LDL, CDL and unformated disk |
103 | * | ||
104 | * identified by info->format | ||
105 | * | ||
106 | * unformated disks we do not have to care about | ||
100 | */ | 107 | */ |
101 | if (strncmp(type, "CMS1", 4) == 0) { | 108 | if (info->format == DASD_FORMAT_LDL) { |
102 | /* | 109 | if (strncmp(type, "CMS1", 4) == 0) { |
103 | * VM style CMS1 labeled disk | 110 | /* |
104 | */ | 111 | * VM style CMS1 labeled disk |
105 | if (label->cms.disk_offset != 0) { | 112 | */ |
106 | printk("CMS1/%8s(MDSK):", name); | 113 | if (label->cms.disk_offset != 0) { |
107 | /* disk is reserved minidisk */ | 114 | printk("CMS1/%8s(MDSK):", name); |
108 | blocksize = label->cms.block_size; | 115 | /* disk is reserved minidisk */ |
109 | offset = label->cms.disk_offset; | 116 | blocksize = label->cms.block_size; |
110 | size = (label->cms.block_count - 1) * (blocksize >> 9); | 117 | offset = label->cms.disk_offset; |
118 | size = (label->cms.block_count - 1) | ||
119 | * (blocksize >> 9); | ||
120 | } else { | ||
121 | printk("CMS1/%8s:", name); | ||
122 | offset = (info->label_block + 1); | ||
123 | size = i_size >> 9; | ||
124 | } | ||
111 | } else { | 125 | } else { |
112 | printk("CMS1/%8s:", name); | 126 | /* |
127 | * Old style LNX1 or unlabeled disk | ||
128 | */ | ||
129 | if (strncmp(type, "LNX1", 4) == 0) | ||
130 | printk ("LNX1/%8s:", name); | ||
131 | else | ||
132 | printk("(nonl)"); | ||
113 | offset = (info->label_block + 1); | 133 | offset = (info->label_block + 1); |
114 | size = i_size >> 9; | 134 | size = i_size >> 9; |
115 | } | 135 | } |
116 | put_partition(state, 1, offset*(blocksize >> 9), | 136 | put_partition(state, 1, offset*(blocksize >> 9), |
117 | size-offset*(blocksize >> 9)); | 137 | size-offset*(blocksize >> 9)); |
118 | } else if ((strncmp(type, "VOL1", 4) == 0) && | 138 | } else if (info->format == DASD_FORMAT_CDL) { |
119 | (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { | ||
120 | /* | 139 | /* |
121 | * New style VOL1 labeled disk | 140 | * New style CDL formatted disk |
122 | */ | 141 | */ |
123 | unsigned int blk; | 142 | unsigned int blk; |
124 | int counter; | 143 | int counter; |
125 | 144 | ||
126 | printk("VOL1/%8s:", name); | ||
127 | |||
128 | /* get block number and read then go through format1 labels */ | ||
129 | blk = cchhb2blk(&label->vol.vtoc, geo) + 1; | ||
130 | counter = 0; | ||
131 | while ((data = read_dev_sector(bdev, blk*(blocksize/512), | ||
132 | §)) != NULL) { | ||
133 | struct vtoc_format1_label f1; | ||
134 | |||
135 | memcpy(&f1, data, sizeof(struct vtoc_format1_label)); | ||
136 | put_dev_sector(sect); | ||
137 | |||
138 | /* skip FMT4 / FMT5 / FMT7 labels */ | ||
139 | if (f1.DS1FMTID == _ascebc['4'] | ||
140 | || f1.DS1FMTID == _ascebc['5'] | ||
141 | || f1.DS1FMTID == _ascebc['7']) { | ||
142 | blk++; | ||
143 | continue; | ||
144 | } | ||
145 | |||
146 | /* only FMT1 valid at this point */ | ||
147 | if (f1.DS1FMTID != _ascebc['1']) | ||
148 | break; | ||
149 | |||
150 | /* OK, we got valid partition data */ | ||
151 | offset = cchh2blk(&f1.DS1EXT1.llimit, geo); | ||
152 | size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - | ||
153 | offset + geo->sectors; | ||
154 | if (counter >= state->limit) | ||
155 | break; | ||
156 | put_partition(state, counter + 1, | ||
157 | offset * (blocksize >> 9), | ||
158 | size * (blocksize >> 9)); | ||
159 | counter++; | ||
160 | blk++; | ||
161 | } | ||
162 | if (!data) | ||
163 | /* Are we not supposed to report this ? */ | ||
164 | goto out_readerr; | ||
165 | } else { | ||
166 | /* | 145 | /* |
167 | * Old style LNX1 or unlabeled disk | 146 | * check if VOL1 label is available |
147 | * if not, something is wrong, skipping partition detection | ||
168 | */ | 148 | */ |
169 | if (strncmp(type, "LNX1", 4) == 0) | 149 | if (strncmp(type, "VOL1", 4) == 0) { |
170 | printk ("LNX1/%8s:", name); | 150 | printk("VOL1/%8s:", name); |
171 | else | 151 | /* |
172 | printk("(nonl)/%8s:", name); | 152 | * get block number and read then go through format1 |
173 | offset = (info->label_block + 1); | 153 | * labels |
174 | size = i_size >> 9; | 154 | */ |
175 | put_partition(state, 1, offset*(blocksize >> 9), | 155 | blk = cchhb2blk(&label->vol.vtoc, geo) + 1; |
176 | size-offset*(blocksize >> 9)); | 156 | counter = 0; |
157 | data = read_dev_sector(bdev, blk * (blocksize/512), | ||
158 | §); | ||
159 | while (data != NULL) { | ||
160 | struct vtoc_format1_label f1; | ||
161 | |||
162 | memcpy(&f1, data, | ||
163 | sizeof(struct vtoc_format1_label)); | ||
164 | put_dev_sector(sect); | ||
165 | |||
166 | /* skip FMT4 / FMT5 / FMT7 labels */ | ||
167 | if (f1.DS1FMTID == _ascebc['4'] | ||
168 | || f1.DS1FMTID == _ascebc['5'] | ||
169 | || f1.DS1FMTID == _ascebc['7']) { | ||
170 | blk++; | ||
171 | data = read_dev_sector(bdev, blk * | ||
172 | (blocksize/512), | ||
173 | §); | ||
174 | continue; | ||
175 | } | ||
176 | |||
177 | /* only FMT1 valid at this point */ | ||
178 | if (f1.DS1FMTID != _ascebc['1']) | ||
179 | break; | ||
180 | |||
181 | /* OK, we got valid partition data */ | ||
182 | offset = cchh2blk(&f1.DS1EXT1.llimit, geo); | ||
183 | size = cchh2blk(&f1.DS1EXT1.ulimit, geo) - | ||
184 | offset + geo->sectors; | ||
185 | if (counter >= state->limit) | ||
186 | break; | ||
187 | put_partition(state, counter + 1, | ||
188 | offset * (blocksize >> 9), | ||
189 | size * (blocksize >> 9)); | ||
190 | counter++; | ||
191 | blk++; | ||
192 | data = read_dev_sector(bdev, | ||
193 | blk * (blocksize/512), | ||
194 | §); | ||
195 | } | ||
196 | |||
197 | if (!data) | ||
198 | /* Are we not supposed to report this ? */ | ||
199 | goto out_readerr; | ||
200 | } else | ||
201 | printk(KERN_WARNING "Warning, expected Label VOL1 not " | ||
202 | "found, treating as CDL formated Disk"); | ||
203 | |||
177 | } | 204 | } |
178 | 205 | ||
179 | printk("\n"); | 206 | printk("\n"); |
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index c17bdbf22067..ea486952f778 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h | |||
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | typedef struct { | 26 | typedef struct { |
27 | volatile int counter; | 27 | int counter; |
28 | } __attribute__ ((aligned (4))) atomic_t; | 28 | } __attribute__ ((aligned (4))) atomic_t; |
29 | #define ATOMIC_INIT(i) { (i) } | 29 | #define ATOMIC_INIT(i) { (i) } |
30 | 30 | ||
@@ -141,7 +141,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) | |||
141 | 141 | ||
142 | #ifdef __s390x__ | 142 | #ifdef __s390x__ |
143 | typedef struct { | 143 | typedef struct { |
144 | volatile long long counter; | 144 | long long counter; |
145 | } __attribute__ ((aligned (8))) atomic64_t; | 145 | } __attribute__ ((aligned (8))) atomic64_t; |
146 | #define ATOMIC64_INIT(i) { (i) } | 146 | #define ATOMIC64_INIT(i) { (i) } |
147 | 147 | ||
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h index 241756f80df3..021e7c3223ec 100644 --- a/include/asm-s390/cmb.h +++ b/include/asm-s390/cmb.h | |||
@@ -88,7 +88,6 @@ extern u64 cmf_read(struct ccw_device *cdev, int index); | |||
88 | * any | 88 | * any |
89 | **/ | 89 | **/ |
90 | extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data); | 90 | extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data); |
91 | extern void cmf_reset(struct ccw_device *cdev); | ||
92 | 91 | ||
93 | #endif /* __KERNEL__ */ | 92 | #endif /* __KERNEL__ */ |
94 | #endif /* S390_CMB_H */ | 93 | #endif /* S390_CMB_H */ |
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index 5cb480af65d5..3b972d4c6b29 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h | |||
@@ -357,8 +357,8 @@ extern void (*s390_base_ext_handler_fn)(void); | |||
357 | /* | 357 | /* |
358 | * CPU idle notifier chain. | 358 | * CPU idle notifier chain. |
359 | */ | 359 | */ |
360 | #define CPU_IDLE 0 | 360 | #define S390_CPU_IDLE 0 |
361 | #define CPU_NOT_IDLE 1 | 361 | #define S390_CPU_NOT_IDLE 1 |
362 | 362 | ||
363 | struct notifier_block; | 363 | struct notifier_block; |
364 | int register_idle_notifier(struct notifier_block *nb); | 364 | int register_idle_notifier(struct notifier_block *nb); |
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h index 21ed64773210..cb9faf1ea5cf 100644 --- a/include/asm-s390/sclp.h +++ b/include/asm-s390/sclp.h | |||
@@ -11,29 +11,6 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <asm/chpid.h> | 12 | #include <asm/chpid.h> |
13 | 13 | ||
14 | struct sccb_header { | ||
15 | u16 length; | ||
16 | u8 function_code; | ||
17 | u8 control_mask[3]; | ||
18 | u16 response_code; | ||
19 | } __attribute__((packed)); | ||
20 | |||
21 | #define LOADPARM_LEN 8 | ||
22 | |||
23 | struct sclp_readinfo_sccb { | ||
24 | struct sccb_header header; /* 0-7 */ | ||
25 | u16 rnmax; /* 8-9 */ | ||
26 | u8 rnsize; /* 10 */ | ||
27 | u8 _reserved0[24 - 11]; /* 11-23 */ | ||
28 | u8 loadparm[LOADPARM_LEN]; /* 24-31 */ | ||
29 | u8 _reserved1[91 - 32]; /* 32-90 */ | ||
30 | u8 flags; /* 91 */ | ||
31 | u8 _reserved2[100 - 92]; /* 92-99 */ | ||
32 | u32 rnsize2; /* 100-103 */ | ||
33 | u64 rnmax2; /* 104-111 */ | ||
34 | u8 _reserved3[4096 - 112]; /* 112-4095 */ | ||
35 | } __attribute__((packed, aligned(4096))); | ||
36 | |||
37 | #define SCLP_CHP_INFO_MASK_SIZE 32 | 14 | #define SCLP_CHP_INFO_MASK_SIZE 32 |
38 | 15 | ||
39 | struct sclp_chp_info { | 16 | struct sclp_chp_info { |
@@ -42,12 +19,22 @@ struct sclp_chp_info { | |||
42 | u8 configured[SCLP_CHP_INFO_MASK_SIZE]; | 19 | u8 configured[SCLP_CHP_INFO_MASK_SIZE]; |
43 | }; | 20 | }; |
44 | 21 | ||
45 | extern struct sclp_readinfo_sccb s390_readinfo_sccb; | 22 | #define LOADPARM_LEN 8 |
46 | extern void sclp_readinfo_early(void); | 23 | |
47 | extern int sclp_sdias_blk_count(void); | 24 | struct sclp_ipl_info { |
48 | extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks); | 25 | int is_valid; |
49 | extern int sclp_chp_configure(struct chp_id chpid); | 26 | int has_dump; |
50 | extern int sclp_chp_deconfigure(struct chp_id chpid); | 27 | char loadparm[LOADPARM_LEN]; |
51 | extern int sclp_chp_read_info(struct sclp_chp_info *info); | 28 | }; |
29 | |||
30 | void sclp_readinfo_early(void); | ||
31 | void sclp_facilities_detect(void); | ||
32 | unsigned long long sclp_memory_detect(void); | ||
33 | int sclp_sdias_blk_count(void); | ||
34 | int sclp_sdias_copy(void *dest, int blk_num, int nr_blks); | ||
35 | int sclp_chp_configure(struct chp_id chpid); | ||
36 | int sclp_chp_deconfigure(struct chp_id chpid); | ||
37 | int sclp_chp_read_info(struct sclp_chp_info *info); | ||
38 | void sclp_get_ipl_info(struct sclp_ipl_info *info); | ||
52 | 39 | ||
53 | #endif /* _ASM_S390_SCLP_H */ | 40 | #endif /* _ASM_S390_SCLP_H */ |
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h index 8ca8c77b2d04..4e16aede4b06 100644 --- a/include/asm-s390/sfp-machine.h +++ b/include/asm-s390/sfp-machine.h | |||
@@ -27,9 +27,9 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | #define _FP_W_TYPE_SIZE 32 | 29 | #define _FP_W_TYPE_SIZE 32 |
30 | #define _FP_W_TYPE unsigned long | 30 | #define _FP_W_TYPE unsigned int |
31 | #define _FP_WS_TYPE signed long | 31 | #define _FP_WS_TYPE signed int |
32 | #define _FP_I_TYPE long | 32 | #define _FP_I_TYPE int |
33 | 33 | ||
34 | #define _FP_MUL_MEAT_S(R,X,Y) \ | 34 | #define _FP_MUL_MEAT_S(R,X,Y) \ |
35 | _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) | 35 | _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) |
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h index 8cabcd23d976..0addc6466d95 100644 --- a/include/asm-s390/sfp-util.h +++ b/include/asm-s390/sfp-util.h | |||
@@ -51,6 +51,16 @@ | |||
51 | wl = __wl; \ | 51 | wl = __wl; \ |
52 | }) | 52 | }) |
53 | 53 | ||
54 | #ifdef __s390x__ | ||
55 | #define udiv_qrnnd(q, r, n1, n0, d) \ | ||
56 | do { unsigned long __n; \ | ||
57 | unsigned int __r, __d; \ | ||
58 | __n = ((unsigned long)(n1) << 32) + n0; \ | ||
59 | __d = (d); \ | ||
60 | (q) = __n / __d; \ | ||
61 | (r) = __n % __d; \ | ||
62 | } while (0) | ||
63 | #else | ||
54 | #define udiv_qrnnd(q, r, n1, n0, d) \ | 64 | #define udiv_qrnnd(q, r, n1, n0, d) \ |
55 | do { unsigned int __r; \ | 65 | do { unsigned int __r; \ |
56 | (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ | 66 | (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ |
@@ -58,6 +68,7 @@ | |||
58 | } while (0) | 68 | } while (0) |
59 | extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int, | 69 | extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int, |
60 | unsigned int , unsigned int); | 70 | unsigned int , unsigned int); |
71 | #endif | ||
61 | 72 | ||
62 | #define UDIV_NEEDS_NORMALIZATION 0 | 73 | #define UDIV_NEEDS_NORMALIZATION 0 |
63 | 74 | ||