diff options
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r-- | arch/s390/kernel/ipl.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 4d73296fed74..a689070be287 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/reboot.h> | 15 | #include <linux/reboot.h> |
16 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/gfp.h> | ||
18 | #include <asm/ipl.h> | 19 | #include <asm/ipl.h> |
19 | #include <asm/smp.h> | 20 | #include <asm/smp.h> |
20 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
@@ -402,8 +403,9 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj, | |||
402 | static struct kobj_attribute sys_ipl_device_attr = | 403 | static struct kobj_attribute sys_ipl_device_attr = |
403 | __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL); | 404 | __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL); |
404 | 405 | ||
405 | static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr, | 406 | static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj, |
406 | char *buf, loff_t off, size_t count) | 407 | struct bin_attribute *attr, char *buf, |
408 | loff_t off, size_t count) | ||
407 | { | 409 | { |
408 | return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START, | 410 | return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START, |
409 | IPL_PARMBLOCK_SIZE); | 411 | IPL_PARMBLOCK_SIZE); |
@@ -418,8 +420,9 @@ static struct bin_attribute ipl_parameter_attr = { | |||
418 | .read = &ipl_parameter_read, | 420 | .read = &ipl_parameter_read, |
419 | }; | 421 | }; |
420 | 422 | ||
421 | static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr, | 423 | static ssize_t ipl_scp_data_read(struct file *filp, struct kobject *kobj, |
422 | char *buf, loff_t off, size_t count) | 424 | struct bin_attribute *attr, char *buf, |
425 | loff_t off, size_t count) | ||
423 | { | 426 | { |
424 | unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len; | 427 | unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len; |
425 | void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data; | 428 | void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data; |
@@ -553,7 +556,7 @@ out: | |||
553 | return rc; | 556 | return rc; |
554 | } | 557 | } |
555 | 558 | ||
556 | static void ipl_run(struct shutdown_trigger *trigger) | 559 | static void __ipl_run(void *unused) |
557 | { | 560 | { |
558 | diag308(DIAG308_IPL, NULL); | 561 | diag308(DIAG308_IPL, NULL); |
559 | if (MACHINE_IS_VM) | 562 | if (MACHINE_IS_VM) |
@@ -562,6 +565,11 @@ static void ipl_run(struct shutdown_trigger *trigger) | |||
562 | reipl_ccw_dev(&ipl_info.data.ccw.dev_id); | 565 | reipl_ccw_dev(&ipl_info.data.ccw.dev_id); |
563 | } | 566 | } |
564 | 567 | ||
568 | static void ipl_run(struct shutdown_trigger *trigger) | ||
569 | { | ||
570 | smp_switch_to_ipl_cpu(__ipl_run, NULL); | ||
571 | } | ||
572 | |||
565 | static int __init ipl_init(void) | 573 | static int __init ipl_init(void) |
566 | { | 574 | { |
567 | int rc; | 575 | int rc; |
@@ -688,7 +696,7 @@ static struct kobj_attribute sys_reipl_ccw_vmparm_attr = | |||
688 | 696 | ||
689 | /* FCP reipl device attributes */ | 697 | /* FCP reipl device attributes */ |
690 | 698 | ||
691 | static ssize_t reipl_fcp_scpdata_read(struct kobject *kobj, | 699 | static ssize_t reipl_fcp_scpdata_read(struct file *filp, struct kobject *kobj, |
692 | struct bin_attribute *attr, | 700 | struct bin_attribute *attr, |
693 | char *buf, loff_t off, size_t count) | 701 | char *buf, loff_t off, size_t count) |
694 | { | 702 | { |
@@ -698,7 +706,7 @@ static ssize_t reipl_fcp_scpdata_read(struct kobject *kobj, | |||
698 | return memory_read_from_buffer(buf, count, &off, scp_data, size); | 706 | return memory_read_from_buffer(buf, count, &off, scp_data, size); |
699 | } | 707 | } |
700 | 708 | ||
701 | static ssize_t reipl_fcp_scpdata_write(struct kobject *kobj, | 709 | static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj, |
702 | struct bin_attribute *attr, | 710 | struct bin_attribute *attr, |
703 | char *buf, loff_t off, size_t count) | 711 | char *buf, loff_t off, size_t count) |
704 | { | 712 | { |
@@ -1039,7 +1047,7 @@ static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb, | |||
1039 | sprintf(dst + pos, " PARM %s", vmparm); | 1047 | sprintf(dst + pos, " PARM %s", vmparm); |
1040 | } | 1048 | } |
1041 | 1049 | ||
1042 | static void reipl_run(struct shutdown_trigger *trigger) | 1050 | static void __reipl_run(void *unused) |
1043 | { | 1051 | { |
1044 | struct ccw_dev_id devid; | 1052 | struct ccw_dev_id devid; |
1045 | static char buf[128]; | 1053 | static char buf[128]; |
@@ -1087,6 +1095,11 @@ static void reipl_run(struct shutdown_trigger *trigger) | |||
1087 | disabled_wait((unsigned long) __builtin_return_address(0)); | 1095 | disabled_wait((unsigned long) __builtin_return_address(0)); |
1088 | } | 1096 | } |
1089 | 1097 | ||
1098 | static void reipl_run(struct shutdown_trigger *trigger) | ||
1099 | { | ||
1100 | smp_switch_to_ipl_cpu(__reipl_run, NULL); | ||
1101 | } | ||
1102 | |||
1090 | static void reipl_block_ccw_init(struct ipl_parameter_block *ipb) | 1103 | static void reipl_block_ccw_init(struct ipl_parameter_block *ipb) |
1091 | { | 1104 | { |
1092 | ipb->hdr.len = IPL_PARM_BLK_CCW_LEN; | 1105 | ipb->hdr.len = IPL_PARM_BLK_CCW_LEN; |
@@ -1369,20 +1382,18 @@ static struct kobj_attribute dump_type_attr = | |||
1369 | 1382 | ||
1370 | static struct kset *dump_kset; | 1383 | static struct kset *dump_kset; |
1371 | 1384 | ||
1372 | static void dump_run(struct shutdown_trigger *trigger) | 1385 | static void __dump_run(void *unused) |
1373 | { | 1386 | { |
1374 | struct ccw_dev_id devid; | 1387 | struct ccw_dev_id devid; |
1375 | static char buf[100]; | 1388 | static char buf[100]; |
1376 | 1389 | ||
1377 | switch (dump_method) { | 1390 | switch (dump_method) { |
1378 | case DUMP_METHOD_CCW_CIO: | 1391 | case DUMP_METHOD_CCW_CIO: |
1379 | smp_send_stop(); | ||
1380 | devid.devno = dump_block_ccw->ipl_info.ccw.devno; | 1392 | devid.devno = dump_block_ccw->ipl_info.ccw.devno; |
1381 | devid.ssid = 0; | 1393 | devid.ssid = 0; |
1382 | reipl_ccw_dev(&devid); | 1394 | reipl_ccw_dev(&devid); |
1383 | break; | 1395 | break; |
1384 | case DUMP_METHOD_CCW_VM: | 1396 | case DUMP_METHOD_CCW_VM: |
1385 | smp_send_stop(); | ||
1386 | sprintf(buf, "STORE STATUS"); | 1397 | sprintf(buf, "STORE STATUS"); |
1387 | __cpcmd(buf, NULL, 0, NULL); | 1398 | __cpcmd(buf, NULL, 0, NULL); |
1388 | sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); | 1399 | sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); |
@@ -1396,10 +1407,17 @@ static void dump_run(struct shutdown_trigger *trigger) | |||
1396 | diag308(DIAG308_SET, dump_block_fcp); | 1407 | diag308(DIAG308_SET, dump_block_fcp); |
1397 | diag308(DIAG308_DUMP, NULL); | 1408 | diag308(DIAG308_DUMP, NULL); |
1398 | break; | 1409 | break; |
1399 | case DUMP_METHOD_NONE: | 1410 | default: |
1400 | return; | 1411 | break; |
1401 | } | 1412 | } |
1402 | printk(KERN_EMERG "Dump failed!\n"); | 1413 | } |
1414 | |||
1415 | static void dump_run(struct shutdown_trigger *trigger) | ||
1416 | { | ||
1417 | if (dump_method == DUMP_METHOD_NONE) | ||
1418 | return; | ||
1419 | smp_send_stop(); | ||
1420 | smp_switch_to_ipl_cpu(__dump_run, NULL); | ||
1403 | } | 1421 | } |
1404 | 1422 | ||
1405 | static int __init dump_ccw_init(void) | 1423 | static int __init dump_ccw_init(void) |
@@ -1577,7 +1595,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger) | |||
1577 | static int vmcmd_init(void) | 1595 | static int vmcmd_init(void) |
1578 | { | 1596 | { |
1579 | if (!MACHINE_IS_VM) | 1597 | if (!MACHINE_IS_VM) |
1580 | return -ENOTSUPP; | 1598 | return -EOPNOTSUPP; |
1581 | vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj); | 1599 | vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj); |
1582 | if (!vmcmd_kset) | 1600 | if (!vmcmd_kset) |
1583 | return -ENOMEM; | 1601 | return -ENOMEM; |
@@ -1595,7 +1613,7 @@ static void stop_run(struct shutdown_trigger *trigger) | |||
1595 | { | 1613 | { |
1596 | if (strcmp(trigger->name, ON_PANIC_STR) == 0) | 1614 | if (strcmp(trigger->name, ON_PANIC_STR) == 0) |
1597 | disabled_wait((unsigned long) __builtin_return_address(0)); | 1615 | disabled_wait((unsigned long) __builtin_return_address(0)); |
1598 | while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) | 1616 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) |
1599 | cpu_relax(); | 1617 | cpu_relax(); |
1600 | for (;;); | 1618 | for (;;); |
1601 | } | 1619 | } |
@@ -1902,7 +1920,6 @@ void __init ipl_update_parameters(void) | |||
1902 | void __init ipl_save_parameters(void) | 1920 | void __init ipl_save_parameters(void) |
1903 | { | 1921 | { |
1904 | struct cio_iplinfo iplinfo; | 1922 | struct cio_iplinfo iplinfo; |
1905 | unsigned int *ipl_ptr; | ||
1906 | void *src, *dst; | 1923 | void *src, *dst; |
1907 | 1924 | ||
1908 | if (cio_get_iplinfo(&iplinfo)) | 1925 | if (cio_get_iplinfo(&iplinfo)) |
@@ -1913,11 +1930,10 @@ void __init ipl_save_parameters(void) | |||
1913 | if (!iplinfo.is_qdio) | 1930 | if (!iplinfo.is_qdio) |
1914 | return; | 1931 | return; |
1915 | ipl_flags |= IPL_PARMBLOCK_VALID; | 1932 | ipl_flags |= IPL_PARMBLOCK_VALID; |
1916 | ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR; | 1933 | src = (void *)(unsigned long)S390_lowcore.ipl_parmblock_ptr; |
1917 | src = (void *)(unsigned long)*ipl_ptr; | ||
1918 | dst = (void *)IPL_PARMBLOCK_ORIGIN; | 1934 | dst = (void *)IPL_PARMBLOCK_ORIGIN; |
1919 | memmove(dst, src, PAGE_SIZE); | 1935 | memmove(dst, src, PAGE_SIZE); |
1920 | *ipl_ptr = IPL_PARMBLOCK_ORIGIN; | 1936 | S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN; |
1921 | } | 1937 | } |
1922 | 1938 | ||
1923 | static LIST_HEAD(rcall); | 1939 | static LIST_HEAD(rcall); |