diff options
-rw-r--r-- | arch/s390/appldata/appldata.h | 1 | ||||
-rw-r--r-- | arch/s390/appldata/appldata_base.c | 74 | ||||
-rw-r--r-- | arch/s390/appldata/appldata_mem.c | 1 | ||||
-rw-r--r-- | arch/s390/appldata/appldata_net_sum.c | 1 | ||||
-rw-r--r-- | arch/s390/appldata/appldata_os.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 120 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 114 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 6 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 56 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 1 | ||||
-rw-r--r-- | arch/s390/mm/cmm.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_id.c | 45 | ||||
-rw-r--r-- | include/asm-s390/system.h | 5 | ||||
-rw-r--r-- | include/linux/sysctl.h | 6 | ||||
-rw-r--r-- | kernel/sysctl_check.c | 14 | ||||
-rw-r--r-- | mm/rmap.c | 9 | ||||
-rw-r--r-- | net/iucv/iucv.c | 107 |
20 files changed, 263 insertions, 307 deletions
diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h index 4069b81f7f1d..db3ae8505103 100644 --- a/arch/s390/appldata/appldata.h +++ b/arch/s390/appldata/appldata.h | |||
@@ -45,7 +45,6 @@ struct appldata_ops { | |||
45 | int active; /* monitoring status */ | 45 | int active; /* monitoring status */ |
46 | 46 | ||
47 | /* fill in from here */ | 47 | /* fill in from here */ |
48 | unsigned int ctl_nr; /* sysctl ID */ | ||
49 | char name[APPLDATA_PROC_NAME_LENGTH]; /* name of /proc fs node */ | 48 | char name[APPLDATA_PROC_NAME_LENGTH]; /* name of /proc fs node */ |
50 | unsigned char record_nr; /* Record Nr. for Product ID */ | 49 | unsigned char record_nr; /* Record Nr. for Product ID */ |
51 | void (*callback)(void *data); /* callback function */ | 50 | void (*callback)(void *data); /* callback function */ |
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index ac61cf43a7d9..655d52543e2d 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
@@ -53,29 +53,26 @@ static int appldata_interval_handler(ctl_table *ctl, int write, | |||
53 | static struct ctl_table_header *appldata_sysctl_header; | 53 | static struct ctl_table_header *appldata_sysctl_header; |
54 | static struct ctl_table appldata_table[] = { | 54 | static struct ctl_table appldata_table[] = { |
55 | { | 55 | { |
56 | .ctl_name = CTL_APPLDATA_TIMER, | ||
57 | .procname = "timer", | 56 | .procname = "timer", |
58 | .mode = S_IRUGO | S_IWUSR, | 57 | .mode = S_IRUGO | S_IWUSR, |
59 | .proc_handler = &appldata_timer_handler, | 58 | .proc_handler = &appldata_timer_handler, |
60 | }, | 59 | }, |
61 | { | 60 | { |
62 | .ctl_name = CTL_APPLDATA_INTERVAL, | ||
63 | .procname = "interval", | 61 | .procname = "interval", |
64 | .mode = S_IRUGO | S_IWUSR, | 62 | .mode = S_IRUGO | S_IWUSR, |
65 | .proc_handler = &appldata_interval_handler, | 63 | .proc_handler = &appldata_interval_handler, |
66 | }, | 64 | }, |
67 | { .ctl_name = 0 } | 65 | { }, |
68 | }; | 66 | }; |
69 | 67 | ||
70 | static struct ctl_table appldata_dir_table[] = { | 68 | static struct ctl_table appldata_dir_table[] = { |
71 | { | 69 | { |
72 | .ctl_name = CTL_APPLDATA, | ||
73 | .procname = appldata_proc_name, | 70 | .procname = appldata_proc_name, |
74 | .maxlen = 0, | 71 | .maxlen = 0, |
75 | .mode = S_IRUGO | S_IXUGO, | 72 | .mode = S_IRUGO | S_IXUGO, |
76 | .child = appldata_table, | 73 | .child = appldata_table, |
77 | }, | 74 | }, |
78 | { .ctl_name = 0 } | 75 | { }, |
79 | }; | 76 | }; |
80 | 77 | ||
81 | /* | 78 | /* |
@@ -441,75 +438,38 @@ out: | |||
441 | */ | 438 | */ |
442 | int appldata_register_ops(struct appldata_ops *ops) | 439 | int appldata_register_ops(struct appldata_ops *ops) |
443 | { | 440 | { |
444 | struct list_head *lh; | 441 | if ((ops->size > APPLDATA_MAX_REC_SIZE) || (ops->size < 0)) |
445 | struct appldata_ops *tmp_ops; | 442 | return -EINVAL; |
446 | int i; | ||
447 | |||
448 | i = 0; | ||
449 | 443 | ||
450 | if ((ops->size > APPLDATA_MAX_REC_SIZE) || | 444 | ops->ctl_table = kzalloc(4 * sizeof(struct ctl_table), GFP_KERNEL); |
451 | (ops->size < 0)){ | 445 | if (!ops->ctl_table) |
452 | P_ERROR("Invalid size of %s record = %i, maximum = %i!\n", | ||
453 | ops->name, ops->size, APPLDATA_MAX_REC_SIZE); | ||
454 | return -ENOMEM; | ||
455 | } | ||
456 | if ((ops->ctl_nr == CTL_APPLDATA) || | ||
457 | (ops->ctl_nr == CTL_APPLDATA_TIMER) || | ||
458 | (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) { | ||
459 | P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr); | ||
460 | return -EBUSY; | ||
461 | } | ||
462 | ops->ctl_table = kzalloc(4*sizeof(struct ctl_table), GFP_KERNEL); | ||
463 | if (ops->ctl_table == NULL) { | ||
464 | P_ERROR("Not enough memory for %s ctl_table!\n", ops->name); | ||
465 | return -ENOMEM; | 446 | return -ENOMEM; |
466 | } | ||
467 | 447 | ||
468 | spin_lock(&appldata_ops_lock); | 448 | spin_lock(&appldata_ops_lock); |
469 | list_for_each(lh, &appldata_ops_list) { | ||
470 | tmp_ops = list_entry(lh, struct appldata_ops, list); | ||
471 | P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n", | ||
472 | ++i, tmp_ops->name, tmp_ops->ctl_nr); | ||
473 | P_DEBUG("Comparing %s (ctl %i) with %s (ctl %i)\n", | ||
474 | tmp_ops->name, tmp_ops->ctl_nr, ops->name, | ||
475 | ops->ctl_nr); | ||
476 | if (strncmp(tmp_ops->name, ops->name, | ||
477 | APPLDATA_PROC_NAME_LENGTH) == 0) { | ||
478 | P_ERROR("Name \"%s\" already registered!\n", ops->name); | ||
479 | kfree(ops->ctl_table); | ||
480 | spin_unlock(&appldata_ops_lock); | ||
481 | return -EBUSY; | ||
482 | } | ||
483 | if (tmp_ops->ctl_nr == ops->ctl_nr) { | ||
484 | P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr); | ||
485 | kfree(ops->ctl_table); | ||
486 | spin_unlock(&appldata_ops_lock); | ||
487 | return -EBUSY; | ||
488 | } | ||
489 | } | ||
490 | list_add(&ops->list, &appldata_ops_list); | 449 | list_add(&ops->list, &appldata_ops_list); |
491 | spin_unlock(&appldata_ops_lock); | 450 | spin_unlock(&appldata_ops_lock); |
492 | 451 | ||
493 | ops->ctl_table[0].ctl_name = CTL_APPLDATA; | ||
494 | ops->ctl_table[0].procname = appldata_proc_name; | 452 | ops->ctl_table[0].procname = appldata_proc_name; |
495 | ops->ctl_table[0].maxlen = 0; | 453 | ops->ctl_table[0].maxlen = 0; |
496 | ops->ctl_table[0].mode = S_IRUGO | S_IXUGO; | 454 | ops->ctl_table[0].mode = S_IRUGO | S_IXUGO; |
497 | ops->ctl_table[0].child = &ops->ctl_table[2]; | 455 | ops->ctl_table[0].child = &ops->ctl_table[2]; |
498 | 456 | ||
499 | ops->ctl_table[1].ctl_name = 0; | ||
500 | |||
501 | ops->ctl_table[2].ctl_name = ops->ctl_nr; | ||
502 | ops->ctl_table[2].procname = ops->name; | 457 | ops->ctl_table[2].procname = ops->name; |
503 | ops->ctl_table[2].mode = S_IRUGO | S_IWUSR; | 458 | ops->ctl_table[2].mode = S_IRUGO | S_IWUSR; |
504 | ops->ctl_table[2].proc_handler = appldata_generic_handler; | 459 | ops->ctl_table[2].proc_handler = appldata_generic_handler; |
505 | ops->ctl_table[2].data = ops; | 460 | ops->ctl_table[2].data = ops; |
506 | 461 | ||
507 | ops->ctl_table[3].ctl_name = 0; | ||
508 | |||
509 | ops->sysctl_header = register_sysctl_table(ops->ctl_table); | 462 | ops->sysctl_header = register_sysctl_table(ops->ctl_table); |
510 | 463 | if (!ops->sysctl_header) | |
464 | goto out; | ||
511 | P_INFO("%s-ops registered!\n", ops->name); | 465 | P_INFO("%s-ops registered!\n", ops->name); |
512 | return 0; | 466 | return 0; |
467 | out: | ||
468 | spin_lock(&appldata_ops_lock); | ||
469 | list_del(&ops->list); | ||
470 | spin_unlock(&appldata_ops_lock); | ||
471 | kfree(ops->ctl_table); | ||
472 | return -ENOMEM; | ||
513 | } | 473 | } |
514 | 474 | ||
515 | /* | 475 | /* |
@@ -519,15 +479,11 @@ int appldata_register_ops(struct appldata_ops *ops) | |||
519 | */ | 479 | */ |
520 | void appldata_unregister_ops(struct appldata_ops *ops) | 480 | void appldata_unregister_ops(struct appldata_ops *ops) |
521 | { | 481 | { |
522 | void *table; | ||
523 | spin_lock(&appldata_ops_lock); | 482 | spin_lock(&appldata_ops_lock); |
524 | list_del(&ops->list); | 483 | list_del(&ops->list); |
525 | /* at that point any incoming access will fail */ | ||
526 | table = ops->ctl_table; | ||
527 | ops->ctl_table = NULL; | ||
528 | spin_unlock(&appldata_ops_lock); | 484 | spin_unlock(&appldata_ops_lock); |
529 | unregister_sysctl_table(ops->sysctl_header); | 485 | unregister_sysctl_table(ops->sysctl_header); |
530 | kfree(table); | 486 | kfree(ops->ctl_table); |
531 | P_INFO("%s-ops unregistered!\n", ops->name); | 487 | P_INFO("%s-ops unregistered!\n", ops->name); |
532 | } | 488 | } |
533 | /********************** module-ops management <END> **************************/ | 489 | /********************** module-ops management <END> **************************/ |
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index 697eb30a68a3..51181ccdb87b 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c | |||
@@ -147,7 +147,6 @@ static void appldata_get_mem_data(void *data) | |||
147 | 147 | ||
148 | 148 | ||
149 | static struct appldata_ops ops = { | 149 | static struct appldata_ops ops = { |
150 | .ctl_nr = CTL_APPLDATA_MEM, | ||
151 | .name = "mem", | 150 | .name = "mem", |
152 | .record_nr = APPLDATA_RECORD_MEM_ID, | 151 | .record_nr = APPLDATA_RECORD_MEM_ID, |
153 | .size = sizeof(struct appldata_mem_data), | 152 | .size = sizeof(struct appldata_mem_data), |
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 6c1815a47714..4d8344336001 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c | |||
@@ -142,7 +142,6 @@ static void appldata_get_net_sum_data(void *data) | |||
142 | 142 | ||
143 | 143 | ||
144 | static struct appldata_ops ops = { | 144 | static struct appldata_ops ops = { |
145 | .ctl_nr = CTL_APPLDATA_NET_SUM, | ||
146 | .name = "net_sum", | 145 | .name = "net_sum", |
147 | .record_nr = APPLDATA_RECORD_NET_SUM_ID, | 146 | .record_nr = APPLDATA_RECORD_NET_SUM_ID, |
148 | .size = sizeof(struct appldata_net_sum_data), | 147 | .size = sizeof(struct appldata_net_sum_data), |
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 76a15523ae9e..6b3eafe10453 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c | |||
@@ -82,7 +82,6 @@ struct appldata_os_data { | |||
82 | static struct appldata_os_data *appldata_os_data; | 82 | static struct appldata_os_data *appldata_os_data; |
83 | 83 | ||
84 | static struct appldata_ops ops = { | 84 | static struct appldata_ops ops = { |
85 | .ctl_nr = CTL_APPLDATA_OS, | ||
86 | .name = "os", | 85 | .name = "os", |
87 | .record_nr = APPLDATA_RECORD_OS_ID, | 86 | .record_nr = APPLDATA_RECORD_OS_ID, |
88 | .owner = THIS_MODULE, | 87 | .owner = THIS_MODULE, |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 8bf4ae1150be..1b3af7dab816 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -200,7 +200,7 @@ static noinline __init void find_memory_chunks(unsigned long memsize) | |||
200 | cc = __tprot(addr); | 200 | cc = __tprot(addr); |
201 | while (cc == old_cc) { | 201 | while (cc == old_cc) { |
202 | addr += CHUNK_INCR; | 202 | addr += CHUNK_INCR; |
203 | if (addr >= memsize) | 203 | if (memsize && addr >= memsize) |
204 | break; | 204 | break; |
205 | #ifndef CONFIG_64BIT | 205 | #ifndef CONFIG_64BIT |
206 | if (addr == ADDR2G) | 206 | if (addr == ADDR2G) |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 139ca153d5cc..b2b2edc40eb1 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -69,13 +69,31 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
69 | basr %r14,%r1 | 69 | basr %r14,%r1 |
70 | .endm | 70 | .endm |
71 | 71 | ||
72 | .macro LOCKDEP_SYS_EXIT | 72 | .macro TRACE_IRQS_CHECK |
73 | l %r1,BASED(.Llockdep_sys_exit) | 73 | tm SP_PSW(%r15),0x03 # irqs enabled? |
74 | jz 0f | ||
75 | l %r1,BASED(.Ltrace_irq_on) | ||
74 | basr %r14,%r1 | 76 | basr %r14,%r1 |
77 | j 1f | ||
78 | 0: l %r1,BASED(.Ltrace_irq_off) | ||
79 | basr %r14,%r1 | ||
80 | 1: | ||
75 | .endm | 81 | .endm |
76 | #else | 82 | #else |
77 | #define TRACE_IRQS_ON | 83 | #define TRACE_IRQS_ON |
78 | #define TRACE_IRQS_OFF | 84 | #define TRACE_IRQS_OFF |
85 | #define TRACE_IRQS_CHECK | ||
86 | #endif | ||
87 | |||
88 | #ifdef CONFIG_LOCKDEP | ||
89 | .macro LOCKDEP_SYS_EXIT | ||
90 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
91 | jz 0f | ||
92 | l %r1,BASED(.Llockdep_sys_exit) | ||
93 | basr %r14,%r1 | ||
94 | 0: | ||
95 | .endm | ||
96 | #else | ||
79 | #define LOCKDEP_SYS_EXIT | 97 | #define LOCKDEP_SYS_EXIT |
80 | #endif | 98 | #endif |
81 | 99 | ||
@@ -234,8 +252,6 @@ sysc_saveall: | |||
234 | lh %r7,0x8a # get svc number from lowcore | 252 | lh %r7,0x8a # get svc number from lowcore |
235 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 253 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
236 | sysc_vtime: | 254 | sysc_vtime: |
237 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | ||
238 | bz BASED(sysc_do_svc) | ||
239 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 255 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
240 | sysc_stime: | 256 | sysc_stime: |
241 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 257 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
@@ -263,19 +279,34 @@ sysc_do_restart: | |||
263 | 279 | ||
264 | sysc_return: | 280 | sysc_return: |
265 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 281 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
266 | bno BASED(sysc_leave) | 282 | bno BASED(sysc_restore) |
267 | tm __TI_flags+3(%r9),_TIF_WORK_SVC | 283 | tm __TI_flags+3(%r9),_TIF_WORK_SVC |
268 | bnz BASED(sysc_work) # there is work to do (signals etc.) | 284 | bnz BASED(sysc_work) # there is work to do (signals etc.) |
285 | sysc_restore: | ||
286 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
287 | la %r1,BASED(sysc_restore_trace_psw) | ||
288 | lpsw 0(%r1) | ||
289 | sysc_restore_trace: | ||
290 | TRACE_IRQS_CHECK | ||
269 | LOCKDEP_SYS_EXIT | 291 | LOCKDEP_SYS_EXIT |
292 | #endif | ||
270 | sysc_leave: | 293 | sysc_leave: |
271 | RESTORE_ALL __LC_RETURN_PSW,1 | 294 | RESTORE_ALL __LC_RETURN_PSW,1 |
295 | sysc_done: | ||
296 | |||
297 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
298 | .align 8 | ||
299 | .globl sysc_restore_trace_psw | ||
300 | sysc_restore_trace_psw: | ||
301 | .long 0, sysc_restore_trace + 0x80000000 | ||
302 | #endif | ||
272 | 303 | ||
273 | # | 304 | # |
274 | # recheck if there is more work to do | 305 | # recheck if there is more work to do |
275 | # | 306 | # |
276 | sysc_work_loop: | 307 | sysc_work_loop: |
277 | tm __TI_flags+3(%r9),_TIF_WORK_SVC | 308 | tm __TI_flags+3(%r9),_TIF_WORK_SVC |
278 | bz BASED(sysc_leave) # there is no work to do | 309 | bz BASED(sysc_restore) # there is no work to do |
279 | # | 310 | # |
280 | # One of the work bits is on. Find out which one. | 311 | # One of the work bits is on. Find out which one. |
281 | # | 312 | # |
@@ -290,8 +321,8 @@ sysc_work: | |||
290 | bo BASED(sysc_restart) | 321 | bo BASED(sysc_restart) |
291 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP | 322 | tm __TI_flags+3(%r9),_TIF_SINGLE_STEP |
292 | bo BASED(sysc_singlestep) | 323 | bo BASED(sysc_singlestep) |
293 | LOCKDEP_SYS_EXIT | 324 | b BASED(sysc_restore) |
294 | b BASED(sysc_leave) | 325 | sysc_work_done: |
295 | 326 | ||
296 | # | 327 | # |
297 | # _TIF_NEED_RESCHED is set, call schedule | 328 | # _TIF_NEED_RESCHED is set, call schedule |
@@ -458,6 +489,7 @@ pgm_check_handler: | |||
458 | pgm_no_vtime: | 489 | pgm_no_vtime: |
459 | #endif | 490 | #endif |
460 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 491 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
492 | TRACE_IRQS_OFF | ||
461 | l %r3,__LC_PGM_ILC # load program interruption code | 493 | l %r3,__LC_PGM_ILC # load program interruption code |
462 | la %r8,0x7f | 494 | la %r8,0x7f |
463 | nr %r8,%r3 | 495 | nr %r8,%r3 |
@@ -497,6 +529,7 @@ pgm_per_std: | |||
497 | pgm_no_vtime2: | 529 | pgm_no_vtime2: |
498 | #endif | 530 | #endif |
499 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 531 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
532 | TRACE_IRQS_OFF | ||
500 | l %r1,__TI_task(%r9) | 533 | l %r1,__TI_task(%r9) |
501 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID | 534 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID |
502 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS | 535 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS |
@@ -517,15 +550,13 @@ pgm_svcper: | |||
517 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 550 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
518 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 551 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
519 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 552 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
520 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | ||
521 | bz BASED(pgm_no_vtime3) | ||
522 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 553 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
523 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 554 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
524 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 555 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
525 | pgm_no_vtime3: | ||
526 | #endif | 556 | #endif |
527 | lh %r7,0x8a # get svc number from lowcore | 557 | lh %r7,0x8a # get svc number from lowcore |
528 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 558 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
559 | TRACE_IRQS_OFF | ||
529 | l %r1,__TI_task(%r9) | 560 | l %r1,__TI_task(%r9) |
530 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID | 561 | mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID |
531 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS | 562 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS |
@@ -542,7 +573,7 @@ kernel_per: | |||
542 | mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check | 573 | mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check |
543 | la %r2,SP_PTREGS(%r15) # address of register-save area | 574 | la %r2,SP_PTREGS(%r15) # address of register-save area |
544 | l %r1,BASED(.Lhandle_per) # load adr. of per handler | 575 | l %r1,BASED(.Lhandle_per) # load adr. of per handler |
545 | la %r14,BASED(sysc_leave) # load adr. of system return | 576 | la %r14,BASED(sysc_restore)# load adr. of system return |
546 | br %r1 # branch to do_single_step | 577 | br %r1 # branch to do_single_step |
547 | 578 | ||
548 | /* | 579 | /* |
@@ -569,26 +600,38 @@ io_no_vtime: | |||
569 | l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ | 600 | l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ |
570 | la %r2,SP_PTREGS(%r15) # address of register-save area | 601 | la %r2,SP_PTREGS(%r15) # address of register-save area |
571 | basr %r14,%r1 # branch to standard irq handler | 602 | basr %r14,%r1 # branch to standard irq handler |
572 | TRACE_IRQS_ON | ||
573 | |||
574 | io_return: | 603 | io_return: |
575 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 604 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
576 | #ifdef CONFIG_PREEMPT | 605 | #ifdef CONFIG_PREEMPT |
577 | bno BASED(io_preempt) # no -> check for preemptive scheduling | 606 | bno BASED(io_preempt) # no -> check for preemptive scheduling |
578 | #else | 607 | #else |
579 | bno BASED(io_leave) # no-> skip resched & signal | 608 | bno BASED(io_restore) # no-> skip resched & signal |
580 | #endif | 609 | #endif |
581 | tm __TI_flags+3(%r9),_TIF_WORK_INT | 610 | tm __TI_flags+3(%r9),_TIF_WORK_INT |
582 | bnz BASED(io_work) # there is work to do (signals etc.) | 611 | bnz BASED(io_work) # there is work to do (signals etc.) |
612 | io_restore: | ||
613 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
614 | la %r1,BASED(io_restore_trace_psw) | ||
615 | lpsw 0(%r1) | ||
616 | io_restore_trace: | ||
617 | TRACE_IRQS_CHECK | ||
583 | LOCKDEP_SYS_EXIT | 618 | LOCKDEP_SYS_EXIT |
619 | #endif | ||
584 | io_leave: | 620 | io_leave: |
585 | RESTORE_ALL __LC_RETURN_PSW,0 | 621 | RESTORE_ALL __LC_RETURN_PSW,0 |
586 | io_done: | 622 | io_done: |
587 | 623 | ||
624 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
625 | .align 8 | ||
626 | .globl io_restore_trace_psw | ||
627 | io_restore_trace_psw: | ||
628 | .long 0, io_restore_trace + 0x80000000 | ||
629 | #endif | ||
630 | |||
588 | #ifdef CONFIG_PREEMPT | 631 | #ifdef CONFIG_PREEMPT |
589 | io_preempt: | 632 | io_preempt: |
590 | icm %r0,15,__TI_precount(%r9) | 633 | icm %r0,15,__TI_precount(%r9) |
591 | bnz BASED(io_leave) | 634 | bnz BASED(io_restore) |
592 | l %r1,SP_R15(%r15) | 635 | l %r1,SP_R15(%r15) |
593 | s %r1,BASED(.Lc_spsize) | 636 | s %r1,BASED(.Lc_spsize) |
594 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) | 637 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) |
@@ -596,14 +639,10 @@ io_preempt: | |||
596 | lr %r15,%r1 | 639 | lr %r15,%r1 |
597 | io_resume_loop: | 640 | io_resume_loop: |
598 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED | 641 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED |
599 | bno BASED(io_leave) | 642 | bno BASED(io_restore) |
600 | mvc __TI_precount(4,%r9),BASED(.Lc_pactive) | 643 | l %r1,BASED(.Lpreempt_schedule_irq) |
601 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 644 | la %r14,BASED(io_resume_loop) |
602 | l %r1,BASED(.Lschedule) | 645 | br %r1 # call schedule |
603 | basr %r14,%r1 # call schedule | ||
604 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | ||
605 | xc __TI_precount(4,%r9),__TI_precount(%r9) | ||
606 | b BASED(io_resume_loop) | ||
607 | #endif | 646 | #endif |
608 | 647 | ||
609 | # | 648 | # |
@@ -627,40 +666,42 @@ io_work_loop: | |||
627 | bo BASED(io_reschedule) | 666 | bo BASED(io_reschedule) |
628 | tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) | 667 | tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) |
629 | bnz BASED(io_sigpending) | 668 | bnz BASED(io_sigpending) |
630 | LOCKDEP_SYS_EXIT | 669 | b BASED(io_restore) |
631 | b BASED(io_leave) | 670 | io_work_done: |
632 | 671 | ||
633 | # | 672 | # |
634 | # _TIF_MCCK_PENDING is set, call handler | 673 | # _TIF_MCCK_PENDING is set, call handler |
635 | # | 674 | # |
636 | io_mcck_pending: | 675 | io_mcck_pending: |
637 | TRACE_IRQS_OFF | ||
638 | l %r1,BASED(.Ls390_handle_mcck) | 676 | l %r1,BASED(.Ls390_handle_mcck) |
639 | basr %r14,%r1 # TIF bit will be cleared by handler | 677 | basr %r14,%r1 # TIF bit will be cleared by handler |
640 | TRACE_IRQS_ON | ||
641 | b BASED(io_work_loop) | 678 | b BASED(io_work_loop) |
642 | 679 | ||
643 | # | 680 | # |
644 | # _TIF_NEED_RESCHED is set, call schedule | 681 | # _TIF_NEED_RESCHED is set, call schedule |
645 | # | 682 | # |
646 | io_reschedule: | 683 | io_reschedule: |
684 | TRACE_IRQS_ON | ||
647 | l %r1,BASED(.Lschedule) | 685 | l %r1,BASED(.Lschedule) |
648 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 686 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
649 | basr %r14,%r1 # call scheduler | 687 | basr %r14,%r1 # call scheduler |
650 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 688 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
689 | TRACE_IRQS_OFF | ||
651 | tm __TI_flags+3(%r9),_TIF_WORK_INT | 690 | tm __TI_flags+3(%r9),_TIF_WORK_INT |
652 | bz BASED(io_leave) # there is no work to do | 691 | bz BASED(io_restore) # there is no work to do |
653 | b BASED(io_work_loop) | 692 | b BASED(io_work_loop) |
654 | 693 | ||
655 | # | 694 | # |
656 | # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal | 695 | # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal |
657 | # | 696 | # |
658 | io_sigpending: | 697 | io_sigpending: |
698 | TRACE_IRQS_ON | ||
659 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 699 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
660 | la %r2,SP_PTREGS(%r15) # load pt_regs | 700 | la %r2,SP_PTREGS(%r15) # load pt_regs |
661 | l %r1,BASED(.Ldo_signal) | 701 | l %r1,BASED(.Ldo_signal) |
662 | basr %r14,%r1 # call do_signal | 702 | basr %r14,%r1 # call do_signal |
663 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 703 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
704 | TRACE_IRQS_OFF | ||
664 | b BASED(io_work_loop) | 705 | b BASED(io_work_loop) |
665 | 706 | ||
666 | /* | 707 | /* |
@@ -688,7 +729,6 @@ ext_no_vtime: | |||
688 | lh %r3,__LC_EXT_INT_CODE # get interruption code | 729 | lh %r3,__LC_EXT_INT_CODE # get interruption code |
689 | l %r1,BASED(.Ldo_extint) | 730 | l %r1,BASED(.Ldo_extint) |
690 | basr %r14,%r1 | 731 | basr %r14,%r1 |
691 | TRACE_IRQS_ON | ||
692 | b BASED(io_return) | 732 | b BASED(io_return) |
693 | 733 | ||
694 | __critical_end: | 734 | __critical_end: |
@@ -853,15 +893,15 @@ cleanup_table_system_call: | |||
853 | cleanup_table_sysc_return: | 893 | cleanup_table_sysc_return: |
854 | .long sysc_return + 0x80000000, sysc_leave + 0x80000000 | 894 | .long sysc_return + 0x80000000, sysc_leave + 0x80000000 |
855 | cleanup_table_sysc_leave: | 895 | cleanup_table_sysc_leave: |
856 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 | 896 | .long sysc_leave + 0x80000000, sysc_done + 0x80000000 |
857 | cleanup_table_sysc_work_loop: | 897 | cleanup_table_sysc_work_loop: |
858 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 | 898 | .long sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000 |
859 | cleanup_table_io_return: | 899 | cleanup_table_io_return: |
860 | .long io_return + 0x80000000, io_leave + 0x80000000 | 900 | .long io_return + 0x80000000, io_leave + 0x80000000 |
861 | cleanup_table_io_leave: | 901 | cleanup_table_io_leave: |
862 | .long io_leave + 0x80000000, io_done + 0x80000000 | 902 | .long io_leave + 0x80000000, io_done + 0x80000000 |
863 | cleanup_table_io_work_loop: | 903 | cleanup_table_io_work_loop: |
864 | .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000 | 904 | .long io_work_loop + 0x80000000, io_work_done + 0x80000000 |
865 | 905 | ||
866 | cleanup_critical: | 906 | cleanup_critical: |
867 | clc 4(4,%r12),BASED(cleanup_table_system_call) | 907 | clc 4(4,%r12),BASED(cleanup_table_system_call) |
@@ -930,8 +970,6 @@ cleanup_system_call: | |||
930 | cleanup_vtime: | 970 | cleanup_vtime: |
931 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) | 971 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) |
932 | bhe BASED(cleanup_stime) | 972 | bhe BASED(cleanup_stime) |
933 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | ||
934 | bz BASED(cleanup_novtime) | ||
935 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 973 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
936 | cleanup_stime: | 974 | cleanup_stime: |
937 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16) | 975 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16) |
@@ -939,7 +977,6 @@ cleanup_stime: | |||
939 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 977 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
940 | cleanup_update: | 978 | cleanup_update: |
941 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 979 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
942 | cleanup_novtime: | ||
943 | #endif | 980 | #endif |
944 | mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4) | 981 | mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4) |
945 | la %r12,__LC_RETURN_PSW | 982 | la %r12,__LC_RETURN_PSW |
@@ -978,10 +1015,10 @@ cleanup_sysc_leave: | |||
978 | 2: la %r12,__LC_RETURN_PSW | 1015 | 2: la %r12,__LC_RETURN_PSW |
979 | br %r14 | 1016 | br %r14 |
980 | cleanup_sysc_leave_insn: | 1017 | cleanup_sysc_leave_insn: |
1018 | .long sysc_done - 4 + 0x80000000 | ||
981 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 1019 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
982 | .long sysc_leave + 14 + 0x80000000 | 1020 | .long sysc_done - 8 + 0x80000000 |
983 | #endif | 1021 | #endif |
984 | .long sysc_leave + 10 + 0x80000000 | ||
985 | 1022 | ||
986 | cleanup_io_return: | 1023 | cleanup_io_return: |
987 | mvc __LC_RETURN_PSW(4),0(%r12) | 1024 | mvc __LC_RETURN_PSW(4),0(%r12) |
@@ -1008,10 +1045,10 @@ cleanup_io_leave: | |||
1008 | 2: la %r12,__LC_RETURN_PSW | 1045 | 2: la %r12,__LC_RETURN_PSW |
1009 | br %r14 | 1046 | br %r14 |
1010 | cleanup_io_leave_insn: | 1047 | cleanup_io_leave_insn: |
1048 | .long io_done - 4 + 0x80000000 | ||
1011 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 1049 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
1012 | .long io_leave + 18 + 0x80000000 | 1050 | .long io_done - 8 + 0x80000000 |
1013 | #endif | 1051 | #endif |
1014 | .long io_leave + 14 + 0x80000000 | ||
1015 | 1052 | ||
1016 | /* | 1053 | /* |
1017 | * Integer constants | 1054 | * Integer constants |
@@ -1019,7 +1056,6 @@ cleanup_io_leave_insn: | |||
1019 | .align 4 | 1056 | .align 4 |
1020 | .Lc_spsize: .long SP_SIZE | 1057 | .Lc_spsize: .long SP_SIZE |
1021 | .Lc_overhead: .long STACK_FRAME_OVERHEAD | 1058 | .Lc_overhead: .long STACK_FRAME_OVERHEAD |
1022 | .Lc_pactive: .long PREEMPT_ACTIVE | ||
1023 | .Lnr_syscalls: .long NR_syscalls | 1059 | .Lnr_syscalls: .long NR_syscalls |
1024 | .L0x018: .short 0x018 | 1060 | .L0x018: .short 0x018 |
1025 | .L0x020: .short 0x020 | 1061 | .L0x020: .short 0x020 |
@@ -1043,6 +1079,8 @@ cleanup_io_leave_insn: | |||
1043 | .Lexecve_tail: .long execve_tail | 1079 | .Lexecve_tail: .long execve_tail |
1044 | .Ljump_table: .long pgm_check_table | 1080 | .Ljump_table: .long pgm_check_table |
1045 | .Lschedule: .long schedule | 1081 | .Lschedule: .long schedule |
1082 | .Lpreempt_schedule_irq: | ||
1083 | .long preempt_schedule_irq | ||
1046 | .Ltrace: .long syscall_trace | 1084 | .Ltrace: .long syscall_trace |
1047 | .Lschedtail: .long schedule_tail | 1085 | .Lschedtail: .long schedule_tail |
1048 | .Lsysc_table: .long sys_call_table | 1086 | .Lsysc_table: .long sys_call_table |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 05e26d1fdf40..a3e47b893f07 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -67,12 +67,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ | |||
67 | brasl %r14,trace_hardirqs_off | 67 | brasl %r14,trace_hardirqs_off |
68 | .endm | 68 | .endm |
69 | 69 | ||
70 | .macro LOCKDEP_SYS_EXIT | 70 | .macro TRACE_IRQS_CHECK |
71 | brasl %r14,lockdep_sys_exit | 71 | tm SP_PSW(%r15),0x03 # irqs enabled? |
72 | jz 0f | ||
73 | brasl %r14,trace_hardirqs_on | ||
74 | j 1f | ||
75 | 0: brasl %r14,trace_hardirqs_off | ||
76 | 1: | ||
72 | .endm | 77 | .endm |
73 | #else | 78 | #else |
74 | #define TRACE_IRQS_ON | 79 | #define TRACE_IRQS_ON |
75 | #define TRACE_IRQS_OFF | 80 | #define TRACE_IRQS_OFF |
81 | #define TRACE_IRQS_CHECK | ||
82 | #endif | ||
83 | |||
84 | #ifdef CONFIG_LOCKDEP | ||
85 | .macro LOCKDEP_SYS_EXIT | ||
86 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
87 | jz 0f | ||
88 | brasl %r14,lockdep_sys_exit | ||
89 | 0: | ||
90 | .endm | ||
91 | #else | ||
76 | #define LOCKDEP_SYS_EXIT | 92 | #define LOCKDEP_SYS_EXIT |
77 | #endif | 93 | #endif |
78 | 94 | ||
@@ -222,8 +238,6 @@ sysc_saveall: | |||
222 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 238 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore |
223 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 239 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
224 | sysc_vtime: | 240 | sysc_vtime: |
225 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | ||
226 | jz sysc_do_svc | ||
227 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 241 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
228 | sysc_stime: | 242 | sysc_stime: |
229 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 243 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
@@ -257,19 +271,34 @@ sysc_noemu: | |||
257 | 271 | ||
258 | sysc_return: | 272 | sysc_return: |
259 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 273 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
260 | jno sysc_leave | 274 | jno sysc_restore |
261 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 275 | tm __TI_flags+7(%r9),_TIF_WORK_SVC |
262 | jnz sysc_work # there is work to do (signals etc.) | 276 | jnz sysc_work # there is work to do (signals etc.) |
277 | sysc_restore: | ||
278 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
279 | larl %r1,sysc_restore_trace_psw | ||
280 | lpswe 0(%r1) | ||
281 | sysc_restore_trace: | ||
282 | TRACE_IRQS_CHECK | ||
263 | LOCKDEP_SYS_EXIT | 283 | LOCKDEP_SYS_EXIT |
284 | #endif | ||
264 | sysc_leave: | 285 | sysc_leave: |
265 | RESTORE_ALL __LC_RETURN_PSW,1 | 286 | RESTORE_ALL __LC_RETURN_PSW,1 |
287 | sysc_done: | ||
288 | |||
289 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
290 | .align 8 | ||
291 | .globl sysc_restore_trace_psw | ||
292 | sysc_restore_trace_psw: | ||
293 | .quad 0, sysc_restore_trace | ||
294 | #endif | ||
266 | 295 | ||
267 | # | 296 | # |
268 | # recheck if there is more work to do | 297 | # recheck if there is more work to do |
269 | # | 298 | # |
270 | sysc_work_loop: | 299 | sysc_work_loop: |
271 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 300 | tm __TI_flags+7(%r9),_TIF_WORK_SVC |
272 | jz sysc_leave # there is no work to do | 301 | jz sysc_restore # there is no work to do |
273 | # | 302 | # |
274 | # One of the work bits is on. Find out which one. | 303 | # One of the work bits is on. Find out which one. |
275 | # | 304 | # |
@@ -284,8 +313,8 @@ sysc_work: | |||
284 | jo sysc_restart | 313 | jo sysc_restart |
285 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP | 314 | tm __TI_flags+7(%r9),_TIF_SINGLE_STEP |
286 | jo sysc_singlestep | 315 | jo sysc_singlestep |
287 | LOCKDEP_SYS_EXIT | 316 | j sysc_restore |
288 | j sysc_leave | 317 | sysc_work_done: |
289 | 318 | ||
290 | # | 319 | # |
291 | # _TIF_NEED_RESCHED is set, call schedule | 320 | # _TIF_NEED_RESCHED is set, call schedule |
@@ -445,6 +474,7 @@ pgm_check_handler: | |||
445 | pgm_no_vtime: | 474 | pgm_no_vtime: |
446 | #endif | 475 | #endif |
447 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 476 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
477 | TRACE_IRQS_OFF | ||
448 | lgf %r3,__LC_PGM_ILC # load program interruption code | 478 | lgf %r3,__LC_PGM_ILC # load program interruption code |
449 | lghi %r8,0x7f | 479 | lghi %r8,0x7f |
450 | ngr %r8,%r3 | 480 | ngr %r8,%r3 |
@@ -484,6 +514,7 @@ pgm_per_std: | |||
484 | pgm_no_vtime2: | 514 | pgm_no_vtime2: |
485 | #endif | 515 | #endif |
486 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 516 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
517 | TRACE_IRQS_OFF | ||
487 | lg %r1,__TI_task(%r9) | 518 | lg %r1,__TI_task(%r9) |
488 | tm SP_PSW+1(%r15),0x01 # kernel per event ? | 519 | tm SP_PSW+1(%r15),0x01 # kernel per event ? |
489 | jz kernel_per | 520 | jz kernel_per |
@@ -504,12 +535,9 @@ pgm_svcper: | |||
504 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 535 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
505 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 536 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
506 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 537 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
507 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | ||
508 | jz pgm_no_vtime3 | ||
509 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 538 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
510 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 539 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
511 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 540 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
512 | pgm_no_vtime3: | ||
513 | #endif | 541 | #endif |
514 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 542 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore |
515 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 543 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
@@ -529,7 +557,7 @@ kernel_per: | |||
529 | lhi %r0,__LC_PGM_OLD_PSW | 557 | lhi %r0,__LC_PGM_OLD_PSW |
530 | sth %r0,SP_TRAP(%r15) # set trap indication to pgm check | 558 | sth %r0,SP_TRAP(%r15) # set trap indication to pgm check |
531 | la %r2,SP_PTREGS(%r15) # address of register-save area | 559 | la %r2,SP_PTREGS(%r15) # address of register-save area |
532 | larl %r14,sysc_leave # load adr. of system ret, no work | 560 | larl %r14,sysc_restore # load adr. of system ret, no work |
533 | jg do_single_step # branch to do_single_step | 561 | jg do_single_step # branch to do_single_step |
534 | 562 | ||
535 | /* | 563 | /* |
@@ -554,26 +582,38 @@ io_no_vtime: | |||
554 | TRACE_IRQS_OFF | 582 | TRACE_IRQS_OFF |
555 | la %r2,SP_PTREGS(%r15) # address of register-save area | 583 | la %r2,SP_PTREGS(%r15) # address of register-save area |
556 | brasl %r14,do_IRQ # call standard irq handler | 584 | brasl %r14,do_IRQ # call standard irq handler |
557 | TRACE_IRQS_ON | ||
558 | |||
559 | io_return: | 585 | io_return: |
560 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 586 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
561 | #ifdef CONFIG_PREEMPT | 587 | #ifdef CONFIG_PREEMPT |
562 | jno io_preempt # no -> check for preemptive scheduling | 588 | jno io_preempt # no -> check for preemptive scheduling |
563 | #else | 589 | #else |
564 | jno io_leave # no-> skip resched & signal | 590 | jno io_restore # no-> skip resched & signal |
565 | #endif | 591 | #endif |
566 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 592 | tm __TI_flags+7(%r9),_TIF_WORK_INT |
567 | jnz io_work # there is work to do (signals etc.) | 593 | jnz io_work # there is work to do (signals etc.) |
594 | io_restore: | ||
595 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
596 | larl %r1,io_restore_trace_psw | ||
597 | lpswe 0(%r1) | ||
598 | io_restore_trace: | ||
599 | TRACE_IRQS_CHECK | ||
568 | LOCKDEP_SYS_EXIT | 600 | LOCKDEP_SYS_EXIT |
601 | #endif | ||
569 | io_leave: | 602 | io_leave: |
570 | RESTORE_ALL __LC_RETURN_PSW,0 | 603 | RESTORE_ALL __LC_RETURN_PSW,0 |
571 | io_done: | 604 | io_done: |
572 | 605 | ||
606 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
607 | .align 8 | ||
608 | .globl io_restore_trace_psw | ||
609 | io_restore_trace_psw: | ||
610 | .quad 0, io_restore_trace | ||
611 | #endif | ||
612 | |||
573 | #ifdef CONFIG_PREEMPT | 613 | #ifdef CONFIG_PREEMPT |
574 | io_preempt: | 614 | io_preempt: |
575 | icm %r0,15,__TI_precount(%r9) | 615 | icm %r0,15,__TI_precount(%r9) |
576 | jnz io_leave | 616 | jnz io_restore |
577 | # switch to kernel stack | 617 | # switch to kernel stack |
578 | lg %r1,SP_R15(%r15) | 618 | lg %r1,SP_R15(%r15) |
579 | aghi %r1,-SP_SIZE | 619 | aghi %r1,-SP_SIZE |
@@ -582,14 +622,9 @@ io_preempt: | |||
582 | lgr %r15,%r1 | 622 | lgr %r15,%r1 |
583 | io_resume_loop: | 623 | io_resume_loop: |
584 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 624 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED |
585 | jno io_leave | 625 | jno io_restore |
586 | larl %r1,.Lc_pactive | 626 | larl %r14,io_resume_loop |
587 | mvc __TI_precount(4,%r9),0(%r1) | 627 | jg preempt_schedule_irq |
588 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | ||
589 | brasl %r14,schedule # call schedule | ||
590 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | ||
591 | xc __TI_precount(4,%r9),__TI_precount(%r9) | ||
592 | j io_resume_loop | ||
593 | #endif | 628 | #endif |
594 | 629 | ||
595 | # | 630 | # |
@@ -613,37 +648,39 @@ io_work_loop: | |||
613 | jo io_reschedule | 648 | jo io_reschedule |
614 | tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) | 649 | tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) |
615 | jnz io_sigpending | 650 | jnz io_sigpending |
616 | LOCKDEP_SYS_EXIT | 651 | j io_restore |
617 | j io_leave | 652 | io_work_done: |
618 | 653 | ||
619 | # | 654 | # |
620 | # _TIF_MCCK_PENDING is set, call handler | 655 | # _TIF_MCCK_PENDING is set, call handler |
621 | # | 656 | # |
622 | io_mcck_pending: | 657 | io_mcck_pending: |
623 | TRACE_IRQS_OFF | ||
624 | brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler | 658 | brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler |
625 | TRACE_IRQS_ON | ||
626 | j io_work_loop | 659 | j io_work_loop |
627 | 660 | ||
628 | # | 661 | # |
629 | # _TIF_NEED_RESCHED is set, call schedule | 662 | # _TIF_NEED_RESCHED is set, call schedule |
630 | # | 663 | # |
631 | io_reschedule: | 664 | io_reschedule: |
665 | TRACE_IRQS_ON | ||
632 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 666 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
633 | brasl %r14,schedule # call scheduler | 667 | brasl %r14,schedule # call scheduler |
634 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 668 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
669 | TRACE_IRQS_OFF | ||
635 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 670 | tm __TI_flags+7(%r9),_TIF_WORK_INT |
636 | jz io_leave # there is no work to do | 671 | jz io_restore # there is no work to do |
637 | j io_work_loop | 672 | j io_work_loop |
638 | 673 | ||
639 | # | 674 | # |
640 | # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal | 675 | # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal |
641 | # | 676 | # |
642 | io_sigpending: | 677 | io_sigpending: |
678 | TRACE_IRQS_ON | ||
643 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 679 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
644 | la %r2,SP_PTREGS(%r15) # load pt_regs | 680 | la %r2,SP_PTREGS(%r15) # load pt_regs |
645 | brasl %r14,do_signal # call do_signal | 681 | brasl %r14,do_signal # call do_signal |
646 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts | 682 | stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts |
683 | TRACE_IRQS_OFF | ||
647 | j io_work_loop | 684 | j io_work_loop |
648 | 685 | ||
649 | /* | 686 | /* |
@@ -669,7 +706,6 @@ ext_no_vtime: | |||
669 | la %r2,SP_PTREGS(%r15) # address of register-save area | 706 | la %r2,SP_PTREGS(%r15) # address of register-save area |
670 | llgh %r3,__LC_EXT_INT_CODE # get interruption code | 707 | llgh %r3,__LC_EXT_INT_CODE # get interruption code |
671 | brasl %r14,do_extint | 708 | brasl %r14,do_extint |
672 | TRACE_IRQS_ON | ||
673 | j io_return | 709 | j io_return |
674 | 710 | ||
675 | __critical_end: | 711 | __critical_end: |
@@ -824,15 +860,15 @@ cleanup_table_system_call: | |||
824 | cleanup_table_sysc_return: | 860 | cleanup_table_sysc_return: |
825 | .quad sysc_return, sysc_leave | 861 | .quad sysc_return, sysc_leave |
826 | cleanup_table_sysc_leave: | 862 | cleanup_table_sysc_leave: |
827 | .quad sysc_leave, sysc_work_loop | 863 | .quad sysc_leave, sysc_done |
828 | cleanup_table_sysc_work_loop: | 864 | cleanup_table_sysc_work_loop: |
829 | .quad sysc_work_loop, sysc_reschedule | 865 | .quad sysc_work_loop, sysc_work_done |
830 | cleanup_table_io_return: | 866 | cleanup_table_io_return: |
831 | .quad io_return, io_leave | 867 | .quad io_return, io_leave |
832 | cleanup_table_io_leave: | 868 | cleanup_table_io_leave: |
833 | .quad io_leave, io_done | 869 | .quad io_leave, io_done |
834 | cleanup_table_io_work_loop: | 870 | cleanup_table_io_work_loop: |
835 | .quad io_work_loop, io_mcck_pending | 871 | .quad io_work_loop, io_work_done |
836 | 872 | ||
837 | cleanup_critical: | 873 | cleanup_critical: |
838 | clc 8(8,%r12),BASED(cleanup_table_system_call) | 874 | clc 8(8,%r12),BASED(cleanup_table_system_call) |
@@ -901,8 +937,6 @@ cleanup_system_call: | |||
901 | cleanup_vtime: | 937 | cleanup_vtime: |
902 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) | 938 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) |
903 | jhe cleanup_stime | 939 | jhe cleanup_stime |
904 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | ||
905 | jz cleanup_novtime | ||
906 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER | 940 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER |
907 | cleanup_stime: | 941 | cleanup_stime: |
908 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32) | 942 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32) |
@@ -910,7 +944,6 @@ cleanup_stime: | |||
910 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 944 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
911 | cleanup_update: | 945 | cleanup_update: |
912 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | 946 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER |
913 | cleanup_novtime: | ||
914 | #endif | 947 | #endif |
915 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) | 948 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) |
916 | la %r12,__LC_RETURN_PSW | 949 | la %r12,__LC_RETURN_PSW |
@@ -949,10 +982,10 @@ cleanup_sysc_leave: | |||
949 | 2: la %r12,__LC_RETURN_PSW | 982 | 2: la %r12,__LC_RETURN_PSW |
950 | br %r14 | 983 | br %r14 |
951 | cleanup_sysc_leave_insn: | 984 | cleanup_sysc_leave_insn: |
985 | .quad sysc_done - 4 | ||
952 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 986 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
953 | .quad sysc_leave + 16 | 987 | .quad sysc_done - 8 |
954 | #endif | 988 | #endif |
955 | .quad sysc_leave + 12 | ||
956 | 989 | ||
957 | cleanup_io_return: | 990 | cleanup_io_return: |
958 | mvc __LC_RETURN_PSW(8),0(%r12) | 991 | mvc __LC_RETURN_PSW(8),0(%r12) |
@@ -979,17 +1012,16 @@ cleanup_io_leave: | |||
979 | 2: la %r12,__LC_RETURN_PSW | 1012 | 2: la %r12,__LC_RETURN_PSW |
980 | br %r14 | 1013 | br %r14 |
981 | cleanup_io_leave_insn: | 1014 | cleanup_io_leave_insn: |
1015 | .quad io_done - 4 | ||
982 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 1016 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
983 | .quad io_leave + 20 | 1017 | .quad io_done - 8 |
984 | #endif | 1018 | #endif |
985 | .quad io_leave + 16 | ||
986 | 1019 | ||
987 | /* | 1020 | /* |
988 | * Integer constants | 1021 | * Integer constants |
989 | */ | 1022 | */ |
990 | .align 4 | 1023 | .align 4 |
991 | .Lconst: | 1024 | .Lconst: |
992 | .Lc_pactive: .long PREEMPT_ACTIVE | ||
993 | .Lnr_syscalls: .long NR_syscalls | 1025 | .Lnr_syscalls: .long NR_syscalls |
994 | .L0x0130: .short 0x130 | 1026 | .L0x0130: .short 0x130 |
995 | .L0x0140: .short 0x140 | 1027 | .L0x0140: .short 0x140 |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 7e1bfb984064..50f8f1e3760e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -347,7 +347,7 @@ void (*_machine_power_off)(void) = do_machine_power_off_nonsmp; | |||
347 | 347 | ||
348 | void machine_restart(char *command) | 348 | void machine_restart(char *command) |
349 | { | 349 | { |
350 | if (!in_interrupt() || oops_in_progress) | 350 | if ((!in_interrupt() && !in_atomic()) || oops_in_progress) |
351 | /* | 351 | /* |
352 | * Only unblank the console if we are called in enabled | 352 | * Only unblank the console if we are called in enabled |
353 | * context or a bust_spinlocks cleared the way for us. | 353 | * context or a bust_spinlocks cleared the way for us. |
@@ -492,6 +492,10 @@ static void setup_addressing_mode(void) | |||
492 | printk("S390 address spaces switched, "); | 492 | printk("S390 address spaces switched, "); |
493 | set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY); | 493 | set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY); |
494 | } | 494 | } |
495 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
496 | sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; | ||
497 | io_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; | ||
498 | #endif | ||
495 | } | 499 | } |
496 | 500 | ||
497 | static void __init | 501 | static void __init |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b05ae8584258..264ea906db4c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -193,72 +193,30 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
193 | } | 193 | } |
194 | EXPORT_SYMBOL(smp_call_function_single); | 194 | EXPORT_SYMBOL(smp_call_function_single); |
195 | 195 | ||
196 | static void do_send_stop(void) | 196 | void smp_send_stop(void) |
197 | { | 197 | { |
198 | int cpu, rc; | 198 | int cpu, rc; |
199 | 199 | ||
200 | /* stop all processors */ | 200 | /* Disable all interrupts/machine checks */ |
201 | for_each_online_cpu(cpu) { | 201 | __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); |
202 | if (cpu == smp_processor_id()) | ||
203 | continue; | ||
204 | do { | ||
205 | rc = signal_processor(cpu, sigp_stop); | ||
206 | } while (rc == sigp_busy); | ||
207 | } | ||
208 | } | ||
209 | 202 | ||
210 | static void do_store_status(void) | 203 | /* write magic number to zero page (absolute 0) */ |
211 | { | 204 | lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; |
212 | int cpu, rc; | ||
213 | 205 | ||
214 | /* store status of all processors in their lowcores (real 0) */ | 206 | /* stop all processors */ |
215 | for_each_online_cpu(cpu) { | 207 | for_each_online_cpu(cpu) { |
216 | if (cpu == smp_processor_id()) | 208 | if (cpu == smp_processor_id()) |
217 | continue; | 209 | continue; |
218 | do { | 210 | do { |
219 | rc = signal_processor_p( | 211 | rc = signal_processor(cpu, sigp_stop); |
220 | (__u32)(unsigned long) lowcore_ptr[cpu], cpu, | ||
221 | sigp_store_status_at_address); | ||
222 | } while (rc == sigp_busy); | 212 | } while (rc == sigp_busy); |
223 | } | ||
224 | } | ||
225 | 213 | ||
226 | static void do_wait_for_stop(void) | ||
227 | { | ||
228 | int cpu; | ||
229 | |||
230 | /* Wait for all other cpus to enter stopped state */ | ||
231 | for_each_online_cpu(cpu) { | ||
232 | if (cpu == smp_processor_id()) | ||
233 | continue; | ||
234 | while (!smp_cpu_not_running(cpu)) | 214 | while (!smp_cpu_not_running(cpu)) |
235 | cpu_relax(); | 215 | cpu_relax(); |
236 | } | 216 | } |
237 | } | 217 | } |
238 | 218 | ||
239 | /* | 219 | /* |
240 | * this function sends a 'stop' sigp to all other CPUs in the system. | ||
241 | * it goes straight through. | ||
242 | */ | ||
243 | void smp_send_stop(void) | ||
244 | { | ||
245 | /* Disable all interrupts/machine checks */ | ||
246 | __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); | ||
247 | |||
248 | /* write magic number to zero page (absolute 0) */ | ||
249 | lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; | ||
250 | |||
251 | /* stop other processors. */ | ||
252 | do_send_stop(); | ||
253 | |||
254 | /* wait until other processors are stopped */ | ||
255 | do_wait_for_stop(); | ||
256 | |||
257 | /* store status of other processors. */ | ||
258 | do_store_status(); | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * Reboot, halt and power_off routines for SMP. | 220 | * Reboot, halt and power_off routines for SMP. |
263 | */ | 221 | */ |
264 | void machine_restart_smp(char *__unused) | 222 | void machine_restart_smp(char *__unused) |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 8ec9def83ccb..8ed16a83fba7 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -260,6 +260,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
260 | bust_spinlocks(1); | 260 | bust_spinlocks(1); |
261 | printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); | 261 | printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); |
262 | print_modules(); | 262 | print_modules(); |
263 | notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); | ||
263 | show_regs(regs); | 264 | show_regs(regs); |
264 | bust_spinlocks(0); | 265 | bust_spinlocks(0); |
265 | add_taint(TAINT_DIE); | 266 | add_taint(TAINT_DIE); |
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index d4ed93dfb9c7..413c240cbca7 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
@@ -341,19 +341,16 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, | |||
341 | 341 | ||
342 | static struct ctl_table cmm_table[] = { | 342 | static struct ctl_table cmm_table[] = { |
343 | { | 343 | { |
344 | .ctl_name = VM_CMM_PAGES, | ||
345 | .procname = "cmm_pages", | 344 | .procname = "cmm_pages", |
346 | .mode = 0644, | 345 | .mode = 0644, |
347 | .proc_handler = &cmm_pages_handler, | 346 | .proc_handler = &cmm_pages_handler, |
348 | }, | 347 | }, |
349 | { | 348 | { |
350 | .ctl_name = VM_CMM_TIMED_PAGES, | ||
351 | .procname = "cmm_timed_pages", | 349 | .procname = "cmm_timed_pages", |
352 | .mode = 0644, | 350 | .mode = 0644, |
353 | .proc_handler = &cmm_pages_handler, | 351 | .proc_handler = &cmm_pages_handler, |
354 | }, | 352 | }, |
355 | { | 353 | { |
356 | .ctl_name = VM_CMM_TIMEOUT, | ||
357 | .procname = "cmm_timeout", | 354 | .procname = "cmm_timeout", |
358 | .mode = 0644, | 355 | .mode = 0644, |
359 | .proc_handler = &cmm_timeout_handler, | 356 | .proc_handler = &cmm_timeout_handler, |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 838f7ac0dc32..6db31089d2d7 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -483,7 +483,7 @@ static DECLARE_WORK(css_reprobe_work, reprobe_all); | |||
483 | void css_schedule_reprobe(void) | 483 | void css_schedule_reprobe(void) |
484 | { | 484 | { |
485 | need_reprobe = 1; | 485 | need_reprobe = 1; |
486 | queue_work(ccw_device_work, &css_reprobe_work); | 486 | queue_work(slow_path_wq, &css_reprobe_work); |
487 | } | 487 | } |
488 | 488 | ||
489 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); | 489 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8867443b8060..bfad421cda66 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -1034,7 +1034,7 @@ device_trigger_reprobe(struct subchannel *sch) | |||
1034 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { | 1034 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { |
1035 | PREPARE_WORK(&cdev->private->kick_work, | 1035 | PREPARE_WORK(&cdev->private->kick_work, |
1036 | ccw_device_move_to_orphanage); | 1036 | ccw_device_move_to_orphanage); |
1037 | queue_work(ccw_device_work, &cdev->private->kick_work); | 1037 | queue_work(slow_path_wq, &cdev->private->kick_work); |
1038 | } else | 1038 | } else |
1039 | ccw_device_start_id(cdev, 0); | 1039 | ccw_device_start_id(cdev, 0); |
1040 | } | 1040 | } |
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index f232832f2b22..2f6bf462425e 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c | |||
@@ -113,19 +113,10 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) | |||
113 | { | 113 | { |
114 | struct subchannel *sch; | 114 | struct subchannel *sch; |
115 | struct ccw1 *ccw; | 115 | struct ccw1 *ccw; |
116 | int ret; | ||
117 | 116 | ||
118 | sch = to_subchannel(cdev->dev.parent); | 117 | sch = to_subchannel(cdev->dev.parent); |
119 | /* Setup sense channel program. */ | 118 | /* Setup sense channel program. */ |
120 | ccw = cdev->private->iccws; | 119 | ccw = cdev->private->iccws; |
121 | if (sch->schib.pmcw.pim != 0x80) { | ||
122 | /* more than one path installed. */ | ||
123 | ccw->cmd_code = CCW_CMD_SUSPEND_RECONN; | ||
124 | ccw->cda = 0; | ||
125 | ccw->count = 0; | ||
126 | ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC; | ||
127 | ccw++; | ||
128 | } | ||
129 | ccw->cmd_code = CCW_CMD_SENSE_ID; | 120 | ccw->cmd_code = CCW_CMD_SENSE_ID; |
130 | ccw->cda = (__u32) __pa (&cdev->private->senseid); | 121 | ccw->cda = (__u32) __pa (&cdev->private->senseid); |
131 | ccw->count = sizeof (struct senseid); | 122 | ccw->count = sizeof (struct senseid); |
@@ -133,25 +124,9 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) | |||
133 | 124 | ||
134 | /* Reset device status. */ | 125 | /* Reset device status. */ |
135 | memset(&cdev->private->irb, 0, sizeof(struct irb)); | 126 | memset(&cdev->private->irb, 0, sizeof(struct irb)); |
127 | cdev->private->flags.intretry = 0; | ||
136 | 128 | ||
137 | /* Try on every path. */ | 129 | return cio_start(sch, ccw, LPM_ANYPATH); |
138 | ret = -ENODEV; | ||
139 | while (cdev->private->imask != 0) { | ||
140 | if ((sch->opm & cdev->private->imask) != 0 && | ||
141 | cdev->private->iretry > 0) { | ||
142 | cdev->private->iretry--; | ||
143 | /* Reset internal retry indication. */ | ||
144 | cdev->private->flags.intretry = 0; | ||
145 | ret = cio_start (sch, cdev->private->iccws, | ||
146 | cdev->private->imask); | ||
147 | /* ret is 0, -EBUSY, -EACCES or -ENODEV */ | ||
148 | if (ret != -EACCES) | ||
149 | return ret; | ||
150 | } | ||
151 | cdev->private->imask >>= 1; | ||
152 | cdev->private->iretry = 5; | ||
153 | } | ||
154 | return ret; | ||
155 | } | 130 | } |
156 | 131 | ||
157 | void | 132 | void |
@@ -161,8 +136,7 @@ ccw_device_sense_id_start(struct ccw_device *cdev) | |||
161 | 136 | ||
162 | memset (&cdev->private->senseid, 0, sizeof (struct senseid)); | 137 | memset (&cdev->private->senseid, 0, sizeof (struct senseid)); |
163 | cdev->private->senseid.cu_type = 0xFFFF; | 138 | cdev->private->senseid.cu_type = 0xFFFF; |
164 | cdev->private->imask = 0x80; | 139 | cdev->private->iretry = 3; |
165 | cdev->private->iretry = 5; | ||
166 | ret = __ccw_device_sense_id_start(cdev); | 140 | ret = __ccw_device_sense_id_start(cdev); |
167 | if (ret && ret != -EBUSY) | 141 | if (ret && ret != -EBUSY) |
168 | ccw_device_sense_id_done(cdev, ret); | 142 | ccw_device_sense_id_done(cdev, ret); |
@@ -278,14 +252,13 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
278 | ccw_device_sense_id_done(cdev, ret); | 252 | ccw_device_sense_id_done(cdev, ret); |
279 | break; | 253 | break; |
280 | case -EACCES: /* channel is not operational. */ | 254 | case -EACCES: /* channel is not operational. */ |
281 | sch->lpm &= ~cdev->private->imask; | ||
282 | cdev->private->imask >>= 1; | ||
283 | cdev->private->iretry = 5; | ||
284 | /* fall through. */ | ||
285 | case -EAGAIN: /* try again. */ | 255 | case -EAGAIN: /* try again. */ |
286 | ret = __ccw_device_sense_id_start(cdev); | 256 | cdev->private->iretry--; |
287 | if (ret == 0 || ret == -EBUSY) | 257 | if (cdev->private->iretry > 0) { |
288 | break; | 258 | ret = __ccw_device_sense_id_start(cdev); |
259 | if (ret == 0 || ret == -EBUSY) | ||
260 | break; | ||
261 | } | ||
289 | /* fall through. */ | 262 | /* fall through. */ |
290 | default: /* Sense ID failed. Try asking VM. */ | 263 | default: /* Sense ID failed. Try asking VM. */ |
291 | if (MACHINE_IS_VM) { | 264 | if (MACHINE_IS_VM) { |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index d866d3385556..44bda786eef7 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -388,6 +388,11 @@ extern void (*_machine_power_off)(void); | |||
388 | 388 | ||
389 | #define arch_align_stack(x) (x) | 389 | #define arch_align_stack(x) (x) |
390 | 390 | ||
391 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
392 | extern psw_t sysc_restore_trace_psw; | ||
393 | extern psw_t io_restore_trace_psw; | ||
394 | #endif | ||
395 | |||
391 | #endif /* __KERNEL__ */ | 396 | #endif /* __KERNEL__ */ |
392 | 397 | ||
393 | #endif | 398 | #endif |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index e99171f01b4c..4f5047df8a9e 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -70,7 +70,6 @@ enum | |||
70 | CTL_ABI=9, /* Binary emulation */ | 70 | CTL_ABI=9, /* Binary emulation */ |
71 | CTL_CPU=10, /* CPU stuff (speed scaling, etc) */ | 71 | CTL_CPU=10, /* CPU stuff (speed scaling, etc) */ |
72 | CTL_ARLAN=254, /* arlan wireless driver */ | 72 | CTL_ARLAN=254, /* arlan wireless driver */ |
73 | CTL_APPLDATA=2120, /* s390 appldata */ | ||
74 | CTL_S390DBF=5677, /* s390 debug */ | 73 | CTL_S390DBF=5677, /* s390 debug */ |
75 | CTL_SUNRPC=7249, /* sunrpc debug */ | 74 | CTL_SUNRPC=7249, /* sunrpc debug */ |
76 | CTL_PM=9899, /* frv power management */ | 75 | CTL_PM=9899, /* frv power management */ |
@@ -207,11 +206,6 @@ enum | |||
207 | VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ | 206 | VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ |
208 | VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ | 207 | VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ |
209 | VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */ | 208 | VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */ |
210 | |||
211 | /* s390 vm cmm sysctls */ | ||
212 | VM_CMM_PAGES=1111, | ||
213 | VM_CMM_TIMED_PAGES=1112, | ||
214 | VM_CMM_TIMEOUT=1113, | ||
215 | }; | 209 | }; |
216 | 210 | ||
217 | 211 | ||
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index 4abc6d2306f4..8f5baac1eb08 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c | |||
@@ -140,9 +140,6 @@ static struct trans_ctl_table trans_vm_table[] = { | |||
140 | { VM_PANIC_ON_OOM, "panic_on_oom" }, | 140 | { VM_PANIC_ON_OOM, "panic_on_oom" }, |
141 | { VM_VDSO_ENABLED, "vdso_enabled" }, | 141 | { VM_VDSO_ENABLED, "vdso_enabled" }, |
142 | { VM_MIN_SLAB, "min_slab_ratio" }, | 142 | { VM_MIN_SLAB, "min_slab_ratio" }, |
143 | { VM_CMM_PAGES, "cmm_pages" }, | ||
144 | { VM_CMM_TIMED_PAGES, "cmm_timed_pages" }, | ||
145 | { VM_CMM_TIMEOUT, "cmm_timeout" }, | ||
146 | 143 | ||
147 | {} | 144 | {} |
148 | }; | 145 | }; |
@@ -1219,16 +1216,6 @@ static struct trans_ctl_table trans_arlan_table[] = { | |||
1219 | {} | 1216 | {} |
1220 | }; | 1217 | }; |
1221 | 1218 | ||
1222 | static struct trans_ctl_table trans_appldata_table[] = { | ||
1223 | { CTL_APPLDATA_TIMER, "timer" }, | ||
1224 | { CTL_APPLDATA_INTERVAL, "interval" }, | ||
1225 | { CTL_APPLDATA_OS, "os" }, | ||
1226 | { CTL_APPLDATA_NET_SUM, "net_sum" }, | ||
1227 | { CTL_APPLDATA_MEM, "mem" }, | ||
1228 | {} | ||
1229 | |||
1230 | }; | ||
1231 | |||
1232 | static struct trans_ctl_table trans_s390dbf_table[] = { | 1219 | static struct trans_ctl_table trans_s390dbf_table[] = { |
1233 | { 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" }, | 1220 | { 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" }, |
1234 | { 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" }, | 1221 | { 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" }, |
@@ -1273,7 +1260,6 @@ static struct trans_ctl_table trans_root_table[] = { | |||
1273 | { CTL_ABI, "abi" }, | 1260 | { CTL_ABI, "abi" }, |
1274 | /* CTL_CPU not used */ | 1261 | /* CTL_CPU not used */ |
1275 | { CTL_ARLAN, "arlan", trans_arlan_table }, | 1262 | { CTL_ARLAN, "arlan", trans_arlan_table }, |
1276 | { CTL_APPLDATA, "appldata", trans_appldata_table }, | ||
1277 | { CTL_S390DBF, "s390dbf", trans_s390dbf_table }, | 1263 | { CTL_S390DBF, "s390dbf", trans_s390dbf_table }, |
1278 | { CTL_SUNRPC, "sunrpc", trans_sunrpc_table }, | 1264 | { CTL_SUNRPC, "sunrpc", trans_sunrpc_table }, |
1279 | { CTL_PM, "pm", trans_pm_table }, | 1265 | { CTL_PM, "pm", trans_pm_table }, |
@@ -471,11 +471,12 @@ int page_mkclean(struct page *page) | |||
471 | 471 | ||
472 | if (page_mapped(page)) { | 472 | if (page_mapped(page)) { |
473 | struct address_space *mapping = page_mapping(page); | 473 | struct address_space *mapping = page_mapping(page); |
474 | if (mapping) | 474 | if (mapping) { |
475 | ret = page_mkclean_file(mapping, page); | 475 | ret = page_mkclean_file(mapping, page); |
476 | if (page_test_dirty(page)) { | 476 | if (page_test_dirty(page)) { |
477 | page_clear_dirty(page); | 477 | page_clear_dirty(page); |
478 | ret = 1; | 478 | ret = 1; |
479 | } | ||
479 | } | 480 | } |
480 | } | 481 | } |
481 | 482 | ||
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index a2f5a6ea3895..7698f6c459d6 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -97,7 +97,7 @@ struct iucv_irq_list { | |||
97 | struct iucv_irq_data data; | 97 | struct iucv_irq_data data; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static struct iucv_irq_data *iucv_irq_data; | 100 | static struct iucv_irq_data *iucv_irq_data[NR_CPUS]; |
101 | static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE; | 101 | static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE; |
102 | static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE; | 102 | static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE; |
103 | 103 | ||
@@ -277,7 +277,7 @@ union iucv_param { | |||
277 | /* | 277 | /* |
278 | * Anchor for per-cpu IUCV command parameter block. | 278 | * Anchor for per-cpu IUCV command parameter block. |
279 | */ | 279 | */ |
280 | static union iucv_param *iucv_param; | 280 | static union iucv_param *iucv_param[NR_CPUS]; |
281 | 281 | ||
282 | /** | 282 | /** |
283 | * iucv_call_b2f0 | 283 | * iucv_call_b2f0 |
@@ -356,7 +356,7 @@ static void iucv_allow_cpu(void *data) | |||
356 | * 0x10 - Flag to allow priority message completion interrupts | 356 | * 0x10 - Flag to allow priority message completion interrupts |
357 | * 0x08 - Flag to allow IUCV control interrupts | 357 | * 0x08 - Flag to allow IUCV control interrupts |
358 | */ | 358 | */ |
359 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 359 | parm = iucv_param[cpu]; |
360 | memset(parm, 0, sizeof(union iucv_param)); | 360 | memset(parm, 0, sizeof(union iucv_param)); |
361 | parm->set_mask.ipmask = 0xf8; | 361 | parm->set_mask.ipmask = 0xf8; |
362 | iucv_call_b2f0(IUCV_SETMASK, parm); | 362 | iucv_call_b2f0(IUCV_SETMASK, parm); |
@@ -377,7 +377,7 @@ static void iucv_block_cpu(void *data) | |||
377 | union iucv_param *parm; | 377 | union iucv_param *parm; |
378 | 378 | ||
379 | /* Disable all iucv interrupts. */ | 379 | /* Disable all iucv interrupts. */ |
380 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 380 | parm = iucv_param[cpu]; |
381 | memset(parm, 0, sizeof(union iucv_param)); | 381 | memset(parm, 0, sizeof(union iucv_param)); |
382 | iucv_call_b2f0(IUCV_SETMASK, parm); | 382 | iucv_call_b2f0(IUCV_SETMASK, parm); |
383 | 383 | ||
@@ -401,9 +401,9 @@ static void iucv_declare_cpu(void *data) | |||
401 | return; | 401 | return; |
402 | 402 | ||
403 | /* Declare interrupt buffer. */ | 403 | /* Declare interrupt buffer. */ |
404 | parm = percpu_ptr(iucv_param, cpu); | 404 | parm = iucv_param[cpu]; |
405 | memset(parm, 0, sizeof(union iucv_param)); | 405 | memset(parm, 0, sizeof(union iucv_param)); |
406 | parm->db.ipbfadr1 = virt_to_phys(percpu_ptr(iucv_irq_data, cpu)); | 406 | parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]); |
407 | rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); | 407 | rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); |
408 | if (rc) { | 408 | if (rc) { |
409 | char *err = "Unknown"; | 409 | char *err = "Unknown"; |
@@ -458,7 +458,7 @@ static void iucv_retrieve_cpu(void *data) | |||
458 | iucv_block_cpu(NULL); | 458 | iucv_block_cpu(NULL); |
459 | 459 | ||
460 | /* Retrieve interrupt buffer. */ | 460 | /* Retrieve interrupt buffer. */ |
461 | parm = percpu_ptr(iucv_param, cpu); | 461 | parm = iucv_param[cpu]; |
462 | iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); | 462 | iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); |
463 | 463 | ||
464 | /* Clear indication that an iucv buffer exists for this cpu. */ | 464 | /* Clear indication that an iucv buffer exists for this cpu. */ |
@@ -558,22 +558,23 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, | |||
558 | switch (action) { | 558 | switch (action) { |
559 | case CPU_UP_PREPARE: | 559 | case CPU_UP_PREPARE: |
560 | case CPU_UP_PREPARE_FROZEN: | 560 | case CPU_UP_PREPARE_FROZEN: |
561 | if (!percpu_populate(iucv_irq_data, | 561 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), |
562 | sizeof(struct iucv_irq_data), | 562 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); |
563 | GFP_KERNEL|GFP_DMA, cpu)) | 563 | if (!iucv_irq_data[cpu]) |
564 | return NOTIFY_BAD; | 564 | return NOTIFY_BAD; |
565 | if (!percpu_populate(iucv_param, sizeof(union iucv_param), | 565 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), |
566 | GFP_KERNEL|GFP_DMA, cpu)) { | 566 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); |
567 | percpu_depopulate(iucv_irq_data, cpu); | 567 | if (!iucv_param[cpu]) |
568 | return NOTIFY_BAD; | 568 | return NOTIFY_BAD; |
569 | } | ||
570 | break; | 569 | break; |
571 | case CPU_UP_CANCELED: | 570 | case CPU_UP_CANCELED: |
572 | case CPU_UP_CANCELED_FROZEN: | 571 | case CPU_UP_CANCELED_FROZEN: |
573 | case CPU_DEAD: | 572 | case CPU_DEAD: |
574 | case CPU_DEAD_FROZEN: | 573 | case CPU_DEAD_FROZEN: |
575 | percpu_depopulate(iucv_param, cpu); | 574 | kfree(iucv_param[cpu]); |
576 | percpu_depopulate(iucv_irq_data, cpu); | 575 | iucv_param[cpu] = NULL; |
576 | kfree(iucv_irq_data[cpu]); | ||
577 | iucv_irq_data[cpu] = NULL; | ||
577 | break; | 578 | break; |
578 | case CPU_ONLINE: | 579 | case CPU_ONLINE: |
579 | case CPU_ONLINE_FROZEN: | 580 | case CPU_ONLINE_FROZEN: |
@@ -612,7 +613,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) | |||
612 | { | 613 | { |
613 | union iucv_param *parm; | 614 | union iucv_param *parm; |
614 | 615 | ||
615 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 616 | parm = iucv_param[smp_processor_id()]; |
616 | memset(parm, 0, sizeof(union iucv_param)); | 617 | memset(parm, 0, sizeof(union iucv_param)); |
617 | if (userdata) | 618 | if (userdata) |
618 | memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); | 619 | memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); |
@@ -755,7 +756,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, | |||
755 | 756 | ||
756 | local_bh_disable(); | 757 | local_bh_disable(); |
757 | /* Prepare parameter block. */ | 758 | /* Prepare parameter block. */ |
758 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 759 | parm = iucv_param[smp_processor_id()]; |
759 | memset(parm, 0, sizeof(union iucv_param)); | 760 | memset(parm, 0, sizeof(union iucv_param)); |
760 | parm->ctrl.ippathid = path->pathid; | 761 | parm->ctrl.ippathid = path->pathid; |
761 | parm->ctrl.ipmsglim = path->msglim; | 762 | parm->ctrl.ipmsglim = path->msglim; |
@@ -799,7 +800,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, | |||
799 | BUG_ON(in_atomic()); | 800 | BUG_ON(in_atomic()); |
800 | spin_lock_bh(&iucv_table_lock); | 801 | spin_lock_bh(&iucv_table_lock); |
801 | iucv_cleanup_queue(); | 802 | iucv_cleanup_queue(); |
802 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 803 | parm = iucv_param[smp_processor_id()]; |
803 | memset(parm, 0, sizeof(union iucv_param)); | 804 | memset(parm, 0, sizeof(union iucv_param)); |
804 | parm->ctrl.ipmsglim = path->msglim; | 805 | parm->ctrl.ipmsglim = path->msglim; |
805 | parm->ctrl.ipflags1 = path->flags; | 806 | parm->ctrl.ipflags1 = path->flags; |
@@ -854,7 +855,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]) | |||
854 | int rc; | 855 | int rc; |
855 | 856 | ||
856 | local_bh_disable(); | 857 | local_bh_disable(); |
857 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 858 | parm = iucv_param[smp_processor_id()]; |
858 | memset(parm, 0, sizeof(union iucv_param)); | 859 | memset(parm, 0, sizeof(union iucv_param)); |
859 | if (userdata) | 860 | if (userdata) |
860 | memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); | 861 | memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); |
@@ -881,7 +882,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16]) | |||
881 | int rc; | 882 | int rc; |
882 | 883 | ||
883 | local_bh_disable(); | 884 | local_bh_disable(); |
884 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 885 | parm = iucv_param[smp_processor_id()]; |
885 | memset(parm, 0, sizeof(union iucv_param)); | 886 | memset(parm, 0, sizeof(union iucv_param)); |
886 | if (userdata) | 887 | if (userdata) |
887 | memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); | 888 | memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); |
@@ -936,7 +937,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg, | |||
936 | int rc; | 937 | int rc; |
937 | 938 | ||
938 | local_bh_disable(); | 939 | local_bh_disable(); |
939 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 940 | parm = iucv_param[smp_processor_id()]; |
940 | memset(parm, 0, sizeof(union iucv_param)); | 941 | memset(parm, 0, sizeof(union iucv_param)); |
941 | parm->purge.ippathid = path->pathid; | 942 | parm->purge.ippathid = path->pathid; |
942 | parm->purge.ipmsgid = msg->id; | 943 | parm->purge.ipmsgid = msg->id; |
@@ -1003,7 +1004,7 @@ int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, | |||
1003 | } | 1004 | } |
1004 | 1005 | ||
1005 | local_bh_disable(); | 1006 | local_bh_disable(); |
1006 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 1007 | parm = iucv_param[smp_processor_id()]; |
1007 | memset(parm, 0, sizeof(union iucv_param)); | 1008 | memset(parm, 0, sizeof(union iucv_param)); |
1008 | parm->db.ipbfadr1 = (u32)(addr_t) buffer; | 1009 | parm->db.ipbfadr1 = (u32)(addr_t) buffer; |
1009 | parm->db.ipbfln1f = (u32) size; | 1010 | parm->db.ipbfln1f = (u32) size; |
@@ -1040,7 +1041,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg) | |||
1040 | int rc; | 1041 | int rc; |
1041 | 1042 | ||
1042 | local_bh_disable(); | 1043 | local_bh_disable(); |
1043 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 1044 | parm = iucv_param[smp_processor_id()]; |
1044 | memset(parm, 0, sizeof(union iucv_param)); | 1045 | memset(parm, 0, sizeof(union iucv_param)); |
1045 | parm->db.ippathid = path->pathid; | 1046 | parm->db.ippathid = path->pathid; |
1046 | parm->db.ipmsgid = msg->id; | 1047 | parm->db.ipmsgid = msg->id; |
@@ -1074,7 +1075,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg, | |||
1074 | int rc; | 1075 | int rc; |
1075 | 1076 | ||
1076 | local_bh_disable(); | 1077 | local_bh_disable(); |
1077 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 1078 | parm = iucv_param[smp_processor_id()]; |
1078 | memset(parm, 0, sizeof(union iucv_param)); | 1079 | memset(parm, 0, sizeof(union iucv_param)); |
1079 | if (flags & IUCV_IPRMDATA) { | 1080 | if (flags & IUCV_IPRMDATA) { |
1080 | parm->dpl.ippathid = path->pathid; | 1081 | parm->dpl.ippathid = path->pathid; |
@@ -1118,7 +1119,7 @@ int iucv_message_send(struct iucv_path *path, struct iucv_message *msg, | |||
1118 | int rc; | 1119 | int rc; |
1119 | 1120 | ||
1120 | local_bh_disable(); | 1121 | local_bh_disable(); |
1121 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 1122 | parm = iucv_param[smp_processor_id()]; |
1122 | memset(parm, 0, sizeof(union iucv_param)); | 1123 | memset(parm, 0, sizeof(union iucv_param)); |
1123 | if (flags & IUCV_IPRMDATA) { | 1124 | if (flags & IUCV_IPRMDATA) { |
1124 | /* Message of 8 bytes can be placed into the parameter list. */ | 1125 | /* Message of 8 bytes can be placed into the parameter list. */ |
@@ -1172,7 +1173,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg, | |||
1172 | int rc; | 1173 | int rc; |
1173 | 1174 | ||
1174 | local_bh_disable(); | 1175 | local_bh_disable(); |
1175 | parm = percpu_ptr(iucv_param, smp_processor_id()); | 1176 | parm = iucv_param[smp_processor_id()]; |
1176 | memset(parm, 0, sizeof(union iucv_param)); | 1177 | memset(parm, 0, sizeof(union iucv_param)); |
1177 | if (flags & IUCV_IPRMDATA) { | 1178 | if (flags & IUCV_IPRMDATA) { |
1178 | parm->dpl.ippathid = path->pathid; | 1179 | parm->dpl.ippathid = path->pathid; |
@@ -1559,7 +1560,7 @@ static void iucv_external_interrupt(u16 code) | |||
1559 | struct iucv_irq_data *p; | 1560 | struct iucv_irq_data *p; |
1560 | struct iucv_irq_list *work; | 1561 | struct iucv_irq_list *work; |
1561 | 1562 | ||
1562 | p = percpu_ptr(iucv_irq_data, smp_processor_id()); | 1563 | p = iucv_irq_data[smp_processor_id()]; |
1563 | if (p->ippathid >= iucv_max_pathid) { | 1564 | if (p->ippathid >= iucv_max_pathid) { |
1564 | printk(KERN_WARNING "iucv_do_int: Got interrupt with " | 1565 | printk(KERN_WARNING "iucv_do_int: Got interrupt with " |
1565 | "pathid %d > max_connections (%ld)\n", | 1566 | "pathid %d > max_connections (%ld)\n", |
@@ -1598,6 +1599,7 @@ static void iucv_external_interrupt(u16 code) | |||
1598 | static int __init iucv_init(void) | 1599 | static int __init iucv_init(void) |
1599 | { | 1600 | { |
1600 | int rc; | 1601 | int rc; |
1602 | int cpu; | ||
1601 | 1603 | ||
1602 | if (!MACHINE_IS_VM) { | 1604 | if (!MACHINE_IS_VM) { |
1603 | rc = -EPROTONOSUPPORT; | 1605 | rc = -EPROTONOSUPPORT; |
@@ -1617,19 +1619,23 @@ static int __init iucv_init(void) | |||
1617 | rc = PTR_ERR(iucv_root); | 1619 | rc = PTR_ERR(iucv_root); |
1618 | goto out_bus; | 1620 | goto out_bus; |
1619 | } | 1621 | } |
1620 | /* Note: GFP_DMA used to get memory below 2G */ | 1622 | |
1621 | iucv_irq_data = percpu_alloc(sizeof(struct iucv_irq_data), | 1623 | for_each_online_cpu(cpu) { |
1622 | GFP_KERNEL|GFP_DMA); | 1624 | /* Note: GFP_DMA used to get memory below 2G */ |
1623 | if (!iucv_irq_data) { | 1625 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), |
1624 | rc = -ENOMEM; | 1626 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); |
1625 | goto out_root; | 1627 | if (!iucv_irq_data[cpu]) { |
1626 | } | 1628 | rc = -ENOMEM; |
1627 | /* Allocate parameter blocks. */ | 1629 | goto out_free; |
1628 | iucv_param = percpu_alloc(sizeof(union iucv_param), | 1630 | } |
1629 | GFP_KERNEL|GFP_DMA); | 1631 | |
1630 | if (!iucv_param) { | 1632 | /* Allocate parameter blocks. */ |
1631 | rc = -ENOMEM; | 1633 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), |
1632 | goto out_extint; | 1634 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); |
1635 | if (!iucv_param[cpu]) { | ||
1636 | rc = -ENOMEM; | ||
1637 | goto out_free; | ||
1638 | } | ||
1633 | } | 1639 | } |
1634 | register_hotcpu_notifier(&iucv_cpu_notifier); | 1640 | register_hotcpu_notifier(&iucv_cpu_notifier); |
1635 | ASCEBC(iucv_error_no_listener, 16); | 1641 | ASCEBC(iucv_error_no_listener, 16); |
@@ -1638,9 +1644,13 @@ static int __init iucv_init(void) | |||
1638 | iucv_available = 1; | 1644 | iucv_available = 1; |
1639 | return 0; | 1645 | return 0; |
1640 | 1646 | ||
1641 | out_extint: | 1647 | out_free: |
1642 | percpu_free(iucv_irq_data); | 1648 | for_each_possible_cpu(cpu) { |
1643 | out_root: | 1649 | kfree(iucv_param[cpu]); |
1650 | iucv_param[cpu] = NULL; | ||
1651 | kfree(iucv_irq_data[cpu]); | ||
1652 | iucv_irq_data[cpu] = NULL; | ||
1653 | } | ||
1644 | s390_root_dev_unregister(iucv_root); | 1654 | s390_root_dev_unregister(iucv_root); |
1645 | out_bus: | 1655 | out_bus: |
1646 | bus_unregister(&iucv_bus); | 1656 | bus_unregister(&iucv_bus); |
@@ -1658,6 +1668,7 @@ out: | |||
1658 | static void __exit iucv_exit(void) | 1668 | static void __exit iucv_exit(void) |
1659 | { | 1669 | { |
1660 | struct iucv_irq_list *p, *n; | 1670 | struct iucv_irq_list *p, *n; |
1671 | int cpu; | ||
1661 | 1672 | ||
1662 | spin_lock_irq(&iucv_queue_lock); | 1673 | spin_lock_irq(&iucv_queue_lock); |
1663 | list_for_each_entry_safe(p, n, &iucv_task_queue, list) | 1674 | list_for_each_entry_safe(p, n, &iucv_task_queue, list) |
@@ -1666,8 +1677,12 @@ static void __exit iucv_exit(void) | |||
1666 | kfree(p); | 1677 | kfree(p); |
1667 | spin_unlock_irq(&iucv_queue_lock); | 1678 | spin_unlock_irq(&iucv_queue_lock); |
1668 | unregister_hotcpu_notifier(&iucv_cpu_notifier); | 1679 | unregister_hotcpu_notifier(&iucv_cpu_notifier); |
1669 | percpu_free(iucv_param); | 1680 | for_each_possible_cpu(cpu) { |
1670 | percpu_free(iucv_irq_data); | 1681 | kfree(iucv_param[cpu]); |
1682 | iucv_param[cpu] = NULL; | ||
1683 | kfree(iucv_irq_data[cpu]); | ||
1684 | iucv_irq_data[cpu] = NULL; | ||
1685 | } | ||
1671 | s390_root_dev_unregister(iucv_root); | 1686 | s390_root_dev_unregister(iucv_root); |
1672 | bus_unregister(&iucv_bus); | 1687 | bus_unregister(&iucv_bus); |
1673 | unregister_external_interrupt(0x4000, iucv_external_interrupt); | 1688 | unregister_external_interrupt(0x4000, iucv_external_interrupt); |