diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-26 22:09:22 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-26 22:09:22 -0500 |
| commit | 9ccc236269c1a838b58148c94ac0eeeca885b836 (patch) | |
| tree | fbe9c922a21da9e949ecad1fd6eb39420aa58c2a | |
| parent | da457d4b93f9d746b0afd4aa65c94759f190d642 (diff) | |
| parent | c5d4a9997b4b2ec71cff0b219f05c6bc51f3fc79 (diff) | |
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[S390] cio: Register/unregister subchannels only from kslowcrw.
[S390] Add missing die_notifier() call to die().
[S390] Fix memory detection.
[S390] Explicitly code allocpercpu calls in iucv
[S390] Dont overwrite lowcores on smp_send_stop().
[S390] Optimize storage key handling for anonymous pages
[S390] Fix kernel preemption.
[S390] appldata: remove unused binary sysctls.
[S390] cmm: remove unused binary sysctls.
[S390] Fix irq tracing and lockdep_sys_exit calls.
[S390] magic sysrq: check for in_atomic before doing an console_unblank
[S390] cio: change device sense procedure to work with pav aliases
| -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); |
